-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Cooperative task prioritization. -- -- A strategy to prioritize access to limited resources. @package priority-sync @version 0.2.1.1 module PrioritySync.Internal.UserData module PrioritySync.Internal.ClaimContext -- | Rules for calling claim_. class ClaimContext c where { type family ClaimHandle c :: *; } approveClaimsEntering :: ClaimContext c => c -> [Claim (UserData c)] -> STM (ClaimHandle c) approveClaimsExiting :: ClaimContext c => c -> [Claim (UserData c)] -> STM (ClaimHandle c) waitingAction :: ClaimContext c => c -> ClaimHandle c -> STM () instance ClaimContext c => ClaimContext (c, m) module PrioritySync.Internal.RoomGroup class RoomGroup m roomsOf :: RoomGroup m => m -> [Room (UserData m)] instance (UserData c ~ UserData m, RoomGroup c, RoomGroup m) => RoomGroup (c, m) instance RoomGroup rs => RoomGroup [rs] instance RoomGroup (Room u) module PrioritySync.Internal.Receipt -- | Get a notification when a claim is approved or scheduled. data Receipt c Receipt :: c -> (ClaimHandle c -> STM ()) -> (ClaimHandle c -> STM ()) -> Receipt c receipt_base_context :: Receipt c -> c receipt_entering_callback :: Receipt c -> ClaimHandle c -> STM () receipt_exiting_callback :: Receipt c -> ClaimHandle c -> STM () instance ClaimContext c => ClaimContext (Receipt c) instance RoomGroup c => RoomGroup (Receipt c) module PrioritySync.Internal.RoomConstraint class RoomConstraint u approveConstraint :: RoomConstraint u => Claim a -> u -> STM () -- | A maximum limit on the number of threads allowed to claim a room. newtype MaxThreads MaxThreads :: Int -> MaxThreads -- | approve some claims according to their constraints. approveClaims :: RoomConstraint u => [Claim u] -> STM () instance RoomConstraint a => RoomConstraint (Maybe a) instance (RoomConstraint a, RoomConstraint b) => RoomConstraint (Either a b) instance (RoomConstraint a, RoomConstraint b) => RoomConstraint (a, b) instance RoomConstraint u => RoomConstraint (STM u) instance RoomConstraint MaxThreads instance RoomConstraint Bool instance RoomConstraint () module PrioritySync.Internal.Room -- | A resource pool, parameterized against arbitrary user data. data Room u -- | Create a new Room with some arbitrary user data. newRoom :: u -> IO (Room u) -- | Get the user data associated with a Room. userData :: Room u -> u -- | Get all ThreadIds that are currently claiming this Room. inUse :: Room u -> STM (Set ThreadId) -- | A Claim, or attempt to acquire or release a Room. data Claim u -- | Get the Room target of a Claim. claimedRoom :: Claim u -> Room u -- | Get the thread attempting a Claim. claimedThread :: Claim u -> ThreadId data ClaimMode Acquire :: ClaimMode Release :: ClaimMode -- | Temporarily Acquire, and then release, or Release, and -- then acquire, some Rooms for the duration of a critical -- section. A simple example where a room might be used to prevent -- interleaving of stdout: -- --
--   room <- newRoom (MaxThreads 1)
--   forkIO $ claim Acquire (Default,room) $ putStrLn "Hello World!"
--   forkIO $ claim Acquire (Default,room) $ putStrLn "Foo!  Bar!"
--   
claim :: (RoomGroup c, ClaimContext c) => ClaimMode -> c -> IO a -> IO a -- | approve some claims according to their constraints. approveClaims :: RoomConstraint u => [Claim u] -> STM () -- | Approve a claim. This actually acquires or releases a Room. approve :: Claim u -> STM () -- | True iff a Room is empty. isEmpty :: Room u -> STM Bool module PrioritySync.Internal.Constrained -- | Require that all RoomConstraints be satisfied when acquiring a -- Room. data Constrained u Constrained :: Constrained u instance RoomConstraint u => ClaimContext (Constrained u) instance RoomGroup (Constrained u) module PrioritySync.Internal.Unconstrained -- | Don't check any RoomConstraints when acquiring a Room. data Unconstrained u Unconstrained :: Unconstrained u instance ClaimContext (Unconstrained u) instance RoomGroup (Unconstrained u) module PrioritySync.Internal.Prioritized -- | Reprioritize a task. This has no effect on a target that has already -- left the queue. class Prioritized p where { type family Priority p :: *; } reprioritize :: Prioritized p => p -> (Priority p -> Priority p) -> STM () instance Prioritized p => Prioritized (Maybe p) module PrioritySync.Internal.Queue -- | A prioritized Queue. Prioritization is least-first, i.e. larger -- values are nicer. -- -- A Queue is not associated with any working thread, therefore, -- it is the client's responsibility to make sure that every pushed task -- is also pulled, or the Queue will stall. There are several ways -- to accomplish this: -- -- data Ord a => Queue a data TaskHandle a data QueueOrder FIFO :: QueueOrder FILO :: QueueOrder -- | Configuration options for a Queue. A Queue blocks on a -- number of predicates when dispatching a job. Generally, -- fair_queue_configuration should work well. -- -- -- -- If a task is blocked for any reason, the task is skipped and the next -- task attempted, in priority order. data Ord a => QueueConfigurationRecord a QueueConfigurationRecord :: STM () -> (a -> STM ()) -> (a -> a -> Bool) -> Int -> !QueueOrder -> QueueConfigurationRecord a -- | A predicate that must hold before any task may be pulled from a -- Queue. queue_predicate :: QueueConfigurationRecord a -> STM () -- | A predicate that must hold before any priority level may be pulled -- from a Queue. priority_indexed_predicate :: QueueConfigurationRecord a -> (a -> STM ()) -- | Constrains the greatest allowed difference between the priority of the -- top-of-queue task and the priority of a task to be pulled. allowed_priority_inversion :: QueueConfigurationRecord a -> a -> a -> Bool -- | The greatest allowed difference between the ideal prioritized -- FILO/FIFO ordering of tasks and the actual ordering of tasks. Setting -- this too high can introduce a lot of overhead in the presence of a lot -- of short-running tasks. Setting this to zero turns off the predicate -- failover feature, i.e. only the top of queue task will ever be pulled. allowed_ordering_inversion :: QueueConfigurationRecord a -> Int -- | Should the Queue run in FILO or FIFO order. Ordering takes -- place after prioritization, and won't have much effect if priorities -- are very fine-grained. queue_order :: QueueConfigurationRecord a -> !QueueOrder -- | A queue tuned for high throughput and fairness when processing -- moderate to long running tasks. fair_queue_configuration :: Ord a => QueueConfigurationRecord a -- | A queue tuned for high responsiveness and low priority inversion, but -- may have poorer long-term throughput and potential to starve some -- tasks compared to fair_queue_configuration. fast_queue_configuration :: Ord a => QueueConfigurationRecord a -- | Create a new Queue. newQueue :: Ord a => QueueConfigurationRecord a -> IO (Queue a) -- | Get the priority of this task, which only exists if the task is still -- enqueued. taskPriority :: Ord a => TaskHandle a -> STM (Maybe a) -- | Get the Queue associated with this task. taskQueue :: TaskHandle a -> Queue a pendingTasks :: Ord a => Queue a -> STM [TaskHandle a] -- | True iff this task is poised at the top of it's Queue. isTopOfQueue :: TaskHandle a -> STM Bool hasCompleted :: TaskHandle a -> STM Bool -- | Put a task with it's priority value onto this queue. Returns a handle -- to the task. putTask :: Ord a => Queue a -> a -> STM () -> STM (TaskHandle a) -- | Pull and commit a task from this Queue. pullTask :: Ord a => Queue a -> STM (TaskHandle a) -- | Pull this task from the top of a Queue, if it is already there. -- If this task is top-of-queue, but it's predicates fail, then -- pullFromTop may instead pull a lower-priority -- TaskHandle. pullFromTop :: Ord a => TaskHandle a -> STM (TaskHandle a) -- | Don't return until the given TaskHandles have been pulled from -- their associated Queues. This doesn't guarantee that the -- TaskHandle will ever be pulled, even when the TaskHandle -- and Queue are both viable. You must concurrently arrange for -- every other TaskHandle associated with the same Queue to -- be pulled, or the Queue will stall. pullSpecificTasks -- can handle lists TaskHandles that are distributed among several -- Queues, as well as a TaskHandles that have already -- completed or complete concurrently from another thread. pullSpecificTasks :: Ord a => [TaskHandle a] -> IO () -- | "Fire and forget" some tasks on a separate thread. dispatchTasks :: Ord a => [(Queue a, a, STM ())] -> IO [TaskHandle a] -- | Process a Queue until it is empty. flushQueue :: Ord a => Queue a -> IO () -- | The number of tasks pending on this Queue. load :: Ord a => Queue a -> STM Int -- | True iff this Queue is empty. isEmpty :: Ord a => Queue a -> STM Bool instance Ord a => Prioritized (TaskHandle a) instance Ord a => Ord (TaskHandle a) instance (Ord a, Eq a) => Eq (TaskHandle a) instance Ord a => Ord (Queue a) instance Ord a => Eq (Queue a) module PrioritySync.Internal.Schedule -- | Schedule a task to run from a prioritized Queue. The task will -- wait until it arrives at (or, with failover, near) the top of queue. -- Typical usage: -- --
--   Schedule q 2 room1
--   
-- -- Only the rooms inside the Schedule declaration are claimed with -- scheduling. If access to a room doesn't need to be prioritized, it can -- be set outside the schedule: -- --
--   (Schedule q 2 room1,room2)
--   
data Schedule p c Schedule :: (Queue p) -> p -> c -> Schedule p c instance (ClaimHandle c ~ (), Ord p, RoomGroup c, ClaimContext c) => ClaimContext (Schedule p c) instance RoomGroup c => RoomGroup (Schedule p c) -- | A prioritized TaskPool. This consists of a Queue, which -- prioritizes tasks, and a Room which restricts the number of -- tasks that may execute at one time. module PrioritySync.Internal.TaskPool data TaskPool p u -- | A prioritized ClaimContext for a task pool. schedule :: TaskPool p u -> p -> (Schedule p (Constrained (TaskPoolConstraint u), Room (TaskPoolConstraint u))) -- | Create a new TaskPool. TaskPools begin stopped, use -- startQueue to start. -- -- -- -- Consider using simpleTaskPool if you have no special needs. newTaskPool :: Ord p => QueueConfigurationRecord p -> Int -> u -> IO (TaskPool p u) -- | Just create a new TaskPool. The task pool is constrained by the -- number of capabilities indicated by numCapabilities. simpleTaskPool :: Ord p => IO (TaskPool p ()) -- | Get the Room that primarily constrains this TaskPool. poolRoom :: TaskPool p u -> Room (TaskPoolConstraint u) -- | Get the Queue that admits new tasks to this TaskPool. poolQueue :: TaskPool p u -> Queue p -- | Start the TaskPool. startQueue :: TaskPool p u -> STM () -- | Stop all activity on this TaskPool. stopQueue :: TaskPool p u -> STM () -- | True iff this TaskPool is entirely empty and inactive. isEmpty :: Ord p => TaskPool p u -> STM Bool -- | Wait until a queue is finished. waitUntilFinished :: Ord p => TaskPool p u -> IO () instance RoomGroup (TaskPool p u) module PrioritySync.Internal.Dispatch -- | Perform a task on another thread. This task can be reprioritized and -- canceled. dispatch :: (RoomGroup c, ClaimContext c, Prioritized (ClaimHandle c)) => c -> IO a -> IO (TaskHandle (Priority (ClaimHandle c)) a) data TaskHandle p a reprioritize :: Prioritized p => p -> (Priority p -> Priority p) -> STM () -- | Wait for the result from this task. getResult :: TaskHandle p a -> STM a -- | Non-blocking version of getResult. tryGetResult :: TaskHandle p a -> STM (Maybe a) instance Prioritized (TaskHandle p a) module PrioritySync.PrioritySync data TaskHandle p a -- | Temporarily Acquire, and then release, or Release, and -- then acquire, some Rooms for the duration of a critical -- section. A simple example where a room might be used to prevent -- interleaving of stdout: -- --
--   room <- newRoom (MaxThreads 1)
--   forkIO $ claim Acquire (Default,room) $ putStrLn "Hello World!"
--   forkIO $ claim Acquire (Default,room) $ putStrLn "Foo!  Bar!"
--   
claim :: (RoomGroup c, ClaimContext c) => ClaimMode -> c -> IO a -> IO a -- | Perform a task on another thread. This task can be reprioritized and -- canceled. dispatch :: (RoomGroup c, ClaimContext c, Prioritized (ClaimHandle c)) => c -> IO a -> IO (TaskHandle (Priority (ClaimHandle c)) a) getResult :: TaskHandle p a -> IO a tryGetResult :: TaskHandle p a -> IO (Maybe a) -- | Reprioritize a task. This has no effect on a target that has already -- left the queue. class Prioritized p reprioritize :: TaskHandle p a -> (p -> p) -> IO () -- | Require that all RoomConstraints be satisfied when acquiring a -- Room. data Constrained u Constrained :: Constrained u -- | Don't check any RoomConstraints when acquiring a Room. data Unconstrained u Unconstrained :: Unconstrained u -- | A maximum limit on the number of threads allowed to claim a room. newtype MaxThreads MaxThreads :: Int -> MaxThreads -- | A resource pool, parameterized against arbitrary user data. data Room u -- | Create a new Room with some arbitrary user data. newRoom :: u -> IO (Room u) -- | Get the user data associated with a Room. userData :: Room u -> u data ClaimMode Acquire :: ClaimMode Release :: ClaimMode -- | The number of tasks waiting on this TaskPool. load :: Ord p => TaskPool p u -> IO Int -- | A convenience class to observe the currently running occupants of a -- Room or TaskPool. class Occupancy o inUse :: Occupancy o => o -> IO (Set ThreadId) isEmpty :: Occupancy o => o -> IO Bool -- | Configuration options for a Queue. A Queue blocks on a -- number of predicates when dispatching a job. Generally, -- fair_queue_configuration should work well. -- -- -- -- If a task is blocked for any reason, the task is skipped and the next -- task attempted, in priority order. data Ord a => QueueConfigurationRecord a QueueConfigurationRecord :: STM () -> (a -> STM ()) -> (a -> a -> Bool) -> Int -> !QueueOrder -> QueueConfigurationRecord a -- | A predicate that must hold before any task may be pulled from a -- Queue. queue_predicate :: QueueConfigurationRecord a -> STM () -- | A predicate that must hold before any priority level may be pulled -- from a Queue. priority_indexed_predicate :: QueueConfigurationRecord a -> (a -> STM ()) -- | Constrains the greatest allowed difference between the priority of the -- top-of-queue task and the priority of a task to be pulled. allowed_priority_inversion :: QueueConfigurationRecord a -> a -> a -> Bool -- | The greatest allowed difference between the ideal prioritized -- FILO/FIFO ordering of tasks and the actual ordering of tasks. Setting -- this too high can introduce a lot of overhead in the presence of a lot -- of short-running tasks. Setting this to zero turns off the predicate -- failover feature, i.e. only the top of queue task will ever be pulled. allowed_ordering_inversion :: QueueConfigurationRecord a -> Int -- | Should the Queue run in FILO or FIFO order. Ordering takes -- place after prioritization, and won't have much effect if priorities -- are very fine-grained. queue_order :: QueueConfigurationRecord a -> !QueueOrder -- | A queue tuned for high throughput and fairness when processing -- moderate to long running tasks. fair_queue_configuration :: Ord a => QueueConfigurationRecord a -- | A queue tuned for high responsiveness and low priority inversion, but -- may have poorer long-term throughput and potential to starve some -- tasks compared to fair_queue_configuration. fast_queue_configuration :: Ord a => QueueConfigurationRecord a data QueueOrder FIFO :: QueueOrder FILO :: QueueOrder data TaskPool p u -- | A prioritized ClaimContext for a task pool. schedule :: TaskPool p u -> p -> (Schedule p (Constrained (TaskPoolConstraint u), Room (TaskPoolConstraint u))) -- | Create a new TaskPool. TaskPools begin stopped, use -- startQueue to start. -- -- -- -- Consider using simpleTaskPool if you have no special needs. newTaskPool :: Ord p => QueueConfigurationRecord p -> Int -> u -> IO (TaskPool p u) -- | Just create a new TaskPool. The task pool is constrained by the -- number of capabilities indicated by numCapabilities. simpleTaskPool :: Ord p => IO (TaskPool p ()) startQueue :: TaskPool p a -> IO () stopQueue :: TaskPool p a -> IO () -- | Wait until a queue is finished. waitUntilFinished :: Ord p => TaskPool p u -> IO () instance Occupancy (Room u) instance Ord p => Occupancy (TaskPool p u)