Autowiring  1.0.3
A C++ Inversion of Control Framework
DispatchQueue Class Reference

This is an asynchronous queue of zero-argument functions More...

#include <DispatchQueue.h>

Inheritance diagram for DispatchQueue:
CoreThread

Public Member Functions

virtual ~DispatchQueue (void)
 Runs down the dispatch queue without calling anything More...
 
void Abort (void)
 Causes the current dispatch queue to be dumped if it's non-empty More...
 
void AddExisting (std::unique_ptr< autowiring::DispatchThunkBase > &&pBase)
 Explicit overload for already-constructed dispatch thunk types More...
 
bool AreAnyDispatchersReady (void) const
 
bool Barrier (std::chrono::nanoseconds timeout)
 Blocks until all dispatchers on the DispatchQueue at the time of the call have been dispatched More...
 
void Barrier (void)
 Identical to the timed version of Barrier, but does not time out More...
 
bool Cancel (void)
 Causes the very first lambda on the dispatch queue to be deleted without running it More...
 
int DispatchAllEvents (void)
 Similar to DispatchEvent, but will attempt to dispatch all events currently queued More...
 
bool DispatchEvent (void)
 Similar to WaitForEvent, but does not block More...
 
size_t GetDispatchQueueLength (void) const
 
void operator+= (DispatchQueue &&rhs)
 Extracts the contents of the dispatch queue on the right-hand side for handling by this queue More...
 
template<class Rep , class Period >
DispatchThunkDelayedExpressionRel operator+= (std::chrono::duration< Rep, Period > rhs)
 Overload for the introduction of a delayed dispatch thunk More...
 
DispatchThunkDelayedExpressionAbs operator+= (std::chrono::steady_clock::time_point rhs)
 Overload for absolute-time based delayed dispatch thunk More...
 
void operator+= (autowiring::DispatchThunkDelayed &&rhs)
 Directly pends a delayed dispatch thunk More...
 
template<class _Fx >
bool operator+= (_Fx &&fx)
 Generic overload which will pend an arbitrary dispatch type More...
 
void Rundown (void)
 Graceful version of Abort More...
 
std::chrono::steady_clock::time_point SuggestSoonestWakeupTimeUnsafe (std::chrono::steady_clock::time_point latestTime) const
 Recommends a point in time to wake up to check for events More...
 
bool TryDispatchEvent (void)
 Similar to WaitForEvent, but does not block More...
 
void WaitForEvent (void)
 Waits until a lambda function is ready to run in this thread's dispatch queue, dispatches the function, and then returns. More...
 
bool WaitForEvent (std::chrono::milliseconds milliseconds)
 Waits until a lambda function in the dispatch queue is ready to run or the specified time period elapses, whichever comes first. More...
 
bool WaitForEvent (std::chrono::steady_clock::time_point wakeTime)
 Waits until a lambda function in the dispatch queue is ready to run or the specified time is reached, whichever comes first. More...
 
void WakeAllWaitingThreads (void)
 Causes all calls to WaitForEvent to return control to their callers More...
 

Protected Member Functions

void DispatchEventUnsafe (std::unique_lock< std::mutex > &lk)
 Similar to DispatchEvent, except assumes that the dispatch lock is currently held More...
 
virtual void OnPended (std::unique_lock< std::mutex > &&lk)
 Utility virtual, called whenever a new event is deferred More...
 
void PendExisting (std::unique_lock< std::mutex > &&lk, autowiring::DispatchThunkBase *thunk)
 Attaches an element to the end of the dispatch queue without any checks. More...
 
bool PromoteReadyDispatchersUnsafe (void)
 Moves all ready events from the delayed queue into the dispatch queue More...
 
void SetDispatcherCap (size_t dispatchCap)
 Updates the upper bound on the number of allowed pending dispatchers More...
 
void TryDispatchEventUnsafe (std::unique_lock< std::mutex > &lk)
 Similar to TryDispatchEvent, except assumes that the dispatch lock is currently held More...
 

Detailed Description

This is an asynchronous queue of zero-argument functions

A DispatchQueue is a type of event receiver which allows for the reception of deferred events.

Constructor & Destructor Documentation

virtual DispatchQueue::~DispatchQueue ( void  )
virtual

Runs down the dispatch queue without calling anything

Nothing in the destructor is synchronized. This is done under the assumption that multi- access during teardown is impossible.

Member Function Documentation

void DispatchQueue::Abort ( void  )

Causes the current dispatch queue to be dumped if it's non-empty

This method should only be called if a non-graceful termination is desired. In this case, the dispatch queue will be immediately cleared and any subsequent calls to WaitForEvent or DispatchEvent will throw a dispatch_aborted_exception.

Callers who are willing to allow the dispatch queue to be fully processed should call Rundown instead.

This method is idempotent

void DispatchQueue::AddExisting ( std::unique_ptr< autowiring::DispatchThunkBase > &&  pBase)
inline

Explicit overload for already-constructed dispatch thunk types

bool DispatchQueue::AreAnyDispatchersReady ( void  ) const
inline
Returns
True if there are curerntly any dispatchers ready for execution–IE, DispatchEvent would return true
bool DispatchQueue::Barrier ( std::chrono::nanoseconds  timeout)

Blocks until all dispatchers on the DispatchQueue at the time of the call have been dispatched

Parameters
timeoutThe maximum amount of time to wait. If this value is zero, this method will not wait.

This method does not cause any dispatchers to run. If the underlying dispatch queue does not have an event loop operating on it, this method will deadlock. It is an error for the party responsible for driving the dispatch queue via WaitForEvent or DispatchAllEvents to call this method unless that party first delegates the responsibility elsewhere.

If DispatchQueue::Abort() is called before the dispatcher has been completed, this method will throw an exception. If a dispatcher on the underlying DispatchQueue throws an exception, this method will also throw an exception.

If zero is passed as the timeout value, this method will return true if and only if the queue was empty at the time of the call, ignoring any delayed dispatchers.

If timeout is nonzero, this method will pend a dispatcher to the queue and only return true if this dispatcher is actually dispatched. If the timeout is zero, this method will return true immediately if the queue length is exactly zero.

void DispatchQueue::Barrier ( void  )

Identical to the timed version of Barrier, but does not time out

bool DispatchQueue::Cancel ( void  )

Causes the very first lambda on the dispatch queue to be deleted without running it

Returns
True if a lambda was cancelled, false if the queue was empty when the cancellation attempt was made

This method cannot cancel lambdas that are already being dispatched. As a result, it's possible for this function to return zero even if the dispatch queue length is nonzero before and after the call.

Lambdas are cancelled in the order they are pended. If there are no lambdas ready to execute, then deferred lambdas will be cancelled in the order they are scheduled to run.

int DispatchQueue::DispatchAllEvents ( void  )

Similar to DispatchEvent, but will attempt to dispatch all events currently queued

Returns
The total number of events dispatched
bool DispatchQueue::DispatchEvent ( void  )

Similar to WaitForEvent, but does not block

Returns
True if an event was dispatched, false if the queue was empty when checked

If the dispatch queue is empty, this method will check the delayed dispatch queue.

void DispatchQueue::DispatchEventUnsafe ( std::unique_lock< std::mutex > &  lk)
protected

Similar to DispatchEvent, except assumes that the dispatch lock is currently held

Parameters
lkA lock on m_dispatchLock

This method assumes that the dispatch lock is held and that m_aborted is false. It is an error to call this method without those preconditions met.

size_t DispatchQueue::GetDispatchQueueLength ( void  ) const
inline
Returns
The total number of all ready and delayed events

This method will also count dispatchers that are presently underway or presently being deleted. Thus, calling this method from within a dispatcher, or from that dispatcher's destructor, should always return a size of at least 1.

virtual void DispatchQueue::OnPended ( std::unique_lock< std::mutex > &&  lk)
inlineprotectedvirtual

Utility virtual, called whenever a new event is deferred

The recipient of this call will be running in an arbitrary thread context while holding the dispatch lock. The queue is guaranteed to contain at least one element, and may potentially contain more. The caller MUST NOT attempt to pend any more events during this call, or a deadlock could occur.

Referenced by operator+=().

void DispatchQueue::operator+= ( DispatchQueue &&  rhs)

Extracts the contents of the dispatch queue on the right-hand side for handling by this queue

template<class Rep , class Period >
DispatchThunkDelayedExpressionRel DispatchQueue::operator+= ( std::chrono::duration< Rep, Period >  rhs)
inline

Overload for the introduction of a delayed dispatch thunk

If the passed duration is equal to zero, the returned expression template will pend a lambda to the dispatch queue as though that lambda were added with operator+= without any delay.

DispatchThunkDelayedExpressionAbs DispatchQueue::operator+= ( std::chrono::steady_clock::time_point  rhs)

Overload for absolute-time based delayed dispatch thunk

void DispatchQueue::operator+= ( autowiring::DispatchThunkDelayed &&  rhs)

Directly pends a delayed dispatch thunk

This overload will always succeed and does not consult the dispatch cap

template<class _Fx >
bool DispatchQueue::operator+= ( _Fx &&  fx)
inline

Generic overload which will pend an arbitrary dispatch type

void DispatchQueue::PendExisting ( std::unique_lock< std::mutex > &&  lk,
autowiring::DispatchThunkBase *  thunk 
)
protected

Attaches an element to the end of the dispatch queue without any checks.

Referenced by AddExisting().

bool DispatchQueue::PromoteReadyDispatchersUnsafe ( void  )
protected

Moves all ready events from the delayed queue into the dispatch queue

Returns
True if at least one dispatcher was promoted
void DispatchQueue::Rundown ( void  )

Graceful version of Abort

In a synchronized context, all attached lambdas are guaranteed to be called when this function returns. No guarantees are made in an unsynchronized context.

Any delayed dispatchers that are ready at the time of the call will be invoked. All oter delayed dispatchers will be aborted.

If a dispatcher throws any exception other than dispatch_aborted_exception, the remaining dispatchers will be aborted.

This method may be safely called from within a dispatcher.

This method is idempotent.

void DispatchQueue::SetDispatcherCap ( size_t  dispatchCap)
inlineprotected

Updates the upper bound on the number of allowed pending dispatchers

std::chrono::steady_clock::time_point DispatchQueue::SuggestSoonestWakeupTimeUnsafe ( std::chrono::steady_clock::time_point  latestTime) const

Recommends a point in time to wake up to check for events

Returns
lastestTime, or if there is a dispatch in the delayed queue which will be ready sooner than latestTime, the time_point when that dispatch will be ready to run.

This method is used by clients that are performing manual dispatch operations and wish to know the shortest time they should sleep in order to be guaranteed that, upon waking, a dispatch will be ready to run.

Users should be aware that another dispatch may arrive which is ready to run sooner than the returned suggestion. Notification of this case will be provided to derived classes via the OnPended override.

bool DispatchQueue::TryDispatchEvent ( void  )

Similar to WaitForEvent, but does not block

Returns
True if an event was dispatched, false if the queue was empty when checked

Implements a retry capability for the dispatch queue

If the dispatch queue is empty, this method will check the delayed dispatch queue. Unlike DispatchEvent, if the pended lambda throws an exception, the lambda is put back at the front of the queue rather than being deleted.

This method may break the strict sequentiality guarantee of DispatchQueue if it is used in a concurrent or reentrant use case. Consider a queue consisting of two lambdas, [A, B]. If A throws an exception the first time it is invoked, and B does not throw, and A calls DispatchEvent, then the call order will be [A(throws), B, A].

void DispatchQueue::TryDispatchEventUnsafe ( std::unique_lock< std::mutex > &  lk)
protected

Similar to TryDispatchEvent, except assumes that the dispatch lock is currently held

Parameters
lkA lock on m_dispatchLock

This method assumes that the dispatch lock is held and that m_aborted is false. It is an error to call this method without those preconditions met.

void DispatchQueue::WaitForEvent ( void  )

Waits until a lambda function is ready to run in this thread's dispatch queue, dispatches the function, and then returns.

This method will throw dispatch_aborted_exception if the queue has been aborted at the time of the call

bool DispatchQueue::WaitForEvent ( std::chrono::milliseconds  milliseconds)

Waits until a lambda function in the dispatch queue is ready to run or the specified time period elapses, whichever comes first.

Returns
False if the timeout period elapsed before an event could be dispatched, true otherwise
bool DispatchQueue::WaitForEvent ( std::chrono::steady_clock::time_point  wakeTime)

Waits until a lambda function in the dispatch queue is ready to run or the specified time is reached, whichever comes first.

Returns
False if the timeout period elapsed before an event could be dispatched, true otherwise
void DispatchQueue::WakeAllWaitingThreads ( void  )

Causes all calls to WaitForEvent to return control to their callers

This method will cause any threads blocked in WaitForEvent to wake up and make progress. This can be useful when threads are being used to dispatch work items and it's necessary to wake them in order to handle out-of-queue processing–IE, pool maintenance


The documentation for this class was generated from the following file: