@@ -5,12 +5,12 @@
5-- second, and write the current time to a shared 'IORef', than it is for each
5-- second, and write the current time to a shared 'IORef', than it is for each
6-- request to make its own call to 'getCurrentTime'.
6-- request to make its own call to 'getCurrentTime'.
8−-- But for a low-volume server, whose request frequency is less than once per
8+-- But for a low-volume server, whose request frequency is less than once per
9−-- second, that approach will result in /more/ calls to 'getCurrentTime' than
9+-- second, that approach will result in /more/ calls to 'getCurrentTime' than
10-- necessary, and worse, kills idle GC.
10-- necessary, and worse, kills idle GC.
12-- This library solves that problem by allowing you to define actions which will
12-- This library solves that problem by allowing you to define actions which will
13−-- either be performed by a dedicated thread, or, in times of low volume, will
13+-- either be performed by a dedicated thread, or, in times of low volume, will
14-- be executed by the calling thread.
14-- be executed by the calling thread.
16-- Example usage:
16-- Example usage:
@@ -42,7 +42,8 @@ module Control.AutoUpdate (
42import Control.Concurrent (forkIO, threadDelay)
42import Control.Concurrent (forkIO, threadDelay)
43import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar,
43import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar,
44 takeMVar, tryPutMVar)
44 takeMVar, tryPutMVar)
45−import Control.Exception (SomeException, catch, throw, mask_, try)
45+import Control.Exception (SomeException, catch, mask_, throw,
46import Control.Monad (void)
47import Control.Monad (void)
47import Data.IORef (newIORef, readIORef, writeIORef)
48import Data.IORef (newIORef, readIORef, writeIORef)
@@ -54,6 +55,7 @@ defaultUpdateSettings = UpdateSettings
54 { updateFreq = 1000000
55 { updateFreq = 1000000
55 , updateSpawnThreshold = 3
56 , updateSpawnThreshold = 3
56 , updateAction = return ()
57 , updateAction = return ()
58+ , updateActionModify = Nothing
59-- | Settings to control how values are updated.
61-- | Settings to control how values are updated.
@@ -90,6 +92,11 @@ data UpdateSettings a = UpdateSettings
90 -- Default: does nothing.
92 -- Default: does nothing.
92 -- @since 0.1.0
94 -- @since 0.1.0
95+ , updateActionModify :: Maybe (a -> IO a)
96+ -- ^ Optional action to be performed to get the current value
97+ -- and updating it if necessary.
99+ -- Default: does nothing.
95-- | Generate an action which will either read from an automatically
102-- | Generate an action which will either read from an automatically
@@ -140,12 +147,12 @@ mkAutoUpdate us = do
140 -- This infinite loop makes up out worker thread. It takes an a
147 -- This infinite loop makes up out worker thread. It takes an a
141 -- responseVar value where the next value should be putMVar'ed to for
148 -- responseVar value where the next value should be putMVar'ed to for
142 -- the benefit of any requesters currently blocked on it.
149 -- the benefit of any requesters currently blocked on it.
143− let loop responseVar = do
150+ let loop responseVar maybea = do
144 -- block until a value is actually needed
151 -- block until a value is actually needed
145 takeMVar needsRunning
152 takeMVar needsRunning
147 -- new value requested, so run the updateAction
154 -- new value requested, so run the updateAction
148− a <- catchSome $ updateAction us
155+ a <- catchSome $ maybe (updateAction us) id (updateActionModify us <*> maybea)
150 -- we got a new value, update currRef and lastValue
157 -- we got a new value, update currRef and lastValue
151 writeIORef currRef $ Right a
158 writeIORef currRef $ Right a
@@ -160,10 +167,10 @@ mkAutoUpdate us = do
160 -- variable.
167 -- variable.
161 responseVar' <- newEmptyMVar
168 responseVar' <- newEmptyMVar
162 writeIORef currRef $ Left responseVar'
169 writeIORef currRef $ Left responseVar'
163− loop responseVar'
170+ loop responseVar' (Just a)
165 -- Kick off the loop, with the initial responseVar0 variable.
172 -- Kick off the loop, with the initial responseVar0 variable.
166− loop responseVar0
173+ loop responseVar0 Nothing
168 return $ do
175 return $ do
169 mval <- readIORef currRef
176 mval <- readIORef currRef