MCS  0.3.3-alpha7
mcs::Synchro Class Reference

A simple class to implement "critical sections". More...

#include <mcs.hh>

+ Inheritance diagram for mcs::Synchro:

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...
 
Synchrooperator= (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...
 

Detailed Description

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:

int shared; //A variable shared between threads.
Synchro syn; //Object used to implement the critical section.
void function() {
syn.enter(); //Enter the critical section
... //Manipulate the shared variable
syn.leave() //Exit the critical section
}

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:

  • critical sections aren't useful in that code executed by only one thread;
  • critical sections are needed when multiple threads wants to modify a shared avariable at the same time;
  • critical sections aren't needed when multiple threads wants to read a shared avariable at the same time;
  • 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:

    • a "return" instruction is encountered;
    • a "goto" instruction is encountered;
    • an exception is thrown;
    • the thread is cancelled (either by other threads or by itself);

    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:

try {
.... //Critical section
}
catch (Event e) {
leave();
throw e;
}

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.

Definition at line 2187 of file mcs.hh.

Constructor & Destructor Documentation

◆ Synchro() [1/2]

mcs::Synchro::Synchro ( const Synchro )

Declared to avoid using of default copy constructor.

Warning
This constructor is declared but not implemented. If you try to use it you will get a compilation error.

◆ Synchro() [2/2]

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.

Definition at line 58 of file Thread.cc.

◆ ~Synchro()

mcs::Synchro::~Synchro ( )

Destructor.

Definition at line 73 of file Thread.cc.

Member Function Documentation

◆ count()

int mcs::Synchro::count ( )

Return how many times the current thread has locked the section.

Definition at line 85 of file Thread.cc.

◆ enter()

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:

  • MCS_SYNCHRO_LOCK, the thread will wait forever until the critical section became unlocked.
  • MCS_SYNCHRO_TRY_LOCK, the thread will try to enter the critical section, then return immediately.
  • MCS_SYNCHRO_TRY_TIMED, the thread will try to enter the critical section, if it cannot lock the section after the timeout has expired it will return.

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.

Parameters
opA code specifying the behaviour in case the section is already locked;
timeoutUse this only if op=MCS_SYNCHRO_TRY_TIMED, the timeout in milliseconds after which a try to lock the section will fail;
Returns
True if the section has been locked, false otherwise. If op=MCS_SYNCHRO_LOCK this method will always return true or never return.

Definition at line 143 of file Thread.cc.

◆ leave()

int mcs::Synchro::leave ( )

Leave a critical section.

Leave a critical section (unlock the mutex). There must be a call to this method for each exit point in the critical section.

Returns
How many times the thread should call this method to completely unlock the section.

Definition at line 194 of file Thread.cc.

◆ operator=()

Synchro& mcs::Synchro::operator= ( const Synchro )

Declared to avoid using of default assignment operator.

Warning
This operator is declared but not implemented. If you try to use it you will get a compilation error.

◆ synchronize()

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.

Parameters
setactiveIf false this became a "dummy" object, that is every call returns immediately without being synchronized.

Definition at line 89 of file Thread.cc.

◆ tryenter()

bool mcs::Synchro::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.

Definition at line 212 of file Thread.cc.

Member Data Documentation

◆ attr

pthread_mutexattr_t mcs::Synchro::attr
private

Attribute of the mutex (PTHREAD_MUTEX_RECURSIVE_NP).

Definition at line 2205 of file mcs.hh.

◆ Count

int mcs::Synchro::Count
private

How many time the Mutex has been locked, or a thread entered a critical section.

Definition at line 2208 of file mcs.hh.

◆ isActive

bool mcs::Synchro::isActive
private

Whether this object is a "dummy" object or not.

Definition at line 2211 of file mcs.hh.

◆ mutex

pthread_mutex_t mcs::Synchro::mutex
private

The mutex used to do the job.

Definition at line 2202 of file mcs.hh.


The documentation for this class was generated from the following files:

mcslogo

MCS (My Customizable Server) ver. 0.3.3-alpha7
Documentation generated on Mon May 28 07:39:41 UTC 2018