-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A parallel producer/consumer engine (thread pool)
--
-- A parallel producer/consumer engine (thread pool). There are lots of
-- features in the Engine, to include dynamically adjustable hooks,
-- managed state, and injection points.
@package Control-Engine
@version 0.0.3
module Control.ThreadPool
-- | 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)
-- | 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)
-- | Implemented here is a thread pool library on crack.
--
--
-- - 0 Introduction Typically, a thread pool is a set of execution
-- contexts that will execute tasks from an input queue. Typically,
-- thread pools are used to parallize the processing of incoming work
-- across all available CPUs without going through the expense of
-- starting a new thread for every new task.
--
--
-- In Control.Engine you will find a somewhat unique
-- implementation. The Engine is not only a set of threads running
-- a common mutator on the input queue, producing an output queue, but
-- also include hooks, task injection, and state management.
--
-- Queues :: (Chan a) From Control.Concurrent.Chan.
--
-- Hooks :: (a -> IO Maybe a) Hooks can be added and removed during
-- execution without creating a new engine. They allow the developer to
-- modify tasks:
--
--
-- - prior to parallization (for sequential preprocessing)
-- - in parallel, prior to main mutation funciton
-- - in parallel, after mutation function
-- - post parallization (for sequential post processing)
--
--
-- State Management The stateManager waits for any updates to the mutator
-- state or hooks. If any modifications are made then the new set of
-- hooks (or state) is provided to the workers. Correctness is handled by
-- keeping the master copies as TVars (Control.Concurrent.STM).
-- While the mutators and hooks read from an MVar
-- (Control.Concurrent.MVar) to avoid contention.
--
-- The thinking here is that changing the hooks and state is a rare / low
-- contention action while the need for this information will be constant
-- and performance critical. How successful this stratagy is has yet to
-- be shown.
--
-- Injection One injection point allows injection of a result that had no
-- preceding task. The second injector allows the initial hooks
-- (Input hooks) to be bypassed.
module Control.Engine
-- | If all you want is a basic thread pool, this will work. You should
-- consider using Control.ThreadPool instead.
--
-- Evaluation of the result is forced using seq.
initSimpleEngine :: Int -> (job -> result) -> IO (Chan job, Chan result)
-- | Simpler than calling initEngine, but it allows no state or
-- interaction with the hooks and injectors. No strictness is forced.
initSimpleEngineIO :: Int -> (job -> IO result) -> IO (Chan job, Chan result)
-- | To initilize an engine you must provide:
--
--
-- - the number of threads
-- - an action that will get the input
-- - an action that will consume output
-- - a mutator function to perform on all inputs
-- - an initial state for the mutator function
--
--
-- No strictness is forced - be sure you force evaluation if wanted. All
-- hooks start out empty.
initEngine :: (Eq st) => Int -> (IO job) -> (result -> IO ()) -> (st -> job -> IO (Maybe result)) -> st -> IO (Engine job result st)
-- | An Engine represents a pool of threads ready to execute tasks.
data Engine job result state
Eng :: Chan job -> Chan result -> TVar [Hook state job] -> TVar [Hook state job] -> TVar [Hook state result] -> TVar [Hook state result] -> MVar [Hook state job] -> MVar [Hook state job] -> MVar [Hook state result] -> MVar [Hook state result] -> TVar state -> Engine job result state
chan1 :: Engine job result state -> Chan job
chan2 :: Engine job result state -> Chan result
tvInHook :: Engine job result state -> TVar [Hook state job]
tvPreMutateHook :: Engine job result state -> TVar [Hook state job]
tvPostMutateHook :: Engine job result state -> TVar [Hook state result]
tvOutHook :: Engine job result state -> TVar [Hook state result]
mvInHook :: Engine job result state -> MVar [Hook state job]
mvPreMutateHook :: Engine job result state -> MVar [Hook state job]
mvPostMutateHook :: Engine job result state -> MVar [Hook state result]
mvOutHook :: Engine job result state -> MVar [Hook state result]
state :: Engine job result state -> TVar state
-- | A hook is simply a mutation on the task. The priority is used to order
-- hook execution (lower value priorites happen first). For accounting
-- and to remove old hooks the description field is used.
data Hook st msg
Hk :: (st -> msg -> IO (Maybe msg)) -> Int -> String -> Hook st msg
hkFunc :: Hook st msg -> st -> msg -> IO (Maybe msg)
hkPriority :: Hook st msg -> Int
hkDescription :: Hook st msg -> String
data HookLoc
InputHook :: HookLoc
PreMutateHook :: HookLoc
PostMutateHook :: HookLoc
OutputHook :: HookLoc
-- | Adds a hook that will be performed in serial on all jobs added to the
-- input queue.
addInputHook :: Engine job result state -> Hook state job -> IO ()
-- | Adds a hook that will be performed in serial on all results before
-- they are added to the output queue.
addOutputHook :: Engine job result state -> Hook state result -> IO ()
-- | Adds a hook that will be performed in parallel before the main mutator
-- function.
addPreMutateHook :: Engine job result state -> Hook state job -> IO ()
-- | Adds a hook that will be performed in parallel after the main mutator
-- function.
addPostMutateHook :: Engine job result state -> Hook state result -> IO ()
-- | Deletes all input hooks matching the provided desciption
delInputHook :: Engine j r s -> String -> IO ()
-- | Deletes all output hooks matching the provided desciption
delOutputHook :: Engine j r s -> String -> IO ()
-- | Deletes all pre-mutate hooks matching the provided desciption
delPreMutateHook :: Engine j r s -> String -> IO ()
-- | Deletes all post-mutate hooks matching the provided desciption
delPostMutateHook :: Engine j r s -> String -> IO ()
-- | Allows adding tasks that bypass the input hooks.
injectPreMutator :: Engine j r s -> j -> IO ()
-- | Allows bypassing the mutator, meaning a result can be
-- produced without a task. This still hits the output hooks.
injectPostMutator :: Engine j r s -> r -> IO ()
instance Eq HookLoc
instance Ord HookLoc
instance Show HookLoc
instance Show (Hook a s)
instance Ord (Hook a s)
instance Eq (Hook m s)