dlr::thread::DistributionQueue< Type > Class Template Reference

This class implements FIFO-style communication between one or more producer threads and multiple consumer threads, so that each queue item is consumed by exactly one thread. More...

#include <distributionQueue.h>

Inheritance diagram for dlr::thread::DistributionQueue< Type >:

Inheritance graph
[legend]
Collaboration diagram for dlr::thread::DistributionQueue< Type >:

Collaboration graph
[legend]
List of all members.

Public Types

typedef ClientID< Type > ClientID
 Each thread that interacts with a particular DistributionQueue instance must create a ClientID instance, and then register with the DistributionQueue by calling the registerClient() member function of that DistributionQueue instance, passing the clientID instance as an argument.

Public Member Functions

 DistributionQueue (size_t maximumLength, size_t numberOfClients=2)
 This constructor specifies the maximum length of the FIFO.
 DistributionQueue (const DistributionQueue< Type > &source)
 The copy constructor does a shallow copy.
virtual ~DistributionQueue ()
 Destroys the DistributionQueue instance and releases any resources.
DistributionQueue< Type > & operator= (const DistributionQueue< Type > &source)
 The assignment operator does a shallow copy.
void bufferBack (const ClientID &clientID)
 This member function copies the tail element of the DistributionQueue into an interal buffer, and then removes it from the queue so that other threads can no longer access it.
bool bufferBack (const ClientID &clientID, double timeout)
 This member function copies the tail element of the DistributionQueue into an interal buffer, and then removes it from the queue so that other threads can no longer access it.
void clear ()
 This member function empties the queue.
void copyBuffer (const ClientID &clientID, Type &target)
 This member function copies the buffered element (see member function bufferBack() from the internal buffer into user code.
size_t getMaximumLength ()
 This member function returns the length at which the DistributionQueue instance will stop accepting new elements.
void lockBack (const ClientID &clientID)
 This member function locks the DistributionQueue instance so that items cannot be pushed or removed by other threads.
bool lockBack (const ClientID &clientID, double timeout)
 This member function locks the DistributionQueue instance so that items cannot be pushed or removed by other threads.
void pushFront (const ClientID &clientID, const Type &element)
 This member function is called by producer threads to add elements to the head of the queue.
void registerClient (ClientID &clientID, const std::string &clientName="anonymous")
 This member function introduces a thread to a DistributionQueue instance.
void unlockBack (const ClientID &clientID)
 This member function releases a lock acquired by lockBack().
void makeCopyable (bool copyableFlag=true)
 This member function enables (or disables) copying of the Monitor instance.

Protected Member Functions

void copyOther (const Monitor &other)
 This protected member function is called by the copy constructor and assignment operator in order to copy another Monitor instance in a thread-safe way.
Condition createCondition (bool doInitialize=true)
 This protected member function creates a condition to be used for communicating with other threads.
Token getToken ()
 This protected member function requests, and waits for, a virtual "token" which is shared between threads.
Token getToken (double timeout)
 This protected member function requests, and waits for, a virtual "token" which is shared between threads.
void releaseResources ()
 This protected member function is called by the destructor and assignment operator to decrement reference counts, etc.
void signalOne (Condition &condition)
 This protected member function wakes up one of the threads which is waiting on the specified condition.
void signalAll (Condition &condition)
 This protected member function wakes up all of the threads which are waiting on the specified condition.
void wait (Condition &condition, Token &token)
 This protected member function waits until signalOne() or signalAll() is called by another thread with the same Condition as its argument.
bool wait (Condition &condition, Token &token, double timeout)
 This protected member function waits until signalOne() or signalAll() is called by another thread with the same Condition as its argument.

Detailed Description

template<class Type>
class dlr::thread::DistributionQueue< Type >

This class implements FIFO-style communication between one or more producer threads and multiple consumer threads, so that each queue item is consumed by exactly one thread.

If you want each item on the queue to be consumed once by each consumer thread, you should use a BroacastQueue instead of a DistributionQueue.

Create the DistributionQueue instance before instantiating the producer and consumer threads, and provide each thread with a copy of, pointer to, or reference to the DistributionQueue. Producers can stuff the FIFO by the pushFront() member function. Consumers can extract data from the other end using the bufferBack() and getBuffer() member functions. The bufferBack()/getBuffer() combination is used instead of the more traditional copyBack()/popBack() interface in order to allow an interface which is both thread-safe and exception-safe. Note that a careful analysis of exception safety has not been done. The interface was selected so as not to preclude exception safety.

During normal usage all client threads are expected to stay within maximumLength elements of the head. If a consumer thread falls more than maximumLength elements behind the head, then the next call to push_back() will throw an overflow exception. This behavior may change in the future.

Definition at line 57 of file distributionQueue.h.


Member Typedef Documentation

template<class Type>
typedef ClientID<Type> dlr::thread::DistributionQueue< Type >::ClientID

Each thread that interacts with a particular DistributionQueue instance must create a ClientID instance, and then register with the DistributionQueue by calling the registerClient() member function of that DistributionQueue instance, passing the clientID instance as an argument.

The same ClientID instance must be passed as an argument in subsequent interactions with that DistributionQueue instance. The ClientID instance identifies the thread to the DistributionQueue, and simplifies internal bookkeeping.

Definition at line 73 of file distributionQueue.h.


Constructor & Destructor Documentation

template<class Type>
dlr::thread::DistributionQueue< Type >::DistributionQueue ( size_t  maximumLength,
size_t  numberOfClients = 2 
) [inline]

This constructor specifies the maximum length of the FIFO.

Parameters:
maximumLength This argument specifies the maximum length of the FIFO. All consumers are expected to call this->popBack() frequently enough to stay within this many elements of the head of the FIFO. If consumers fail to keep up, then calls to pushFront(), bufferBack() or lockBack() may throw exceptions.
numberOfClients This argument can be used to specify the number of threads that will interact with the DistributionQueue instance. If this argument is not provided, the DistributionQueue will function normally, except that memory usage will likely be higher, and execution time for some member function calls may be increased.

Definition at line 398 of file distributionQueue.h.

References DLR_THROW, and dlr::thread::Monitor::makeCopyable().

template<class Type>
dlr::thread::DistributionQueue< Type >::DistributionQueue ( const DistributionQueue< Type > &  source  )  [inline]

The copy constructor does a shallow copy.

Operating on the copy has exactly the same effect as operating on the original.

Parameters:
source The DistributionQueue instance to be copied.

Definition at line 438 of file distributionQueue.h.

References dlr::thread::Monitor::getToken(), dlr::thread::DistributionQueue< Type >::m_bufferArrayPtr, dlr::thread::DistributionQueue< Type >::m_clientNameMapPtr, dlr::thread::DistributionQueue< Type >::m_dataArray, dlr::thread::DistributionQueue< Type >::m_headChangedCondition, dlr::thread::DistributionQueue< Type >::m_headIndexPtr, dlr::thread::DistributionQueue< Type >::m_isLockedCondition, dlr::thread::DistributionQueue< Type >::m_isLockedPtr, dlr::thread::DistributionQueue< Type >::m_maxNumberOfClientsPtr, dlr::thread::DistributionQueue< Type >::m_numberOfClientsPtr, dlr::thread::DistributionQueue< Type >::m_referenceCountPtr, dlr::thread::DistributionQueue< Type >::m_size, and dlr::thread::DistributionQueue< Type >::m_tailIndexPtr.

template<class Type>
dlr::thread::DistributionQueue< Type >::~DistributionQueue (  )  [inline, virtual]

Destroys the DistributionQueue instance and releases any resources.

Definition at line 476 of file distributionQueue.h.

References dlr::thread::Monitor::getToken().


Member Function Documentation

template<class Type>
DistributionQueue< Type > & dlr::thread::DistributionQueue< Type >::operator= ( const DistributionQueue< Type > &  source  )  [inline]

The assignment operator does a shallow copy.

After assignment, operating on the copy has exactly the same effect as operating on the original.

Parameters:
source The DistributionQueue instance to be copied.
Returns:
A reference to *this.

Definition at line 503 of file distributionQueue.h.

References dlr::thread::Monitor::copyOther(), dlr::thread::Monitor::getToken(), and dlr::thread::Monitor::operator=().

template<class Type>
void dlr::thread::DistributionQueue< Type >::bufferBack ( const ClientID clientID  )  [inline]

This member function copies the tail element of the DistributionQueue into an interal buffer, and then removes it from the queue so that other threads can no longer access it.

Repeated calls to bufferBack() will copy and remove subsequent elements from the queue.

Each thread has its own buffer, so elements can be buffered by two or more consumer threads with no conflict.

If all items have been removed from the queue, bufferBack() will block, waiting for a new element to be copied onto the queue.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().

Definition at line 523 of file distributionQueue.h.

References dlr::thread::DistributionQueue< Type >::lockBack(), dlr::thread::ClientID< Type >::m_idNumber, and dlr::thread::DistributionQueue< Type >::unlockBack().

template<class Type>
bool dlr::thread::DistributionQueue< Type >::bufferBack ( const ClientID clientID,
double  timeout 
) [inline]

This member function copies the tail element of the DistributionQueue into an interal buffer, and then removes it from the queue so that other threads can no longer access it.

It is just like void bufferBack(const ClientID&), with the exception that it will not block for longer than the specified timeout.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().
timeout This argument specifies the total amount of time that bufferBack is permitted to block while waiting for access to the queue and/or waiting for a new element to become available. If timeout is less than or equal to zero then the call will return immediately.

Definition at line 550 of file distributionQueue.h.

References dlr::thread::ClientID< Type >::m_idNumber, and dlr::thread::DistributionQueue< Type >::unlockBack().

template<class Type>
void dlr::thread::DistributionQueue< Type >::clear (  )  [inline]

This member function empties the queue.

Definition at line 579 of file distributionQueue.h.

References dlr::thread::Monitor::getToken().

template<class Type>
void dlr::thread::DistributionQueue< Type >::copyBuffer ( const ClientID clientID,
Type &  target 
) [inline]

This member function copies the buffered element (see member function bufferBack() from the internal buffer into user code.

Repeated calls to copyBuffer() will copy the same element until a new call to bufferBack() is made. If copyBuffer() is called before any calls to bufferBack() are made, a LogicException will be thrown.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().
target This reference argument is used to return a copy of the tail element in the queue.

Definition at line 594 of file distributionQueue.h.

References dlr::thread::ClientID< Type >::m_idNumber.

template<class Type>
size_t dlr::thread::DistributionQueue< Type >::getMaximumLength (  )  [inline]

This member function returns the length at which the DistributionQueue instance will stop accepting new elements.

Returns:
The return value is the maximum number of elements that consumer threads can fall behind without causing problems.

Definition at line 207 of file distributionQueue.h.

template<class Type>
void dlr::thread::DistributionQueue< Type >::lockBack ( const ClientID clientID  )  [inline]

This member function locks the DistributionQueue instance so that items cannot be pushed or removed by other threads.

By never using this member function, you will avoid many headaches, so please use copyBack() instead if at all possible. Member function lockBack() is provided to handle a few extreme circumstances.

Member function lockBack() will block until the lock is acquired. If the queue is empty, lockBack() will sleep until data is available, and then block until the lock is acquired.

An example of a circumstance in which it makes sense to use lockBack() is when the distributionQueue elements contain pointers or references to data, so that copyBuffer() gives you a copy of a pointer, but doesn't actually copy the data. Presumably, the producer threads are smart enough not to de-allocate the data until the element drops of the end of the queue, so you can be confident that you're getting a good pointer at the time of the bufferBack() call, but there's nothing to stop the associated data from being de-allocated) after the call, when the consumer is still trying to access it. In this case, it makes sense to call lockBack() in the following sequence.

myDistributionQueue.lockBack(myClientID);

myDistributionQueue.bufferBack(myClientID);

myDistributionQueue.copyBuffer(myClientID, myLocalElement);

// Code here does accesses to the referenced data.

myDistributionQueue.unlockBack(myClientID);

Member function bufferBack() is smart enough not to deadlock when copying an already-locked element.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().

Definition at line 605 of file distributionQueue.h.

References dlr::thread::Monitor::getToken(), and dlr::thread::Monitor::wait().

Referenced by dlr::thread::DistributionQueue< Type >::bufferBack().

template<class Type>
bool dlr::thread::DistributionQueue< Type >::lockBack ( const ClientID clientID,
double  timeout 
) [inline]

This member function locks the DistributionQueue instance so that items cannot be pushed or removed by other threads.

By never using this member function, you will avoid many headaches. It is just like void lockBack(const ClientID&), with the exception that it will not block for longer than the specified timeout.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().
timeout This argument controls how long the call to lockBack() will block waiting for the lock to become available. If timeout is less than or equal to zero, then the call to will return immediately.
Returns:
The return value is true if a lock was established, and false otherwise.

Definition at line 629 of file distributionQueue.h.

References dlr::portability::getCurrentTime(), and dlr::thread::Monitor::getToken().

template<class Type>
void dlr::thread::DistributionQueue< Type >::pushFront ( const ClientID clientID,
const Type &  element 
) [inline]

This member function is called by producer threads to add elements to the head of the queue.

When the element is added to the queue, it is copied, not referenced.

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().
element This argument is the element to be copied onto the head of the DistributionQueue instance.

Definition at line 663 of file distributionQueue.h.

References DLR_THROW, dlr::thread::Monitor::getToken(), dlr::thread::ClientID< Type >::m_idNumber, and dlr::thread::Monitor::signalAll().

template<class Type>
void dlr::thread::DistributionQueue< Type >::registerClient ( ClientID clientID,
const std::string &  clientName = "anonymous" 
) [inline]

This member function introduces a thread to a DistributionQueue instance.

The thread should create a ClientID instance, and then call registerClient() exactly once, passing the ClientID instance as the first argument. This same ClientID instance should be used by the calling thread in subsequent interactions with the DistributionQueue instance. Using the same ClientID instance to interact with another DistributionQueue instance (besides *this) is bad, and will have undefined results.

Note that the ClientID class is currently not copyable. This means the client thread should create the ClientID in an outer scope and then pass it by reference into any inner scopes that need access to the DistributionQueue.

Parameters:
clientID This argument is the clientID that will be used to identify the calling thread to the DistributionQueue in future interactions.
clientName This argument specifies a name for the thread. It is useful to specify a unique name for each thread that interacts with a DistributionQueue instance because this will make it easier to debug any exceptions thrown by the DistributionQueue member functions.

Definition at line 716 of file distributionQueue.h.

References dlr::thread::Monitor::getToken(), dlr::thread::ClientID< Type >::m_count, dlr::thread::ClientID< Type >::m_idNumber, and dlr::thread::ClientID< Type >::m_index.

template<class Type>
void dlr::thread::DistributionQueue< Type >::unlockBack ( const ClientID clientID  )  [inline]

This member function releases a lock acquired by lockBack().

Parameters:
clientID This argument identifies the calling thread to the DistributionQueue. It should have been previously registered with the DistributionQueue by calling member function registerClient().

Definition at line 756 of file distributionQueue.h.

References dlr::thread::Monitor::getToken().

Referenced by dlr::thread::DistributionQueue< Type >::bufferBack().

void dlr::thread::Monitor::makeCopyable ( bool  copyableFlag = true  )  [inline, inherited]

This member function enables (or disables) copying of the Monitor instance.

Parameters:
copyableFlag When this argument is left at its default value of true, a call to makeCopyable will enable copying of the Monitor instance. Explicitly setting this argument to false will reverse the effect of makeCopyable() and disable copying.

Definition at line 238 of file monitor.h.

Referenced by dlr::thread::DistributionQueue< Type >::DistributionQueue().

void dlr::thread::Monitor::copyOther ( const Monitor other  )  [protected, inherited]

This protected member function is called by the copy constructor and assignment operator in order to copy another Monitor instance in a thread-safe way.

Parameters:
other This argument is the Monitor instance to be copied.

Definition at line 282 of file monitor.cpp.

References DLR_THROW, dlr::thread::Monitor::getToken(), dlr::thread::Monitor::m_boostConditionVectorPtr, dlr::thread::Monitor::m_isCopyable, dlr::thread::Monitor::m_referenceCountPtr, and dlr::thread::Monitor::m_tokenMutexPtr.

Referenced by dlr::thread::Monitor::Monitor(), dlr::thread::Monitor::operator=(), and dlr::thread::DistributionQueue< Type >::operator=().

Condition dlr::thread::Monitor::createCondition ( bool  doInitialize = true  )  [protected, inherited]

This protected member function creates a condition to be used for communicating with other threads.

If argument doInitialize is true, then the resources allocated by createCondition() are not returned to the system until the Monitor instance is destroyed.

Special care must be taken when creating Condition objects in copy constructors. The member initialization list of the copy constructor should create a dummy condition by setting argument doInitialize to false, and the copying of the condition from the to-be-copied Monitor instance should be done in the body of the copy constructor, where it can be protected by creation of a Token instance. Please refer to the class documentation for Monitor to see an example.

Parameters:
doInitialize This parameter should be set to false in the parameter initializion lists of copy constructors in order to suppress allocation of resources. Note(xxx): is this really necessary now that condition has no reference count?
Returns:
The return value is a condition object.

Definition at line 306 of file monitor.cpp.

References dlr::thread::Monitor::getToken().

Token dlr::thread::Monitor::getToken (  )  [inline, protected, inherited]

This protected member function requests, and waits for, a virtual "token" which is shared between threads.

The caller will block until the it gets the token, at which point all other callers will block until the token goes out-of-scope in the callers thread.

Returns:
The return value represents the virtual token.

Definition at line 292 of file monitor.h.

Referenced by dlr::thread::DistributionQueue< Type >::clear(), dlr::thread::Monitor::copyOther(), dlr::thread::Monitor::createCondition(), dlr::thread::DistributionQueue< Type >::DistributionQueue(), dlr::thread::DistributionQueue< Type >::lockBack(), dlr::thread::DistributionQueue< Type >::operator=(), dlr::thread::DistributionQueue< Type >::pushFront(), dlr::thread::DistributionQueue< Type >::registerClient(), dlr::thread::Monitor::releaseResources(), dlr::thread::DistributionQueue< Type >::unlockBack(), and dlr::thread::DistributionQueue< Type >::~DistributionQueue().

Token dlr::thread::Monitor::getToken ( double  timeout  )  [inline, protected, inherited]

This protected member function requests, and waits for, a virtual "token" which is shared between threads.

It is just like getToken(), with the exception that it will not block for longer than the specified timeout. If the timout expires before the token is acquired, a TimeoutException is thrown.

Returns:
The return value represents the virtual token.

Definition at line 305 of file monitor.h.

void dlr::thread::Monitor::releaseResources (  )  [protected, inherited]

This protected member function is called by the destructor and assignment operator to decrement reference counts, etc.

Definition at line 325 of file monitor.cpp.

References dlr::thread::Monitor::getToken().

Referenced by dlr::thread::Monitor::operator=(), and dlr::thread::Monitor::~Monitor().

void dlr::thread::Monitor::signalOne ( Condition condition  )  [inline, protected, inherited]

This protected member function wakes up one of the threads which is waiting on the specified condition.

If no thread is waiting, then signalOne() does nothing. The awakened thread will become active after the current thread releases the token. Note that this behavior is different from the behavior of signal() in Hoare's paper: in Hoare's formulation, the awakened thread becomes active immediately, and control returns to the current thread after the awakened thread releases the token. This difference is immaterial if you follow the usual convention of only calling signalOne() as the last line of a member function.

Parameters:
condition This argument is the condition to signal.

Definition at line 332 of file monitor.h.

References dlr::thread::Condition::signalOne().

void dlr::thread::Monitor::signalAll ( Condition condition  )  [inline, protected, inherited]

This protected member function wakes up all of the threads which are waiting on the specified condition.

If no thread is waiting, then signalAll() does nothing. The awakened threads will become active (each in turn) after the current thread releases the token. Note that signalAll() has no analog in Hoare's paper.

Parameters:
condition This argument is the condition to signal.

Definition at line 346 of file monitor.h.

References dlr::thread::Condition::signalAll().

Referenced by dlr::thread::DistributionQueue< Type >::pushFront().

void dlr::thread::Monitor::wait ( Condition condition,
Token token 
) [inline, protected, inherited]

This protected member function waits until signalOne() or signalAll() is called by another thread with the same Condition as its argument.

Parameters:
condition This argument is the condition on which to wait.
token This argument is a token instance, which should have been acquired using getToken() at the beginning of the member function which is now calling wait().

Definition at line 363 of file monitor.h.

References dlr::thread::Condition::wait().

Referenced by dlr::thread::DistributionQueue< Type >::lockBack().

bool dlr::thread::Monitor::wait ( Condition condition,
Token token,
double  timeout 
) [inline, protected, inherited]

This protected member function waits until signalOne() or signalAll() is called by another thread with the same Condition as its argument.

It is just like wait(Condition&), with the exception that it will not block for longer than the specified timeout.

Parameters:
condition This argument is the condition on which to wait.
token This argument is a token instance, which should have been acquired using getToken() at the beginning of the member function which is now calling wait().
timeout This argument specifies how long to wait for the condition to be satisfied.
Returns:
The return value is false if the timout expires, true otherwise.

Definition at line 387 of file monitor.h.

References dlr::thread::Condition::wait().


The documentation for this class was generated from the following file:
Generated on Mon Jul 9 20:34:22 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2