ircbot-0.5.0: Network/IRC/Bot/Limiter.hs
{- |
Module : Network.IRC.Bot.Limiter
Description : simple rate limiter
Copyright : (c) 2012 Eric Mertens
License : BSD3
Maintainer : jeremy@seereason.com
Stability : stable
Portability : portable
A simple rate limiter.
-}
module Network.IRC.Bot.Limiter
( Limiter(..)
, newLimiter
, limit
)
where
import Control.Concurrent (ThreadId, forkIO, threadDelay)
import Control.Concurrent.QSem (QSem, newQSem, signalQSem, waitQSem)
import Control.Monad (forever)
data Limiter = Limiter
{ limitsIn :: QSem
, limitsOut :: QSem
, limitsDelay :: Int
, limitsThreadId :: ThreadId
}
-- | Construct a new rate limit control
newLimiter :: Int -- ^ max burst length
-> Int -- ^ delay (in microseconds)
-> IO Limiter
newLimiter burst delay = do
rdy <- newQSem burst
sent <- newQSem 0
let l = Limiter { limitsIn = sent
, limitsOut = rdy
, limitsDelay = delay
, limitsThreadId = error "limiter thread not started yet"
}
tid <- forkIO (limiter l)
return $ l { limitsThreadId = tid }
-- | Execute this before sending
limit :: Limiter -> IO ()
limit l = do
waitQSem (limitsOut l)
signalQSem (limitsIn l)
-- | Loop which manages the limit timers
limiter :: Limiter -> IO b
limiter l = forever $ do
waitQSem (limitsIn l)
threadDelay (limitsDelay l)
signalQSem (limitsOut l)