diff options
author | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2019-08-14 22:50:43 +0800 |
commit | 15740faf9fe9fe4be08965098bbf2947e096aeeb (patch) | |
tree | a730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Threads/SimpleLock.h |
Diffstat (limited to 'Runtime/Threads/SimpleLock.h')
-rw-r--r-- | Runtime/Threads/SimpleLock.h | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/Runtime/Threads/SimpleLock.h b/Runtime/Threads/SimpleLock.h new file mode 100644 index 0000000..ace47aa --- /dev/null +++ b/Runtime/Threads/SimpleLock.h @@ -0,0 +1,53 @@ +#ifndef SIMPLE_LOCK_H +#define SIMPLE_LOCK_H + +#if SUPPORT_THREADS + +#include "AtomicOps.h" +#include "Semaphore.h" + +// Simple, non-recursive mutual exclusion lock. Efficient when there is low contention. +// First tries to attain lock using atomic ops, then waits for lock using semaphores. +// Same idea as described here: http://preshing.com/20120226/roll-your-own-lightweight-mutex + +class SimpleLock : public NonCopyable +{ +public: + SimpleLock() : m_Count(0) {} + + class AutoLock : public NonCopyable + { + public: + AutoLock( SimpleLock& lock ) : m_Lock(lock) + { + m_Lock.Lock(); + } + + ~AutoLock() + { + m_Lock.Unlock(); + } + + private: + SimpleLock& m_Lock; + }; + + void Lock() + { + if (AtomicIncrement(&m_Count) != 1) + m_Semaphore.WaitForSignal(); + } + + void Unlock() + { + if (AtomicDecrement(&m_Count) != 0) + m_Semaphore.Signal(); + } + +private: + volatile int m_Count; + Semaphore m_Semaphore; +}; + +#endif // SUPPORT_THREADS +#endif |