Wefts::CriticalSection Class Reference
[Advanced Syncronization constructs]

#include <wefts_critical.h>

Inheritance diagram for Wefts::CriticalSection:

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

Collaboration graph
[legend]
List of all members.

Detailed Description

Critical sections implementation support.

Note:
Critical sections of "Wefts" are NOT to be confused with MS-Windows CRITICAL_SECTION objects. MS-Windows CRITICAL_SECTION are fast reentrant intra-process mutexes. Indeed, the term CRITICAL_SECTION applied to mutexes in this way is not following standard multithreading theory nomenclature.
Critical sections are portions of the code in which only one thread is allowed to run; when a thread enters a critical sections, it must be guaranteed that all the other threads of the process are not running. A thread working in a critical section of the code is guaranteed to be the only one thread of the process being active at the moment.

This concept is mainly provided for higher level languages in which some sort of automatic processing has to be taken outside the control of the final programmers. In example, on Virtual Machine based high level languages, a form of garbage collecting is often provided. Some fast and efficient implementations of the garbage collector need to be handled by a thread which can count of the memory to stay untouched for the whole duration of collection loops.

Moreover, suspension of other threads may be targeted only to some kind of threads; in the example, the garbage collector would be willing to stop all related VM threads, but the applications may know that other threads are not affecting collection operations, and so there isn't the need to stop them.

At low level, if the application wills to maintain tread safety, it is necessary the active cooperation of target suspendable threads. Threads that may be stopped if a certain critical section is entered by another thread must grant that they can be suspended at a certain point, so that their suspension happens safely, after releasing all the resources that the critical section user may need.

For this reason, this class is called "critical section implementation support". There is no (safe) way to provide a raw suspension of unwilling threads; instead, this class provide an easy interface to grant thread safe suspension of threads willing to cooperate with portion of code needing critical section semantic. This also helps to provide critical sections for higher level languages, or scripting languages, that may be implemented by using wefts as multithreading support.

This is the support provided: a thread willing to cooperate on a determinate critical section will call the CriticalSection::signIn() method at its begin, or when its cooperation becomes necessary. If the critical section is not currently being held, the call will return immediately, and the calling thread will be now accounted for critical section usage, else the call will return when the critical section is released.

Then, whenever the cooperation of the thread is not needed anymore, it will call the CriticalSection::signOut() method; this call is not blocking.

A thread that may pause for a long time should sign out before doing the pause, and sign in again after the pause has elapsed; also, a thread that knows that it's going to take some long operations in which the data guarded by the critical section is not used should sign out, so to signal other threads willing to enter the critical section that they are temporarily out of business.

If a thread is canceled while it's signed in for a critical section, the thread is not automatically signed out; it's necessary to call the CriticalSection::signOut() method in it's cleanup routine to avoid deadlocks due to waits for critical sections waiting threads never become clear to go.

A thread willing to enter a critical section must call the method CriticalSection::enter(). This will block the calling thread until it is the only thread interested in the critical section. To prevent other threads to sign in the section while the thread is waiting to enter it, a boolean true parameter may be passed to the enter method; normally, the other threads will be able to sign out and in again up to the moment that the calling thread is waked up and able to enter the section, but using this option the critical section requestor will prevent other threads to sign in even if it has not yet entered it. When the thread is done, it must call CriticalSection::leave() to allow other threads to sign in or enter again.

If more than a thread is willing to enter a critical section, and if they are using the resources the critical section holders may use inside and outside the critical section, then they should sign in normally and sign out right before try to enter the section. Otherwise, if the thread wishing to achieve a critical section uses the resources only inside the section, they need not to sign in.

CriticalSection class provides also timed waits on enter method and a try semantic that checks for section achieve being immediately available.

Finally, if a cooperating thread, one of which signed in for the section, is engaged in some long operation in which periodically holds the resources, it should call from time to time the CriticalSection::checkPoint() method. This won't sign out the resource, but it will eventually suspend resource control if there is a thread waiting for critical section entrance.

Enter (both timed version and infinite wait versions), signIn and checkPoint methods are cancellation points. The thread must be clean (or push an adequate cleanup handler) before calling them; checkPoint() automatically signs out the resources if a cancellation is issued, but enter() does not (as the calling thread is not required to sign in to call it). Anyhow, it's necessary to sign out a signed in thread before calling enter() or that thread will infinitely wait for itself to sign out.


Public Member Functions

 CriticalSection ()
 Initializes the critical section.

bool enter (bool fence=true, bool timed=false, double time=0)
 Enters the critical section.

bool enter (double time, bool fence=true)
 Enter a critical section for a maximum of a given amount of seconds.

bool tryEnter ()
 Try to enter a critical section and returns immediately.

void leave ()
 Leaves the critical sections, allowing other threads to proceed.

void signIn ()
 Claims the critical section to be not enterable.

void signOut ()
 Signals that the current thread is not interested in the critical section anymore.

void checkPoint ()
 Allows critical section entering if possible.

virtual void handleCleanup (int code, void *caller=0)

Private Attributes

int m_signedIn
 Count of signed in threads.

int m_signRequests
 Count of threads wishing to sign in.

int m_enterRequests
 Count of threads wishing enter the critical section.

int m_fenceCount
 Fence count for enter requests.

bool m_achieved
 True if currently achieved by a thread.

Mutex m_mutex
 Mutex to protect internal data.

Condition m_signinCond
 Condition for threads wishing to sign in.

Condition m_enterCond
 Condition for threads willing to enter the section.


Constructor & Destructor Documentation

Wefts::CriticalSection::CriticalSection  ) 
 

Initializes the critical section.

This is not an inlined method.


Member Function Documentation

void Wefts::CriticalSection::checkPoint  ) 
 

Allows critical section entering if possible.

If the current thread does not wants to sign out, but it is doing some interruptible but long work on the data set guarded by the critical section, it may wish to call this method at some point, or periodically.

This method will block and allow the thread(s) that asked for critical section entering to proceed, if they risen a fence or if this is the only currently signed in thread.

Note:
In this case, this becomes a cancellation point. An eventual cancellation during a check point wait will automatically signout this thread form the section, but the thread will have to do it's own cleanup with Thread::pushCleanup() method, or to prevent cancellation with Thread::setCancel().

bool Wefts::CriticalSection::enter double  time,
bool  fence = true
[inline]
 

Enter a critical section for a maximum of a given amount of seconds.

Works as enter( bool ), except for the fact that it returns false if the thread is not able to enter the critical section in the given time, or true if the section is achieved.

Note:
This method is a cancellation point. Be sure to clean the thread or to push a cleanup routine (or to disable cancellation) before calling it.
Parameters:
time seconds to wait for the critical section to be enterable.
fence true to rise the sign in fence.
Returns:
true if the thread entered the section, false otherwise.

bool Wefts::CriticalSection::enter bool  fence = true,
bool  timed = false,
double  time = 0
 

Enters the critical section.

The calling thread will be suspended until the count of signed in threads will reach 0, and the critical section is not achieved by other threads.

If the fence parameter is true, a fence is risen; this fence blocks other threads willing to sign in, and blocks also threads entering check points. Anyhow, it won't prevent other threads from entering the critical section. In example, if two threads try to enter a critical section, and one of them rises the fence, the other threads willing to sign in or entering a checkpoint will be stopped, but there is no guarantee that the fencing thread will enter the section before the other.

Anyhow, it's guaranteed that the fencing thread will be eventually called before that a new thread has the chance to successfully sign in or exit a checkpoint.

If the fence parameter is false, then this thread will have to wait for all the threads to be signed out, or to engage at the same time a checkpoint before to proceed. This may happened randomly, or it may happen consistently if the program is designed to have many waits inside the singed in threads.

Be the fence parameter true or false, once that the thread has entered the critical section, no thread is allowed to go past a checkpoint or to sign in, up to when the owning thread calls the leave method.

If the thread calling this method is also signed in, it MUST sign out before to call enter, or it will hang forever.

The timed parameter serves to know if the time parameter must be considered. If timed is true, the function will return true if the function is able to enter the section in the given time interval, or false if it fails. Typically, you'll want to use candy grammar version enter( double, bool ).

Note:
This method is a cancellation point. Be sure to clean the thread or to push a cleanup routine (or to disable cancellation) before calling it.
See also:
leave()
Parameters:
fence true to rise a fence and prevents other threads to sign in. False to wait for all the thread to be really signed out.
timed set true if you want to provide a timeout.
time if timed is true, wait for time seconds or abort function
Returns:
false if timeout was given and it expired without the function being able to enter the section; true otherwise.

void Wefts::CriticalSection::handleCleanup int  code,
void *  caller = 0
[virtual]
 

Implements Wefts::CleanupHandler.

void Wefts::CriticalSection::leave  ) 
 

Leaves the critical sections, allowing other threads to proceed.

If there are other threads waiting for the critical section to become enterable, and fence is risen they are awaken. Else, threads waiting to sign in are awaken.

void Wefts::CriticalSection::signIn  ) 
 

Claims the critical section to be not enterable.

Calling this thread states that it must work on the application data so that the critical section may not be entered safely. Notice that if the data set guarded this way was simple and consistent, a mutex or a read write mutex would be fare enough to handle this situation. But when the data set becomes very complex, or it's not even defined because it may vary from time to time, usage of a critical section semantics becomes important.

Any number of threads may sign in for a critical section, but only one is allowed to enter it; and it can enter it only if no other thread has signed in. Also, by entering a critical section, sign in is temporarily forbidden.

Timed sign in and sign in tries semantics are not provided because critical section holding is meant to be sporadic and temporary; it has no sense to ask if the current thread may or may not be blocked as a sign in request, because the sign in request significance is exactly to block the thread if the critical section is currently entered.

Note:
This method is a cancellation point. Be sure to clean the thread or to push a cleanup routine (or to disable cancellation) before calling it.

void Wefts::CriticalSection::signOut  ) 
 

Signals that the current thread is not interested in the critical section anymore.

With this call, the current thread tells eventual other threads wishing to enter the section that they may do it now, as even if the thread continues to work, it will not harm or use the critical section guarded data.

bool Wefts::CriticalSection::tryEnter  ) 
 

Try to enter a critical section and returns immediately.

If the critical section is immediately available, the thread enters it and the function returns true; else, it returns false.

Its a candy grammar for enter( fence, true, time );

Note:
This is not a cancellation point, and can be called also if the thread is in an unclean status.
See also:
enter(bool)
Returns:
true if the thread entered the section, false otherwise


Member Data Documentation

bool Wefts::CriticalSection::m_achieved [private]
 

True if currently achieved by a thread.

This prevents multiple threads to achieve the section when the signed in count reaches zero.

Condition Wefts::CriticalSection::m_enterCond [private]
 

Condition for threads willing to enter the section.

This condition serves for the predicate ( !m_achieved && m_signedIn == 0 ). Will be signaled only if m_enterRequests != 0.

int Wefts::CriticalSection::m_enterRequests [private]
 

Count of threads wishing enter the critical section.

int Wefts::CriticalSection::m_fenceCount [private]
 

Fence count for enter requests.

Mutex Wefts::CriticalSection::m_mutex [private]
 

Mutex to protect internal data.

int Wefts::CriticalSection::m_signedIn [private]
 

Count of signed in threads.

When it's 0, the critical section may be entered.

Condition Wefts::CriticalSection::m_signinCond [private]
 

Condition for threads wishing to sign in.

This condition serves for the predicate ( !m_achieved && m_fenceCount == 0 ). Will be signaled only if m_signRequests != 0.

int Wefts::CriticalSection::m_signRequests [private]
 

Count of threads wishing to sign in.


The documentation for this class was generated from the following files:
Generated on Tue Oct 5 14:57:02 2004 for Wefts by doxygen 1.3.7