CopperSpice API  1.7.4
QRecursiveMutex Class Reference

Provides exclusive access to a block of code by different threads. More...

Public Methods

 QRecursiveMutex () = default
 
 ~QRecursiveMutex () = default
 
void lock ()
 
bool try_lock ()
 
template<typename T1 , typename T2 >
bool try_lock_for (std::chrono::duration< T1, T2 > duration)
 
template<typename T1 , typename T2 >
bool try_lock_until (std::chrono::time_point< T1, T2 > timePoint)
 
bool tryLock (int timeout=0)
 
void unlock ()
 

Detailed Description

The QRecursiveMutex class provides exclusive access to a block of code by different threads. A QRecursiveMutex is used to protect an object, data structure, or section of code so only one thread can access the given code at one time.

A recursive mutex must be used if the same thread needs to acquire multiple locks on the same mutex. If recursive locking is required your code must use the QRecursiveMutex class or a deadlock will occur. Using a recursive mutex will be slightly slower so only use this approach if it is required.

Example

Consider two functions which modify the same global variable.

int number = 20;
void F1()
{
number += 5;
number -= 9;
}
void F2()
{
number += 3;
number *= 2;
}

If these are called in succession the following output might occur.

// f1()
number += 5; // number is now 25
number -= 9; // number is now 16
// f2()
number += 3; // number is now 19
number *= 2; // number is now 38

If these functions are called simultaneously from two different threads there is a race condition, which is undefined behavior. The code below shows a possible outcome and the final result is different from order of operations as shown above.

// Thread 1 calls F1()
number += 5; // number is now 25
// Thread 2 calls F2()
number += 3; // number is now 28
number *= 2; // number is now 56
// Thread 1 now finishes
number -= 9; // number is now 47

One way to guarantee each function will finish, without being interrupted, is to add a mutex. With a mutex in place only one thread can modify number at any given time.

When the method lock() is called from one thread, all other threads that call lock() on the same mutex will be blocked until the thread that owns the lock calls unlock(). A non-blocking alternative to lock() is tryLock().

int number = 6;
void F1()
{
mutex.lock();
number += 5;
number -= 9;
mutex.unlock();
}
void F2()
{
mutex.lock();
number += 3;
number *= 2;
mutex.unlock();
}
See also
QMutex, QMutexLocker, QRecursiveMutexLocker, QReadWriteLock, QSemaphore, QWaitCondition

Constructor & Destructor Documentation

QRecursiveMutex::QRecursiveMutex ( )
default

Constructs a new QRecursiveMutex which is in an unlocked state.

QRecursiveMutex::~QRecursiveMutex ( )
default

Destroys the mutex. Destroying a locked mutex is undefined behavior.

Method Documentation

void QRecursiveMutex::lock ( )
inline

Locks the current mutex. If another thread has locked the mutex then calling this methods will block until that thread has unlocked it.

This method will dead lock if the mutex is locked recursively.

See also
unlock()
bool QRecursiveMutex::try_lock ( )
inline

Attempts to lock the mutex. This method returns true if the lock was obtained, otherwise it returns false.

Equivalent to calling tryLock().

template<typename T1 , typename T2 >
bool QRecursiveMutex::try_lock_for ( std::chrono::duration< T1, T2 >  duration)
inline

Attempts to lock the mutex. This method returns true if the lock was obtained, otherwise it returns false. If another thread has locked the mutex, this method will wait for at least duration for the mutex to become available.

If the lock was obtained the mutex must be unlocked before another thread can successfully lock it.

This method will always return false when attempting to lock the mutex recursively. Passing a negative value for duration as the duration is equivalent to calling try_lock().

template<typename T1 , typename T2 >
bool QRecursiveMutex::try_lock_until ( std::chrono::time_point< T1, T2 >  timePoint)
inline

Attempts to lock the mutex. This method returns true if the lock was obtained, otherwise it returns false. If another thread has locked the mutex, this method will wait at least until timePoint for the mutex to become available.

If the lock was obtained the mutex must be unlocked before another thread can successfully lock it.

This method will always return false when attempting to lock the mutex recursively. Passing a negative value for timePoint as the duration is equivalent to calling try_lock().

bool QRecursiveMutex::tryLock ( int  timeout = 0)
inline

Attempts to lock the current mutex. This method returns true if the lock was obtained, otherwise it returns false.

If another thread has locked the mutex, this method will wait for at most timeout milliseconds for the mutex to become available. If the lock was obtained the mutex must be unlocked with unlock() before another thread can successfully lock it.

This method will always return false when attempting to lock the mutex recursively.

Passing a negative value for the timeout is equivalent to calling lock(), which means this method will wait forever until the mutex can be locked.

void QRecursiveMutex::unlock ( )
inline

Unlocks the mutex. Attempting to unlock a mutex which was locked in a different thread or unlocking a mutex which is not locked, is undefined behavior.

See also
lock()