#include <monitor.h>
Inheritance diagram for dlr::thread::Monitor:

Public Member Functions | |
| Monitor () | |
| Default constructor. | |
| Monitor (const Monitor &other) | |
| The copy constructor does a shallow copy. | |
| virtual | ~Monitor () |
| Destroys the Monitor instance and releases any resources. | |
| Monitor & | operator= (const Monitor &other) |
| The assignment operator does a shallow copy. | |
| 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. | |
A. R. Hoare in [1]. Use this class as follows:
Here's an example of a simple monitor, based on the first example in Hoares paper. It turns out that this example could be more easily implemented using just a semaphore or a lock, but it's useful anyway. Note that the signal() method differs slightly from the behavior described in the paper (see the documentation for Monitor::signal()) but that this difference is insignificant if we adhere to the usual convention of only calling signal() at the end of a function.
class SimpleMonitor: public Monitor { public: SimpleMonitor() : Monitor(), m_isBusy(false), m_nonbusyCondition(Monitor::createCondition()) {} void acquire() { Token token = this->getToken(); if(this->m_isBusy) { this->wait(this->m_nonbusyCondition, token); } this->m_isBusy = true; } void release() { Token token = this->getToken(); this->m_isBusy = false; this->signalOne(this->m_nonbusyCondition, token); } private: bool m_isBusy; Condition m_nonbusyCondition; };
Monitor is also useful as a parent class for objects to which access should be serialized. In this case, you may choose to completely ignore the wait(), signalOne() and signalAll() methods and just use the getToken() method to ensure that the object interacts with only one thread at a time.
Monitor is reference counted, so that interacting with a copy of a monitor object has the same effect as interacting with the monitor object itself. This increases the flexibility of the class, but also opens the door to lots of headaches: data members of derived classes will not be shared between copies unless you make them so by using pointers, reference counting, etc. For this reason, copying is disabled by default. If you really want to copy a Monitor instance, you can enable copying by calling the makeCopyable() member function.
If you do decide to copy a Monitor instance, the copy constructor and assignment operator should be sure to copy the class in a thread safe way. The following example illustrates this, and shows how to avoid wasting resources when copying Condition instances.
SimpleMonitor(const SimpleMonitor& other) : Monitor(other), m_isBusy(), m_nonbusyCondition(Monitor::createCondition(false)) { Token token = this->getToken(); m_isBusy = other.m_isBusy; m_nonBusyCondition = other.m_nonBusyCondition; }
Definition at line 186 of file monitor.h.
| dlr::thread::Monitor::Monitor | ( | ) |
| dlr::thread::Monitor::Monitor | ( | const Monitor & | other | ) |
The copy constructor does a shallow copy.
Operating on the copy has exactly the same effect as operating on the original. For more information about copying monitors, please read the class-level documentation for Monitor.
| other | The Monitor instance to be copied. |
Definition at line 241 of file monitor.cpp.
References copyOther().
| dlr::thread::Monitor::~Monitor | ( | ) | [virtual] |
Destroys the Monitor instance and releases any resources.
Definition at line 253 of file monitor.cpp.
References releaseResources().
The assignment operator does a shallow copy.
After assignment, operating on the copy has exactly the same effect as operating on the original.
| other | The Monitor instance to be copied. |
Definition at line 262 of file monitor.cpp.
References copyOther(), DLR_THROW, and releaseResources().
Referenced by dlr::thread::DistributionQueue< Type >::operator=().
| void dlr::thread::Monitor::makeCopyable | ( | bool | copyableFlag = true |
) | [inline] |
This member function enables (or disables) copying of the Monitor instance.
| 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] |
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.
| other | This argument is the Monitor instance to be copied. |
Definition at line 282 of file monitor.cpp.
References DLR_THROW, getToken(), m_boostConditionVectorPtr, m_isCopyable, m_referenceCountPtr, and m_tokenMutexPtr.
Referenced by Monitor(), operator=(), and dlr::thread::DistributionQueue< Type >::operator=().
| Condition dlr::thread::Monitor::createCondition | ( | bool | doInitialize = true |
) | [protected] |
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.
| 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? |
Definition at line 306 of file monitor.cpp.
References getToken().
| Token dlr::thread::Monitor::getToken | ( | ) | [inline, protected] |
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.
Definition at line 292 of file monitor.h.
Referenced by dlr::thread::DistributionQueue< Type >::clear(), copyOther(), 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(), releaseResources(), dlr::thread::DistributionQueue< Type >::unlockBack(), and dlr::thread::DistributionQueue< Type >::~DistributionQueue().
| Token dlr::thread::Monitor::getToken | ( | double | timeout | ) | [inline, protected] |
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.
| void dlr::thread::Monitor::releaseResources | ( | ) | [protected] |
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 getToken().
Referenced by operator=(), and ~Monitor().
| void dlr::thread::Monitor::signalOne | ( | Condition & | condition | ) | [inline, protected] |
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.
| 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] |
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.
| 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().
This protected member function waits until signalOne() or signalAll() is called by another thread with the same Condition as its argument.
| 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] |
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.
| 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. |
Definition at line 387 of file monitor.h.
References dlr::thread::Condition::wait().
1.5.2