Skip to content

Instantly share code, notes, and snippets.

@kakkun61
Last active April 24, 2019 10:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kakkun61/06f3480bc8805b9d51334cfeaadbedb3 to your computer and use it in GitHub Desktop.
Save kakkun61/06f3480bc8805b9d51334cfeaadbedb3 to your computer and use it in GitHub Desktop.
thread pool with thread-local state
module Control.Concurrent.ThreadPool
( Pool
, create
, queue
, state
, kill
) where
import Control.Concurrent (ThreadId, forkIO, killThread)
import Control.Concurrent.STM (TQueue, atomically, newTQueueIO,
readTQueue, writeTQueue)
import Control.Monad (replicateM)
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import Data.Traversable (for)
data Pool a = Pool (TQueue (a -> IO a)) [(ThreadId, IORef a)]
create :: Word -> IO a -> IO (Pool a)
create n ini = do
q <- newTQueueIO
ts <- replicateM (fromIntegral n) $ do
s <- ini
ref <- newIORef s
tid <- forkIO $ go q ref s
pure (tid, ref)
pure $ Pool q ts
where
go q r s = do
task <- atomically $ readTQueue q
s' <- task s
writeIORef r s'
go q r s'
queue :: Pool a -> (a -> IO a) -> IO ()
queue (Pool q _) task = atomically $ writeTQueue q task
state :: Pool a -> IO [a]
state (Pool _ ts) = for ts $ \(_, ref) -> readIORef ref
kill :: Pool a -> IO [a]
kill (Pool _ ts) =
for ts $ \(tid, ref) -> do
killThread tid
readIORef ref
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment