packages feed

time-manager 0.3.1 → 0.3.1.1

raw patch · 5 files changed

+110/−46 lines, 5 files

Files

ChangeLog.md view
@@ -1,29 +1,37 @@ # ChangeLog for time-manager +## 0.3.1.1++* Added `README.md` file and improved documentation of modules and functions.+  [#1057](https://github.com/yesodweb/wai/pull/1057)+ ## 0.3.1  BUGFIXES: -* `resume` now acts as a `tickle` if the `Handle` isn't paused.-  This is the same behaviour as before version `0.3.0`.-* `registerKillThread` now throws the `TimeoutThread` in a separate-  thread, so as to not block the GHC's System TimerManager.-  This does mean that `TimeoutThread` exceptions could technically-  be thrown "out of order", but they will be more prompt.+* [#1055](https://github.com/yesodweb/wai/pull/1055)+  * `resume` now acts as a `tickle` if the `Handle` isn't paused.+    This is the same behaviour as before version `0.3.0`.+  * `registerKillThread` now throws the `TimeoutThread` in a separate+    thread, so as to not block the GHC's System TimerManager.+    This does mean that `TimeoutThread` exceptions could technically+    be thrown "out of order", but they will be more prompt. + ## 0.3.0 -* New architecture. The backend is switched from the designated thread-  to GHC's System TimerManager. From this version, this library is-  just wrapper APIs of GHC's System TimerManager. Unlike v0.2 or-  earlier, callbacks are executed at the exact time. System-  TimerManager uses a PSQ (a tree) while v0.2 or earlier uses a list.-  So, this version hopefully scales better.-* Deprecated functions: `stopManager`, `killManager` and `withManager'`.-* `tickle` sets the specified timeout from now.-* `pause` is now identical to `cancel`.-* `resume` is now re-registration of timeout.-* The signature of `withHandle` is changed.+* [#1048](https://github.com/yesodweb/wai/pull/1048)+  * New architecture. The backend is switched from the designated thread+    to GHC's System TimerManager. From this version, this library is+    just wrapper APIs of GHC's System TimerManager. Unlike v0.2 or+    earlier, callbacks are executed at the exact time. System+    TimerManager uses a PSQ (a tree) while v0.2 or earlier uses a list.+    So, this version hopefully scales better.+  * Deprecated functions: `stopManager`, `killManager` and `withManager'`.+  * `tickle` sets the specified timeout from now.+  * `pause` is now identical to `cancel`.+  * `resume` is now re-registration of timeout.+  * The signature of `withHandle` is changed.  ## 0.2.4 
+ README.md view
@@ -0,0 +1,13 @@+## time-manager++This package provides module to let you run actions with resettable timeouts+(i.e. `System.TimeManager`) and run actions that will make sure that all+threads forked with the given `ThreadManager` will be killed when the action+finishes.++## WARNINGS++Since version `0.3.0`, **the timeout manager relies on GHC internals**.+This change also means that using **this package only works with the threaded**+**runtime**. The moment a timeout is registered on a non-threaded runtime, an+exception will be thrown.
System/ThreadManager.hs view
@@ -4,6 +4,17 @@  -- | A thread manager including a time manager. --   The manager has responsibility to kill managed threads.+--+-- Because this is based on the accompanying "System.TimeManager" module,+-- the same caveats apply:+--+--   * Only works for GHC.+--   * Only works with a threaded runtime.+--   * Users of older versions should check the current semantics.+--   * Using 32-bit systems means the max timeout is @'maxBound' :: Int@+--     (2147483647) microseconds, which is less than 36 minutes.+--   * Using the same 'Handle' in different threads might cause issues in some+--     edge cases. (i.e. using cancel/pause in one thread, and resume in another) module System.ThreadManager (     ThreadManager,     newThreadManager,@@ -36,7 +47,7 @@ import qualified Control.Exception as E import Control.Monad (unless, void) import Data.Foldable (forM_)-import Data.IORef+import Data.IORef (IORef, atomicModifyIORef', newIORef) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Word (Word64)@@ -65,10 +76,12 @@  ---------------------------------------------------------------- --- | Starting a thread manager.---   Its action is initially set to 'return ()' and should be set---   by 'setAction'. This allows that the action can include---   the manager itself.+-- | Create a thread manager.+--+-- To create a 'ThreadManager', you will first have to create a+-- 'T.Manager' from the "System.TimeManager" module.+--+-- You can use either 'System.TimeManager.initialize' or 'System.TimeManager.withManager'. newThreadManager :: T.Manager -> IO ThreadManager newThreadManager timmgr = ThreadManager timmgr <$> newTVarIO Map.empty @@ -84,6 +97,10 @@  -- | Stopping the manager. --+-- @+-- stopAfter threadManager action cleanup+-- @+-- -- The action is run in the scope of an exception handler that catches all -- exceptions (including asynchronous ones); this allows the cleanup handler -- to cleanup in all circumstances. If an exception is caught, it is rethrown@@ -123,14 +140,25 @@  -- | Like 'forkManaged', but run action with exceptions masked forkManagedUnmask-    :: ThreadManager -> String -> ((forall x. IO x -> IO x) -> IO ()) -> IO ()+    :: ThreadManager+    -> String+    -- ^ Thread name+    -> ((forall x. IO x -> IO x) -> IO ())+    -- ^ Action with unmask argument+    -> IO () forkManagedUnmask (ThreadManager _timmgr var) label io =     void $ E.mask_ $ forkIOWithUnmask $ \unmask -> E.handle ignore $ do         labelMe label         E.bracket (setup var) (clear var) $ \_ -> io unmask  -- | Fork a managed thread with a handle created by a timeout manager.-forkManagedTimeout :: ThreadManager -> String -> (T.Handle -> IO ()) -> IO ()+forkManagedTimeout+    :: ThreadManager+    -> String+    -- ^ Thread name+    -> (T.Handle -> IO ())+    -- ^ Action with timeout handle+    -> IO () forkManagedTimeout (ThreadManager timmgr var) label io =     void $ forkIO $ do         labelMe label@@ -140,26 +168,37 @@     ex = KilledByThreadManager Nothing  -- | Fork a managed thread with a cleanup function.-forkManagedFinally :: ThreadManager -> String -> IO () -> IO () -> IO ()-forkManagedFinally mgr label io final = E.mask $ \restore ->-    forkManaged-        mgr-        label-        (E.try (restore io) >>= \(_ :: Either E.SomeException ()) -> final)+forkManagedFinally+    :: ThreadManager+    -> String+    -- ^ Thread name+    -> IO ()+    -- ^ Action+    -> IO ()+    -- ^ Cleanup function+    -> IO ()+forkManagedFinally mgr label io final =+    forkManagedUnmask mgr label $ \restore ->+        E.try (restore io) >>= \(_ :: Either E.SomeException ()) -> final  -- | Fork a managed thread with a handle created by a timeout manager -- and with a cleanup function. forkManagedTimeoutFinally-    :: ThreadManager -> String -> (T.Handle -> IO ()) -> IO () -> IO ()+    :: ThreadManager+    -> String+    -- ^ Thread name+    -> (T.Handle -> IO ())+    -- ^ Action with timeout handle+    -> IO ()+    -- ^ Cleanup function+    -> IO () forkManagedTimeoutFinally mgr label io final = E.mask $ \restore ->-    forkManagedTimeout-        mgr-        label-        (\th -> E.try (restore $ io th) >>= \(_ :: Either E.SomeException ()) -> final)+    forkManagedTimeout mgr label $ \th ->+        E.try (restore $ io th) >>= \(_ :: Either E.SomeException ()) -> final  setup :: TVar (Map Key ManagedThread) -> IO (Key, Weak ThreadId, IORef Bool) setup var = do-    (wtid, n) <- myWeakThradId+    (wtid, n) <- myWeakThreadId     ref <- newIORef False     let ent = ManagedThread wtid ref     -- asking to throw KilledByThreadManager to me@@ -184,21 +223,21 @@ ignore :: KilledByThreadManager -> IO () ignore (KilledByThreadManager _) = return () --- | Wait until all managed thread are finished.+-- | Wait until all managed threads are finished. waitUntilAllGone :: ThreadManager -> IO ()-waitUntilAllGone (ThreadManager _timmgr var) = atomically $ do-    m <- readTVar var-    check (Map.size m == 0)+waitUntilAllGone tm =+    atomically $+        isAllGone tm >>= check +-- | STM action that checks if all managed threads are finished. isAllGone :: ThreadManager -> STM Bool-isAllGone (ThreadManager _timmgr var) = do-    m <- readTVar var-    return (Map.size m == 0)+isAllGone (ThreadManager _timmgr var) =+    Map.null <$> readTVar var  ---------------------------------------------------------------- -myWeakThradId :: IO (Weak ThreadId, Key)-myWeakThradId = do+myWeakThreadId :: IO (Weak ThreadId, Key)+myWeakThreadId = do     tid <- myThreadId     wtid <- mkWeakThreadId tid     let n = fromThreadId tid@@ -209,6 +248,8 @@     tid <- myThreadId     labelThread tid l +-- | Registering a 'T.TimeoutAction' and unregister its 'T.Handle'+--   when the body action is finished. withHandle     :: ThreadManager -> T.TimeoutAction -> (T.Handle -> IO a) -> IO a withHandle (ThreadManager timmgr _) = T.withHandle timmgr
System/TimeManager.hs view
@@ -5,6 +5,7 @@ -- GHC System TimerManager. -- -- Some caveats of using this package:+-- --   * Only works for GHC --   * Only works with a threaded runtime --   * Users of older versions should check the current semantics.
time-manager.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               time-manager-version:            0.3.1+version:            0.3.1.1 license:            MIT license-file:       LICENSE maintainer:         kazu@iij.ad.jp@@ -16,6 +16,7 @@ category:           System build-type:         Simple extra-source-files: ChangeLog.md+                    README.md  library     exposed-modules: