PCL
pcl::Mutex Class Reference

Adaptive mutual exclusion lock variable. More...

#include <Mutex.h>

Public Member Functions

 Mutex (int spin=512)
 
 Mutex (const Mutex &)=delete
 
virtual ~Mutex ()
 
void Lock ()
 
void operator() (bool lock=true)
 
Mutexoperator= (const Mutex &)=delete
 
int SpinCount () const
 
bool TryLock ()
 
void Unlock ()
 

Detailed Description

The word mutex is an abbreviation for mutual exclusion. A mutex object provides access synchronization for threads. A mutex protects one or more objects or a code section, so that only one thread can access them at a given time.

To understand how mutual thread exclusion works and why is it needed, consider the following example code:

int data;
void functionOne()
{
data += 2;
data *= 2;
}
void functionTwo()
{
data -= 3;
data *= 3;
}

If functionOne() and functionTwo() are called in sequence, this happens:

data = 3;
functionOne(); // data is now = 10
functionTwo(); // data is now = 21

Now suppose that we define two threads that call the above functions:

class ThreadOne : public Thread
{
//...
void Run() override
{
functionOne();
}
};
class ThreadTwo : public Thread
{
//...
void Run() override
{
functionTwo();
}
};

If we start both threads in sequence:

data = 3;
ThreadOne one;
ThreadTwo two;
one.Start();
two.Start();

then the following might happen:

// ThreadOne calls functionOne:
data += 2; // data is now = 5
// ThreadTwo calls functionTwo. This causes ThreadOne to enter a wait state
// until ThreadTwo terminates:
data -= 3; // data is now = 2
data *= 3; // data is now = 6
// ThreadOne resumes execution:
data *= 2; // data is now = 12

Because both threads can access data in any order, and there is no guarantee as to when a given thread starts execution, the result may not be what we expect (we get 12 instead of 21). Adding synchronization with a Mutex object in functionOne() and functionTwo() solves the problem:

int data;
Mutex mutex;
void functionOne()
{
mutex.Lock();
data += 2;
data *= 2;
mutex.Unlock();
}
void functionTwo()
{
mutex.Lock();
data -= 3;
data *= 3;
mutex.Unlock();
}

A mutex can only be locked by a single thread at a time. After Lock() has been called from a thread T, other threads that call Lock() on the same mutex object block their execution until the thread T calls Unlock().

To attempt locking a mutex without blocking execution, the Mutex::TryLock() member function can be used. This can provide much higher performance than Mutex::Lock() when the calling threads don't depend on gaining exclusive access to the shared data being protected by the mutex object.

Mutex implements spinning locking, a technique that can also improve performance by avoiding expensive semaphore wait operations under high levels of contention. See the documentation for Mutex::Mutex( int ) and Mutex::Lock() for more information.

Mutex has been implemented as a low-level PCL class that does not depend on the PixInsight Core application. On Windows platforms, Mutex has been implemented as a wrapper to a critical section. On UNIX/Linux platforms, Mutex uses atomic int operations implemented as inline assembly code and direct calls to the pthreads library.

See also
AutoLock, ReadWriteMutex

Definition at line 208 of file Mutex.h.

Constructor & Destructor Documentation

◆ Mutex() [1/2]

pcl::Mutex::Mutex ( int  spin = 512)
inline

Constructs a Mutex object.

Parameters
spinMaximum number of spinning loops to do before performing a semaphore wait operation when a thread attempts to lock this mutex and it has already been locked by another thread. If this mutex becomes unlocked during the spinning loops, the expensive wait operation can be avoided. The spin count must be >= 0. The default value is 512.

Definition at line 222 of file Mutex.h.

◆ ~Mutex()

virtual pcl::Mutex::~Mutex ( )
inlinevirtual

Destroys a Mutex object.

Warning
Destroying a locked Mutex object may result in undefined (mostly catastrophic) behavior. Always make sure that a mutex has been unlocked before destroying it.

Definition at line 239 of file Mutex.h.

◆ Mutex() [2/2]

pcl::Mutex::Mutex ( const Mutex )
delete

Copy constructor. This constructor is disabled because mutexes are unique objects.

Member Function Documentation

◆ Lock()

void pcl::Mutex::Lock ( )
inline

Locks this Mutex object.

When a mutex has been locked in a thread T, other threads cannot lock it until the thread T unlocks it. When a thread attempts to lock a Mutex object that has been previously locked, it blocks its execution until the Mutex object is unlocked.

If the mutex has already been locked by another thread, this routine performs a number of spin loops before doing an (expensive) wait operation on a semaphore associated with this mutex object. If this mutex becomes unlocked during the spinning loops, the wait operation can be avoided to lock the mutex in the calling thread. This can greatly improve efficiency of multithreaded code under high levels of contention (e.g. several running threads that depend on frequent concurrent accesses to shared data). For fine control and performance tuning, the maximum number of spinning loops performed can be specified as a parameter to the Mutex::Mutex( int ) constructor.

Definition at line 279 of file Mutex.h.

◆ operator()()

void pcl::Mutex::operator() ( bool  lock = true)
inline

Function call operator. This is a convenience operator that performs the lock and unlock operations in an alternative, perhaps more elegant way.

Parameters
lockWhether the mutex should be locked (when true) or unlocked (when lock is false).

For example, the following code snippet:

Mutex mutex;
//...
mutex( true );
// some code to be protected
mutex( false );

is equivalent to:

Mutex mutex;
//...
mutex.Lock();
// some code to be protected
mutex.Unlock();

Definition at line 347 of file Mutex.h.

◆ operator=()

Mutex& pcl::Mutex::operator= ( const Mutex )
delete

Copy assignment. This operator is disabled because mutexes are unique objects.

◆ SpinCount()

int pcl::Mutex::SpinCount ( ) const
inline

Returns the spin count of this Mutex object.

The spin count is a read-only property that can only be set upon object construction. For information on mutex spin counts, refer to Mutex's constructor: Mutex::Mutex( int ).

Definition at line 380 of file Mutex.h.

◆ TryLock()

bool pcl::Mutex::TryLock ( )
inline

Attempts locking this Mutex object. Returns true iff this mutex has been successfully locked.

Unlike Lock(), this function does not block execution of the calling thread if this mutex cannot be locked.

Definition at line 362 of file Mutex.h.

◆ Unlock()

void pcl::Mutex::Unlock ( )
inline

Unlocks this Mutex object.

See the Lock() documentation for more information.

Definition at line 310 of file Mutex.h.


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