module Poll ( watch ) where import System.Directory import Data.Time.Clock import Data.Time.Calendar import Control.Monad (forever) import qualified Control.Concurrent as C import System.IO.Error watch :: (String -> IO ()) -> [String] -> IO () watch fun fs = do putStrLn "starting.." -- total microseconds for each file to cause a 1 sec delay per loop let delay = 1000000 `div` (length fs) forever $ mapM_ (onDiff fun delay) fs onDiff :: (String -> IO ()) -> Int -> String -> IO () onDiff fun delay file = do modified <- errorHandler (getModificationTime file) curTime <- getCurrentTime let diff = (diffUTCTime curTime modified) if diff < 1 then fun file >> C.threadDelay delay else return () -- a really conservative check to prevent file -- "inavailability" due to reading modification bits errorHandler = errorHandlerNTimes 100 errorHandlerNTimes 0 mnd = catchIOError mnd (\e -> ioError e) errorHandlerNTimes times mnd = catchIOError mnd handle where handle e = if isDoesNotExistError e then C.threadDelay 5000 >> errorHandlerNTimes (times - 1) mnd else ioError e