#include <wefts_moaning.h>
Inheritance diagram for Wefts::MoaningThread:
First of all, I want to extend my excuses to all the readers for the not-so-technical (or too much poethical) name of this class, but I really couldn't resist :-), moreover I find this name pretty self-explanatory.
A MoaningThread is a thread that "moans" just before dying, so that any listener willing to listen will know about that fact.
I've always found limiting the fact that ONLY ONE thread is able to join another thread; implementing a condition that signals when the thread is terminating is trivial, so it is obvous that low-level routines should not bother with that, but a full featured threading library (as Wefts) should have a way to make more than a thread to synchronize with another thread's end.
A moaning thread is automatically detached at cleanup sequence. This means that the joiners have not the need to syncronize on object destruction; but this also means that any data held in the MoaningThread class is destroyed before the joiners has a chance to get it.
To allow the results of a MoaningThread to bypass its lifetime span, it is necessary to do one of the following:
Overloaded classes should accept somewhere (before starting) a variable or an object reference that is created outside their scope, and that is not destroyed with them. This objects will be then manipulated by their run method, and they will be ready for joiners inspection at thread termination.
Another way is to return a dynamically allocated value at run() termination; the standard behavior that clears the return value of detached Thread's run() is here overloaded so that all the joiners receive the same object. The joiners must then have a way to decide when they don't need the object anymore.
The Wefts::Referenced utility class has a threadsafe mechanism so that joiners are able to cleanly release this returned object, in a fashon like this:
MyMoaningThread th; // derived from (guess) MoaningThread MyRefData *result; // derived from Referenced th.start(); result = (MyRefData *) th->join(); ... //work on result; as Referenced is derived from RWLock, it can also be // synchronized with lockRead() and lockWrite() against other joiners. ... result->decRef(); // if last referencing result, the object is destroyed.
Since the MoaningThreads knows how many joiners are waiting, it can setup the reference count of the returned variable correctly:
void *MyMoaningThread::run() { ... // going to end, // we anticipate a little "official" termination, // so no joiners are now allowed blockJoiners(); // joiners count is now threadsafe MyRefData result = new MyRefData( joiners() ); ... add to result the thing you want to have your joiners know return result; }
After that blockJoiners() called, no more joiner is allowed to join, and it receives 0 as return value if it tries to. (Important: see blockJoiners() notices).
Public Member Functions | |
MoaningThread () | |
Fills member variables with default values. | |
void * | join () throw ( NotJoinableError ) |
Join the current thread, waiting its termination. | |
virtual void | executionEnd () |
Termination hook called by the thread termination process. | |
virtual void | handleCleanup (int code, void *caller=0) |
Used by condition wait while joning. | |
Protected Member Functions | |
int | joiners () |
Returns currently waiting joiners. | |
void | blockJoiners () |
Forbids threads from joining to this MoaningThreads from this moment. | |
Protected Attributes | |
FastCondition | m_cond |
Condition that regulates access to private data and joiners wakeup. | |
Private Attributes | |
bool | m_canJoin |
When false, joiners are not allowed anymore. | |
volatile int | m_joiners |
Counters of currently waiting joiners. | |
volatile bool | m_dying |
true while dying |
|
Fills member variables with default values.
|
|
Forbids threads from joining to this MoaningThreads from this moment. This function uses m_cond; do not call it while already holding that mutex. Programmers are warned that blockJoin() must be called only after that the thread has done anything relevant, and just before termination sequence. This is because a thread trying to join after blockJoin() will not be blocked and will receive a return value of 0; this is indistinguishable from the thread being already terminated and returning 0, so if the joiners does not rely on the return value, everything else the MoaningThread must accomplish before terminating must be complete, or foreing joiners may be fooled. |
|
Termination hook called by the thread termination process. This method is called just before the thread terminates, and if the thread is detached, also just before thread destructor. This gives a chance to this thread to provide cleanup actions (as freeing mutexes not previously releases, close files and connections, logging the imminent termination, signaling in member variables things that an eventual join()er should know etc.).
Reimplemented from Wefts::Thread. |
|
Used by condition wait while joning. If joiners are canceled while joning the moaner, this cleanup ensures that they release both join count and mutexes Implements Wefts::CleanupHandler. |
|
Join the current thread, waiting its termination. MoaningThread implementation of join allows more than one joiner to wait for thread termination. On success, the calling thread is blocked until the thread terminates, and returns the value returned by the run() method. On failure, this metod not ownings a NotJoinableError.
Reimplemented from Wefts::Thread. |
|
Returns currently waiting joiners. This method is not locked or protected; caller must ensure that the count of joiners is still valid when it is able to process the data by locking m_cond, or by issuing blockJoiners() (so that no more joiners are allow to join from that moment on).
|
|
When false, joiners are not allowed anymore.
|
|
Condition that regulates access to private data and joiners wakeup.
|
|
true while dying
|
|
Counters of currently waiting joiners.
|