Skip to content

Instantly share code, notes, and snippets.

@roman
Last active December 7, 2017 05:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save roman/5578320 to your computer and use it in GitHub Desktop.
Save roman/5578320 to your computer and use it in GitHub Desktop.
Implementation of throttle in Conduit 0.5.x
import Control.Concurrent (forkIO, killThread,
threadDelay, newEmptyMVar,
tryTakeMVar, putMVar)
import Control.Monad (void, forever)
import Control.Concurrent.STM (atomically)
import Control.Monad.Trans (MonadIO(..))
import Control.Monad.Trans.Resource (MonadResource, allocate)
import Data.Conduit (GInfConduit, awaitE)
throttle :: (MonadResource m) => Int -> GInfConduit a m a
throttle micro = do
inputThrottle <- liftIO $ newEmptyMVar
yieldInitialInput
startThrottleThread inputThrottle
throttleRestOfInput inputThrottle
where
yieldInitialInput = do
inputE <- awaitE
case inputE of
Right input -> yield input
Left _ -> return ()
throttleRestOfInput inputThrottle =
awaitForever $ \input -> do
result <- liftIO $ tryTakeMVar inputThrottle
case result of
Just _ -> yield $ input
Nothing -> return ()
startThrottleThread inputThrottle =
void $ allocate (forkIO $ throttleThread inputThrottle)
(killThread)
throttleThread inputThrottle = forever $ do
threadDelay micro
void $ putMVar inputThrottle True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment