Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   Related Pages  

Wefts::MoaningThread Class Reference

A thread subclass supporting an arbitrary number of joiners. More...

#include <wefts_moaning.h>

Inheritance diagram for Wefts::MoaningThread:

Inheritance graph
[legend]
Collaboration diagram for Wefts::MoaningThread:

Collaboration graph
[legend]
List of all members.

Public Methods

 MoaningThread ()
 Fills member variables with default values.

void * join ()
 Join the current thread, waiting its termination.

virtual void cleanup ()
 Termination hook called by the thread termination process.


Protected Methods

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.


Detailed Description

A thread subclass supporting an arbitrary number of joiners.

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 ad 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:

   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).

Note:
Please, notice that this solution is elegant and functional, but is not very fast. This is meant to be implemented where raw speed is not at stake.


Constructor & Destructor Documentation

Wefts::MoaningThread::MoaningThread  
 

Fills member variables with default values.


Member Function Documentation

void Wefts::MoaningThread::blockJoiners   [protected]
 

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.

void Wefts::MoaningThread::cleanup   [virtual]
 

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.).

Note:
MoaningThread implementation of cleanup is meaningful: subclasses willing to overload this method are advised to call MoaninThread::cleanup() at the end of their method body.

Reimplemented from Wefts::Thread.

void * Wefts::MoaningThread::join   [virtual]
 

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 returns immediately with 0; this is indistinguishable from a join() success and a return value 0 from run(). So it is advisable that joiners receiving a 0 as a return value have other means to check that the MoaningThread has completed its job.

Returns:
the object returned by run() method or 0 on failure.

Reimplemented from Wefts::Thread.

int Wefts::MoaningThread::joiners   [inline, protected]
 

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).

Returns:
count of currently available joiners.


Member Data Documentation

bool Wefts::MoaningThread::m_canJoin [private]
 

When false, joiners are not allowed anymore.

FastCondition Wefts::MoaningThread::m_cond [protected]
 

Condition that regulates access to private data and joiners wakeup.

volatile int Wefts::MoaningThread::m_joiners [private]
 

Counters of currently waiting joiners.


The documentation for this class was generated from the following files:
Generated on Tue Aug 5 18:09:03 2003 for Wefts by doxygen1.2.18