You.i Engine
CYIMutex Class Reference

Detailed Description

Provides access serialization between threads by guaranteeing that only one thread is going to enter a designated critical section determined by CYIMutex::Lock() and CYIMutex::Unlock(). For a function that has multiple returns, it is highly advisable to use CYIAutoMutex to wrap the Lock and Unlock calls using the Resource-Acquisition-Is-Initialization (RAII) principle.

Here is an example on how to use CYIMutex

class MyClass
{
int32_t m_resource = 42;
public:
int32_t operator++() // prefix ++
{
return ++m_resource;
}
int32_t operator++(int) //postfix ++
{
return m_resource++;
}
int32_t operator--() // prefix --
{
return --m_resource;
}
int32_t operator--(int) //postfix --
{
return m_resource--;
}
}

In this example, everything will work fine if MyClass is only accessed by a single thread, but if two thread were to call any of the overridden operators exactly at the same time, that is where the unpredictable may occur. Depending if you are using the prefix or postfix override, the number of cpu instructions varies between 2 to 3 instructions.

When multiple threads are calling the operators, these instructions may be interleaved, which may cause the operator to have absolutely no effect even though the returned value may look correct. This problem can be solved using a mutex.

#include "threads/YiMutex.h"
class MyClass
{
int32_t m_resource = 42;
CYIMutex m_resourceMutex;
public:
int32_t operator++() // prefix ++
{
m_resourceMutex.Lock();
return ++m_resource;
m_resourceMutex.Unlock();
}
int32_t operator++(int) //postfix ++
{
m_resourceMutex.Lock();
return m_resource++;
m_resourceMutex.Unlock();
}
int32_t operator--() // prefix --
{
m_resourceMutex.Lock();
return --m_resource;
m_resourceMutex.Unlock();
}
int32_t operator--(int) //postfix --
{
m_resourceMutex.Lock();
return m_resource--;
m_resourceMutex.Unlock();
}
}

Now the m_resource attribute is protected against multiple thread access. MyClass can now be declared 'thread-safe'.

See also
CYIRecursiveMutex
CYIAutoMutex
CYIReadWriteMutex
CYISpinLock

#include <thread/YiMutex.h>

Inheritance diagram for CYIMutex:

Public Types

enum  YI_MUTEX_MODE {
  YI_FAST_MUTEX,
  YI_RECURSIVE_MUTEX
}
 

Public Member Functions

 CYIMutex (YI_MUTEX_MODE mode=YI_FAST_MUTEX)
 
virtual ~CYIMutex ()
 
bool Lock ()
 
bool TryLock ()
 
bool Unlock ()
 

Protected Attributes

CYIMutexPriv * m_pPriv
 

Friends

class CYIWaitCondition
 

Member Enumeration Documentation

Enumerator
YI_FAST_MUTEX 
YI_RECURSIVE_MUTEX 

Constructor & Destructor Documentation

CYIMutex::CYIMutex ( YI_MUTEX_MODE  mode = YI_FAST_MUTEX)

Constructor. The user can chose to turn the mutex into a recursive mutex. A recursive mutex is a mutex that can be locked more than once without self-blocking which would cause an deadlock. The trade-off is speed. Recursive mutex are slower than their regular counterparts. Use a recursive mutex only if it is strictly necessary. Using a recursive mutex can still be faster than making a copy of the shared resource.

The same can be achieved by using CYIRecursiveMutex instead of CYIMutex with the YI_RECURISVE_MUTEX mode.

Warning
Recursive mutex are slower than regular mutex.
virtual CYIMutex::~CYIMutex ( )
virtual

Member Function Documentation

bool CYIMutex::Lock ( )

Locks the mutex. It denotes where the critical section begins. If another thread calls this function, the other would be completely descheduled until we call Unlock(). This function returns true if the lock was successful and false if there were any errors.

Warning
This function can cause a deadlock if called more than once by the same thread when the mutex is non-recursive.
bool CYIMutex::TryLock ( )

This function attempts to lock the mutex. If the mutex is already locked, the function will return false. If the lock was successful, the function will return true. Using this function is perfect for situation in which the thread can be doing something else while the mutex is locked.

Warning
This function can cause a livelock if called by an infinite loop by the same thread when the mutex is non-recursive.
bool CYIMutex::Unlock ( )

Unlocks the mutex. It denotes where the critical section ends. If the function was successful, it will return true. If another thread tries to call this function, but that thread is not the thread that locked the mutex in the first place, this function will return false. Unlocking a mutex that isn't locked results in an undefined behaviour.

Friends And Related Function Documentation

friend class CYIWaitCondition
friend

Member Data Documentation

CYIMutexPriv* CYIMutex::m_pPriv
protected

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