Copyright | (c) Dong Han 2017-2018 |
---|---|
License | BSD |
Maintainer | winterland1989@gmail.com |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
This module provide low resolution (0.1s) timers using a timing wheel of size 128 per capability, each timer thread will automatically started or stopped based on demannd. register or cancel a timeout is O(1), and each step only need scan n/128 items given timers are registered in an even fashion. This timer is particularly suitable for high concurrent approximated IO timeout scheduling. You should not rely on it to provide timing information since it's very inaccurate. Reference: * https://github.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/HashedWheelTimer.java * http://www.cse.wustl.edu/~cdgill/courses/cs6874/TimingWheels.ppt
Synopsis
- registerLowResTimer :: Int -> IO () -> IO LowResTimer
- registerLowResTimer_ :: Int -> IO () -> IO ()
- registerLowResTimerOn :: LowResTimerManager -> Int -> IO () -> IO LowResTimer
- data LowResTimer
- queryLowResTimer :: LowResTimer -> IO Int
- cancelLowResTimer :: LowResTimer -> IO Int
- cancelLowResTimer_ :: LowResTimer -> IO ()
- timeoutLowRes :: Int -> IO a -> IO (Maybe a)
- timeoutLowResEx :: HasCallStack => Int -> IO a -> IO a
- throttle :: Int -> IO a -> IO (IO a)
- throttle_ :: Int -> IO () -> IO (IO ())
- throttleTrailing_ :: Int -> IO () -> IO (IO ())
- data LowResTimerManager
- getLowResTimerManager :: IO LowResTimerManager
- isLowResTimerManagerRunning :: LowResTimerManager -> IO Bool
- lowResTimerManagerCapabilitiesChanged :: IO ()
low resolution timers
:: Int | timeout in unit of 0.1s |
-> IO () | the action you want to perform, it should not block |
-> IO LowResTimer |
Register a new timer on current capability's timer manager, start the timing wheel if it's not turning.
If the action could block, you may want to run it in another thread. Example to kill a thread after 10s:
registerLowResTimer 100 (forkIO $ killThread tid)
void
(registerLowResTimer
t action)
registerLowResTimerOn Source #
:: LowResTimerManager | a low resolution timer manager |
-> Int | timeout in unit of 0.1s |
-> IO () | the action you want to perform, it should not block |
-> IO LowResTimer |
Same as registerLowResTimer
, but allow you choose timer manager.
data LowResTimer Source #
Timer registered by registerLowResTimer
or registerLowResTimerOn
.
queryLowResTimer :: LowResTimer -> IO Int Source #
Query how many seconds remain before timer firing.
A return value <= 0 indictate the timer is firing or fired.
cancelLowResTimer :: LowResTimer -> IO Int Source #
Cancel a timer, return the remaining ticks.
This function have no effect after the timer is fired.
cancelLowResTimer_ :: LowResTimer -> IO () Source #
void . cancelLowResTimer
similar to timeout
, this function put a limit on time which an IO can consume.
Note timeoutLowRes is also implemented with Exception
underhood, which can have some surprising
effects on some devices, e.g. use timeoutLowRes
with reading or writing on UVStream
s may close
the UVStream
once a reading or writing is not able to be done in time.
:: HasCallStack | |
=> Int | timeout in unit of 0.1s |
-> IO a | |
-> IO a |
Similar to timeoutLowRes
, but raise a TimeOutException
to current thread
instead of return Nothing
if timeout.
Cache result of an IO action for give time t.
This combinator is useful when you want to share IO result within a period, the action will be called on demand, and the result will be cached for t milliseconds.
One common way to get a shared periodical updated value is to start a seperate thread and do calculation periodically, but doing that will stop system from being idle, which stop idle GC from running, and in turn disable deadlock detection, which is too bad. This function solves that.
Throttle an IO action without caching result.
The IO action will run at leading edge. i.e. once run, during following (t/10)s throttled action will no-ops.
Note the action will run in the calling thread.
Similar to throttle_
but run action in trailing edge
The IO action will run at trailing edge. i.e. no matter how many times throttled action are called, original action will run only once after (t/10)s.
Note the action will be run in a new created thread.
low resolution timer manager
data LowResTimerManager Source #
getLowResTimerManager :: IO LowResTimerManager Source #
Get a LowResTimerManager
for current thread.
isLowResTimerManagerRunning :: LowResTimerManager -> IO Bool Source #
Check if a timer manager's wheel is turning
This is mostly for testing purpose.
lowResTimerManagerCapabilitiesChanged :: IO () Source #
Create new low resolution timer manager on capability change.
Since low resolution timer manager is not hooked into RTS, you're responsible to call this function
after you call setNumCapabilities
to match timer manager array size with new capability number.
This is not a must though, when we fetch timer manager we always take a modulo.