-- 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.
--
--
-- - A single STM predicate for the entire Queue. This blocks
-- the entire Queue until the predicate is satisfied.
-- - A STM predicate parameterized by priority. This blocks a single
-- priority level, and the Queue will skip all tasks at that
-- priority.
-- - Each task is itself an STM transaction, and can block itself.
-- - Pure constraints on priority and ordering inversion.
--
--
-- 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.
--
--
-- - A single STM predicate for the entire Queue. This blocks
-- the entire Queue until the predicate is satisfied.
-- - A STM predicate parameterized by priority. This blocks a single
-- priority level, and the Queue will skip all tasks at that
-- priority.
-- - Each task is itself an STM transaction, and can block itself.
-- - Pure constraints on priority and ordering inversion.
--
--
-- 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)