module System.Delta.Callback ( CallbackWatcher
, CallbackId
, withCallbacks
, withDeleteCallback
, withChangedCallback
, withNewCallback
, unregisterCallback
, removeAllCallbacks
, closeCallbackWatcher
, callbackOnEvent
)where
import FRP.Sodium
import System.Delta.Base
import System.Delta.Class
import qualified Data.Map as M
import Control.Concurrent.MVar
newtype CallbackId = CallbackId Integer
deriving (Eq, Ord)
data CallbackWatcher where
CallbackWatcher :: {
baseWatcher :: FileWatcher
, nextCallbackId :: MVar CallbackId
, watcherCallbacks :: MVar (M.Map CallbackId (IO ()))
} -> CallbackWatcher
raiseId :: CallbackWatcher -> IO (CallbackId)
raiseId w = do
(CallbackId n) <- takeMVar $ nextCallbackId w
putMVar (nextCallbackId w) (CallbackId $ n+1)
return (CallbackId n)
addCallbackUnregister :: CallbackWatcher -> IO () -> IO CallbackId
addCallbackUnregister w removeCallback = do
newId <- raiseId w
mp <- takeMVar $ watcherCallbacks w
putMVar (watcherCallbacks w) (M.insert newId removeCallback mp)
return newId
withCallbacks :: FileWatcher -> IO CallbackWatcher
withCallbacks w = do
nextIdVar <- newMVar (CallbackId 0)
callbacks <- newMVar (M.empty)
return $ CallbackWatcher w nextIdVar callbacks
withDeleteCallback :: CallbackWatcher
-> (FilePath -> IO ())
-> IO (CallbackId)
withDeleteCallback watcher action = do
unregisterCallback <- callbackOnEvent (deletedFiles $ baseWatcher watcher) action
addCallbackUnregister watcher unregisterCallback
withNewCallback :: CallbackWatcher
-> (FilePath -> IO ())
-> IO (CallbackId)
withNewCallback watcher action = do
unregisterCallback <- callbackOnEvent (newFiles $ baseWatcher watcher) action
addCallbackUnregister watcher unregisterCallback
withChangedCallback :: CallbackWatcher
-> (FilePath -> IO ())
-> IO (CallbackId)
withChangedCallback watcher action = do
unregisterCallback <- callbackOnEvent (changedFiles $ baseWatcher watcher) action
addCallbackUnregister watcher unregisterCallback
unregisterCallback :: CallbackWatcher -> CallbackId -> IO ()
unregisterCallback watcher cId = do
mp <- takeMVar $ watcherCallbacks watcher
case M.lookup cId mp of
Nothing -> return ()
Just action -> action
putMVar (watcherCallbacks watcher) (M.delete cId mp)
removeAllCallbacks :: CallbackWatcher -> IO ()
removeAllCallbacks watcher = do
mp <- takeMVar $ watcherCallbacks watcher
putMVar (watcherCallbacks watcher) M.empty
sequence_ (M.elems mp)
closeCallbackWatcher :: CallbackWatcher -> IO ()
closeCallbackWatcher watcher = do
removeAllCallbacks watcher
cleanUpAndClose $ baseWatcher watcher
callbackOnEvent :: Event a -> (a -> IO ()) -> IO (IO ())
callbackOnEvent e action = sync $ listen e action