-- 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.2 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. -- --
    --
  1. 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.
  2. --
-- -- 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: -- -- -- -- 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: -- -- -- -- 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)