Ion
|
A Mutex is used to ensure that only one thread or process can access a block of code at one time. More...
#include "mutex.h"
Public Member Functions | |
Mutex () | |
POSIX mutexes are non-recursive, meaning that if the same thread tries to Lock() the mutex, it will block indefinitely. More... | |
~Mutex () | |
bool | IsLocked () |
Returns whether the Mutex is currently locked. Does not block. More... | |
void | Lock () |
Locks the Mutex. More... | |
bool | TryLock () |
Returns true if the mutex was successfully locked, and false otherwise. More... | |
void | Unlock () |
Unlocks the Mutex. More... | |
A Mutex is used to ensure that only one thread or process can access a block of code at one time.
ion::port::Mutex::Mutex | ( | ) |
POSIX mutexes are non-recursive, meaning that if the same thread tries to Lock() the mutex, it will block indefinitely.
On Windows, a CRITICAL_SECTION can be entered recursively, so long as the number of EnterCriticalSection()s matches the number of LeaveCriticalSection()s, and TryEnterCriticalSection() always succeeds if the same thread is already in the critical section. POSIX threads can match this behavior if you set them PTHREAD_MUTEX_RECURSIVE.
Recursive locks are in general a bad idea, and lead to poorly written code: if a lock is held, there is no reason to try to acquire that lock again.
Windows supports non-recursive Mutexes, but they are very slow. Instead, we wrap an Event test around Interlocked(Increment|Decrement), which are very fast (faster than (Try)EnterCriticalSection()) atomic operations. A slower path is only taken when there are multiple contenders; if a single thread repeatedly Lock()s and Unlock()s a mutex, the Event is never tested, and the only cost is the (very small) increment and decrement cost plus that of an if. Intel has shown that the costs of WaitForSingleObject() and EnterCriticalSection() are very similar for multiple threads under high contention: See http://software.intel.com/en-us/articles/implementing-scalable-atomic- locks-for-multi-core-intel-em64t-and-ia32-architectures
To use a CRITICAL_SECTION anyway, uncomment the following line, otherwise the above interlocking increment/decrement scheme is used. This will cause tests in mutex_tests.cc and lockguards_test.cc to fail; their logic must be updated. #define ION_MUTEX_USE_CRITICAL_SECTION
bool ion::port::Mutex::IsLocked | ( | ) |
void ion::port::Mutex::Lock | ( | ) |
Locks the Mutex.
Blocks the calling thread or process until the lock is available; no thread or process can return from Lock() until the lock owner Unlock()s.
Definition at line 92 of file mutex.cc.
References ion::port::GetCurrentThreadId().
Referenced by ion::base::ReadWriteLock::LockForRead(), and ion::base::ReadWriteLock::LockForWrite().
bool ion::port::Mutex::TryLock | ( | ) |
Returns true if the mutex was successfully locked, and false otherwise.
Does not block.
Definition at line 116 of file mutex.cc.
References ion::port::GetCurrentThreadId().
Referenced by IsLocked().
void ion::port::Mutex::Unlock | ( | ) |
Unlocks the Mutex.
Any thread or process can now return from Lock(). Does nothing if the Mutex was not locked by the calling thread or at all. Does not block.
Definition at line 145 of file mutex.cc.
References ion::port::GetCurrentThreadId().
Referenced by IsLocked(), ion::base::ReadWriteLock::LockForRead(), and ion::base::ReadWriteLock::UnlockForWrite().