diff options
author | Joey Hess <joey@kitenet.net> | 2013-01-26 14:14:32 +1100 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2013-01-26 14:14:32 +1100 |
commit | 44d7913686ccfef4e6cbd0fdc2b5611aa944ec70 (patch) | |
tree | b8343b59f6730ff31fb7b88ffc11e13073d88c8e /Assistant | |
parent | 28eb1f598b1f494b6de815593fa8bfb9aaaeb250 (diff) |
use async to track and manage threads
Diffstat (limited to 'Assistant')
-rw-r--r-- | Assistant/Common.hs | 1 | ||||
-rw-r--r-- | Assistant/Monad.hs | 20 | ||||
-rw-r--r-- | Assistant/NamedThread.hs | 43 | ||||
-rw-r--r-- | Assistant/Threads/ConfigMonitor.hs | 3 | ||||
-rw-r--r-- | Assistant/Types/DaemonStatus.hs | 8 | ||||
-rw-r--r-- | Assistant/Types/NamedThread.hs | 32 |
6 files changed, 61 insertions, 46 deletions
diff --git a/Assistant/Common.hs b/Assistant/Common.hs index 0be536250..0c97bd1f7 100644 --- a/Assistant/Common.hs +++ b/Assistant/Common.hs @@ -10,4 +10,3 @@ module Assistant.Common (module X) where import Common.Annex as X import Assistant.Monad as X import Assistant.Types.DaemonStatus as X -import Assistant.Types.NamedThread as X diff --git a/Assistant/Monad.hs b/Assistant/Monad.hs index a676bc8fb..3b1eb86ec 100644 --- a/Assistant/Monad.hs +++ b/Assistant/Monad.hs @@ -19,10 +19,15 @@ module Assistant.Monad ( asIO, asIO1, asIO2, + NamedThread(..), + ThreadName, + debug, + notice ) where import "mtl" Control.Monad.Reader import Control.Monad.Base (liftBase, MonadBase) +import System.Log.Logger import Common.Annex import Assistant.Types.ThreadedMonad @@ -37,6 +42,10 @@ import Assistant.Types.Changes import Assistant.Types.Buddies import Assistant.Types.NetMessager +{- Information about a named thread that can be run. -} +data NamedThread = NamedThread ThreadName (Assistant ()) +type ThreadName = String + newtype Assistant a = Assistant { mkAssistant :: ReaderT AssistantData IO a } deriving ( Monad, @@ -118,3 +127,14 @@ asIO2 a = do {- Runs an IO action on a selected field of the AssistantData. -} (<<~) :: (a -> IO b) -> (AssistantData -> a) -> Assistant b io <<~ v = reader v >>= liftIO . io + +debug :: [String] -> Assistant () +debug = logaction debugM + +notice :: [String] -> Assistant () +notice = logaction noticeM + +logaction :: (String -> String -> IO ()) -> [String] -> Assistant () +logaction a ws = do + name <- getAssistant threadName + liftIO $ a name $ unwords $ (name ++ ":") : ws diff --git a/Assistant/NamedThread.hs b/Assistant/NamedThread.hs index 083252f94..9187448fb 100644 --- a/Assistant/NamedThread.hs +++ b/Assistant/NamedThread.hs @@ -7,19 +7,39 @@ module Assistant.NamedThread where -import Assistant.Common +import Common.Annex +import Assistant.Types.DaemonStatus import Assistant.DaemonStatus import Assistant.Alert +import Assistant.Monad -import qualified Control.Exception as E +import Control.Concurrent +import Control.Concurrent.Async +import qualified Data.Map as M -runNamedThread :: NamedThread -> Assistant () -runNamedThread (NamedThread name a) = do - d <- getAssistant id - liftIO . go $ d { threadName = name } +{- Starts a named thread, if it's not already running. + - + - Named threads are run by a management thread, so if they crash + - an alert is displayed, allowing the thread to be restarted. -} +startNamedThread :: NamedThread -> Assistant () +startNamedThread namedthread@(NamedThread name a) = do + m <- startedThreads <$> getDaemonStatus + case M.lookup name m of + Nothing -> start + Just aid -> + maybe noop (const start) =<< liftIO (poll aid) where - go d = do - r <- E.try (runAssistant d a) :: IO (Either E.SomeException ()) + start = do + d <- getAssistant id + aid <- liftIO $ runmanaged $ d { threadName = name } + modifyDaemonStatus_ $ \s -> s + { startedThreads = M.insertWith' const name aid (startedThreads s) } + runmanaged d = do + aid <- async $ runAssistant d a + void $ forkIO $ manager d aid + return aid + manager d aid = do + r <- waitCatch aid case r of Right _ -> noop Left e -> do @@ -28,3 +48,10 @@ runNamedThread (NamedThread name a) = do -- TODO click to restart runAssistant d $ void $ addAlert $ warningAlert name msg + +{- Waits for all named threads that have been started to finish. -} +waitNamedThreads :: Assistant () +waitNamedThreads = do + m <- startedThreads <$> getDaemonStatus + liftIO $ mapM_ wait $ M.elems m + diff --git a/Assistant/Threads/ConfigMonitor.hs b/Assistant/Threads/ConfigMonitor.hs index 47e197116..afa94f97f 100644 --- a/Assistant/Threads/ConfigMonitor.hs +++ b/Assistant/Threads/ConfigMonitor.hs @@ -23,9 +23,6 @@ import qualified Annex.Branch import qualified Data.Set as S -thisThread :: ThreadName -thisThread = "ConfigMonitor" - {- This thread detects when configuration changes have been made to the - git-annex branch and reloads cached configuration. - diff --git a/Assistant/Types/DaemonStatus.hs b/Assistant/Types/DaemonStatus.hs index 7f868d957..6c949c8f4 100644 --- a/Assistant/Types/DaemonStatus.hs +++ b/Assistant/Types/DaemonStatus.hs @@ -16,12 +16,15 @@ import Utility.NotificationBroadcaster import Logs.Transfer import Control.Concurrent.STM +import Control.Concurrent.Async import Data.Time.Clock.POSIX import qualified Data.Map as M data DaemonStatus = DaemonStatus + -- All the named threads that comprise the daemon. + { startedThreads :: M.Map String (Async ()) -- False when the daemon is performing its startup scan - { scanComplete :: Bool + , scanComplete :: Bool -- Time when a previous process of the daemon was running ok , lastRunning :: Maybe POSIXTime -- True when the sanity checker is running @@ -58,7 +61,8 @@ type DaemonStatusHandle = TMVar DaemonStatus newDaemonStatus :: IO DaemonStatus newDaemonStatus = DaemonStatus - <$> pure False + <$> pure M.empty + <*> pure False <*> pure Nothing <*> pure False <*> pure Nothing diff --git a/Assistant/Types/NamedThread.hs b/Assistant/Types/NamedThread.hs deleted file mode 100644 index 0e122c097..000000000 --- a/Assistant/Types/NamedThread.hs +++ /dev/null @@ -1,32 +0,0 @@ -{- git-annex assistant named threads. - - - - Copyright 2012 Joey Hess <joey@kitenet.net> - - - - Licensed under the GNU GPL version 3 or higher. - -} - -module Assistant.Types.NamedThread ( - ThreadName, - NamedThread(..), - debug, - notice, -) where - -import Common.Annex -import Assistant.Monad - -import System.Log.Logger - -type ThreadName = String -data NamedThread = NamedThread ThreadName (Assistant ()) - -debug :: [String] -> Assistant () -debug = logaction debugM - -notice :: [String] -> Assistant () -notice = logaction noticeM - -logaction :: (String -> String -> IO ()) -> [String] -> Assistant () -logaction a ws = do - name <- getAssistant threadName - liftIO $ a name $ unwords $ (name ++ ":") : ws |