module Control.ThreadPool
	( threadPool
	, threadPoolIO
	) where

import Control.Monad (forever, forM_)
import Control.Concurrent (forkIO)
import Control.Concurrent.Chan

-- |A trival thread pool for pure functions (mappings).  Simply specify the number of threads desired and a mutator function.
threadPool :: Int -> (a -> b) -> IO (Chan a, Chan b)
threadPool nr mutator = do
	input <- newChan
	output <- newChan
	forM_ [1..nr] $
		\_ -> forkIO (forever $ do
			i <- readChan input
			o <- return $! mutator i
			writeChan output o)
	return (input, output)

-- |A trivial thread pool that allows IO mutator functions.  Evaluation of output is not strict
-- - force evaluation if desired!
threadPoolIO :: Int -> (a -> IO b) -> IO (Chan a, Chan b)
threadPoolIO nr mutator = do
	input <- newChan
	output <- newChan
	forM_ [1..nr] $
		\_ -> forkIO (forever $ do
			i <- readChan input
			o <- mutator i
			writeChan output o)
	return (input, output)