MCS
0.3.3-alpha7
|
A simple class to implement "critical sections". More...
#include <mcs.hh>
Public Member Functions | |
int | count () |
Return how many times the current thread has locked the section. More... | |
bool | enter (int op=1, unsigned int timeout=0) |
Enter, or try to enter a critical section. More... | |
int | leave () |
Leave a critical section. More... | |
Synchro & | operator= (const Synchro &) |
Declared to avoid using of default assignment operator. More... | |
Synchro (const Synchro &) | |
Declared to avoid using of default copy constructor. More... | |
Synchro () | |
Constructor. More... | |
void | synchronize (bool setactive) |
Enable or disable the synchronization feature. More... | |
bool | tryenter (unsigned int timeout=0) |
Wrapper around enter(), using op=MCS_SYNCHRO_TRY_LOCK if the parameter is 0, op=MCS_SYNCHRO_TRY_TIMED otherwise. More... | |
~Synchro () | |
Destructor. More... | |
Private Attributes | |
pthread_mutexattr_t | attr |
Attribute of the mutex (PTHREAD_MUTEX_RECURSIVE_NP). More... | |
int | Count |
How many time the Mutex has been locked, or a thread entered a critical section. More... | |
bool | isActive |
Whether this object is a "dummy" object or not. More... | |
pthread_mutex_t | mutex |
The mutex used to do the job. More... | |
A simple class to implement "critical sections".
Critical sections are portions of code which cannot be executed by two different threads simultaneously, that is one thread must wait that the other has finished before it can execute it. This is often useful to synchronize threads, or let them access shared variables. Critical sections are implemented in MCS using mutexes. For example if two threads would execute the same code, accessing the same variable, then you must implement a critical section like the following:
In this code, when multiple threads are executing the function at the same time, then it is guaranteed that only one thread will execute the code in the critical section, while the other are suspended (and consume no CPU time).
Anyway developer should pay attention because critical sections, or better a call to enter(), can be a potential deadlock, that is a point at which the thread remain suspended forever. Actually a thread can be killed (or better cancelled) by itself or by other threads only when it is executing a so called "cancellation point", typically I/O operations or some system call (like (sleep()). The system call to lock a mutex is not a cancellation point, so if the thread is suspended waiting to lock a mutex it cannot be cancelled, the only way to kill it is to kill the entire program using signals. On the other hand enter() and tryenter() are cancellation points, so if a thread received a cancellation request while it was suspended, this methods won't return at all. In other words, once a thread is waiting to enter a critical section that is ran by some other thread, it can't be cancelled until the other thread leave the section. For this reason every critical section must be balanced, that is it must have a starting point (using the enter() or tryenter() methods) and an ending point (using the leave() method).
For these reasons developers should design critical sections appropriately, here we'll give some useful hints:
In critical sections you usually put a call to enter() at the beginning of the section and a leave() at the end, but this could not be enough to implement a balanced critical section, because the control flow can be interupted by several event:
In the first three cases you MUST provide the balancing call to leave(), anyway we recommend not to use any "return" or "goto" instruction inside critical sections. To handle exceptions you can write a code like the following:
As you can see there are one call to the enter() method, but two call to leave(), one for each possible exit point in the function. The code above can be easily implemented using the MCS_CRITICAL_SECTION macros. In the fourth case the Synchro object will leave the section automatically;
Critical sections can be nested, that is a thread can enter a critical section any number of time, while the others are waiting. Each thread must also leave critical sections the same number of time. Other threads are allowed to enter a critical section once it is completely free.
mcs::Synchro::Synchro | ( | const Synchro & | ) |
Declared to avoid using of default copy constructor.
mcs::Synchro::Synchro | ( | ) |
Constructor.
This contructor initialize a "dummy" object, that is an object with synchronization disabled. To enable it call synchronize().
That is because several class are derived from Synchro, but not all objects of those classes needs to be synchronized.
int mcs::Synchro::count | ( | ) |
bool mcs::Synchro::enter | ( | int | op = 1 , |
unsigned int | timeout = 0 |
||
) |
Enter, or try to enter a critical section.
If other threads are locking the critical section the behaviour of this method depends on the first parameter:
If you specify MCS_SYNCHRO_LOCK as first parameter, then the thread must lock the section before it can do anything else. Once the section has been locked this method will return, or the thread will be cancelled (this method won't return) if a cancellation request arrived in the meanwhile.
op | A code specifying the behaviour in case the section is already locked; |
timeout | Use this only if op=MCS_SYNCHRO_TRY_TIMED, the timeout in milliseconds after which a try to lock the section will fail; |
int mcs::Synchro::leave | ( | ) |
Declared to avoid using of default assignment operator.
void mcs::Synchro::synchronize | ( | bool | setactive | ) |
Enable or disable the synchronization feature.
You must enable or disable the synchronization feature before callling any other method of this class, otherwise an exception will be thrown.
setactive | If false this became a "dummy" object, that is every call returns immediately without being synchronized. |
bool mcs::Synchro::tryenter | ( | unsigned int | timeout = 0 | ) |
|
private |
|
private |
|
private |
|
private |
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha7
|