#ifndef _DEBUG inline void AssertST() {} #endif #ifdef _MULTITHREADED #ifdef COMPILER_MSC #define thread__ __declspec(thread) #else #define thread__ __thread #endif #ifdef flagPROFILEMT class Mutex; class StaticMutex; struct MtInspector { const char *name; int number; int locked; int blocked; static MtInspector *Dumi(); MtInspector(const char *s, int n = -1) { name = s; number = n; locked = blocked = 0; } ~MtInspector(); }; #define PROFILEMT(mutex) \ { static MtInspector MK__s(__FILE__, __LINE__); mutex.Set(MK__s); } #define PROFILEMT_(mutex, id) \ { static MtInspector MK__s(id); mutex.Set(MK__s); } #else #define PROFILEMT(mutex) #define PROFILEMT_(mutex, id) #endif class Callback; class Thread : NoCopy { #ifdef PLATFORM_WIN32 HANDLE handle; #endif #ifdef PLATFORM_POSIX pthread_t handle; #endif public: bool Run(Callback cb); void Detach(); int Wait(); bool IsOpen() const { return handle; } #ifdef PLATFORM_WIN32 HANDLE GetHandle() const { return handle; } #endif #ifdef PLATFORM_POSIX pthread_t GetHandle() const { return handle; } #endif void Priority(int percent); // 0 = lowest, 100 = normal static void Start(Callback cb); static void Sleep(int ms); static bool IsST(); static bool IsMain(); static int GetCount(); static void ShutdownThreads(); static bool IsShutdownThreads(); Thread(); ~Thread(); private: void operator=(const Thread&); Thread(const Thread&); }; #ifdef _DEBUG inline void AssertST() { ASSERT(Thread::IsST()); } #endif void ReadMemoryBarrier(); void WriteMemoryBarrier(); #ifdef CPU_SSE2 inline void ReadMemoryBarrier() { #ifdef CPU_AMD64 #ifdef COMPILER_MSC _mm_lfence(); #else __asm__("lfence"); #endif #else #ifdef COMPILER_MSC __asm lfence; #else __asm__("lfence"); #endif #endif } inline void WriteMemoryBarrier() { #ifdef CPU_AMD64 #ifdef COMPILER_MSC _mm_sfence(); #else __asm__("sfence"); #endif #else #ifdef COMPILER_MSC __asm sfence; #else __asm__("sfence"); #endif #endif } #endif #ifdef CPU_BLACKFIN inline void ReadMemoryBarrier() {} //placing in Mt.cpp somehow yields 'undefined reference' inline void WriteMemoryBarrier() {} #endif template inline U ReadWithBarrier(const volatile U& b) { /*volatile*/ U tmp = b; ReadMemoryBarrier(); return tmp; } template inline void BarrierWrite(volatile U& dest, V data) { WriteMemoryBarrier(); dest = data; } class Semaphore : NoCopy { #ifdef PLATFORM_WIN32 HANDLE handle; #else sem_t sem; #endif public: void Wait(); void Release(); #ifdef PLATFORM_WIN32 void Release(int n); #endif Semaphore(); ~Semaphore(); }; class StaticSemaphore : NoCopy { volatile Semaphore *semaphore; byte buffer[sizeof(Semaphore)]; void Initialize(); public: Semaphore& Get() { if(!ReadWithBarrier(semaphore)) Initialize(); return *const_cast(semaphore); } operator Semaphore&() { return Get(); } void Wait() { Get().Wait(); } void Release() { Get().Release(); } }; struct MtInspector; #ifdef PLATFORM_WIN32 typedef LONG Atomic; inline int AtomicInc(volatile Atomic& t) { return InterlockedIncrement((Atomic *)&t); } inline int AtomicDec(volatile Atomic& t) { return InterlockedDecrement((Atomic *)&t); } inline int AtomicXAdd(volatile Atomic& t, int incr) { return InterlockedExchangeAdd((Atomic *)&t, incr); } class Mutex : NoCopy { protected: CRITICAL_SECTION section; MtInspector *mti; Mutex(int) {} public: bool TryEnter(); void Leave() { LeaveCriticalSection(§ion); } #ifdef flagPROFILEMT void Enter() { if(!TryEnter()) { mti->blocked++; EnterCriticalSection(§ion); }; mti->locked++; } void Set(MtInspector& m) { mti = &m; } Mutex() { mti = MtInspector::Dumi(); InitializeCriticalSection(§ion); } #else void Enter() { EnterCriticalSection(§ion); } Mutex() { InitializeCriticalSection(§ion); } #endif ~Mutex() { DeleteCriticalSection(§ion); } class Lock; }; /* Win32 RWMutex implementation by Chris Thomasson, cristom@comcast.net */ class RWMutex : NoCopy { LONG m_count, m_rdwake; HANDLE m_wrwset, m_rdwset; CRITICAL_SECTION m_wrlock; public: void EnterWrite(); void LeaveWrite(); void EnterRead(); void LeaveRead(); RWMutex(); ~RWMutex(); class ReadLock; class WriteLock; }; class ConditionVariable { Mutex mutex; friend struct sCVWaiter_; struct sCVWaiter_ *head, *tail; public: void Wait(Mutex& m); void Signal(); void Broadcast(); ConditionVariable(); ~ConditionVariable(); }; #endif #ifdef PLATFORM_POSIX typedef _Atomic_word Atomic; inline int AtomicXAdd(volatile Atomic& t, int incr) { using namespace __gnu_cxx; return __exchange_and_add(&t, incr); } inline int AtomicInc(volatile Atomic& t) { return AtomicXAdd(t, +1) + 1; } inline int AtomicDec(volatile Atomic& t) { return AtomicXAdd(t, -1) - 1; } class Mutex : NoCopy { pthread_mutex_t mutex[1]; #ifdef flagPROFILEMT MtInspector *mti; #endif friend class ConditionVariable; public: #ifdef flagPROFILEMT bool TryEnter() { bool b = pthread_mutex_trylock(mutex) == 0; mti->locked += b; return b; } void Enter() { if(pthread_mutex_trylock(mutex) != 0) { mti->blocked++; pthread_mutex_lock(mutex); } mti->locked++; } void Set(MtInspector& m) { mti = &m; } #else bool TryEnter() { return pthread_mutex_trylock(mutex) == 0; } void Enter() { pthread_mutex_lock(mutex); } #endif void Leave() { pthread_mutex_unlock(mutex); } class Lock; Mutex(); ~Mutex() { pthread_mutex_destroy(mutex); } }; class RWMutex : NoCopy { pthread_rwlock_t rwlock[1]; public: void EnterWrite() { pthread_rwlock_wrlock(rwlock); } void LeaveWrite() { pthread_rwlock_unlock(rwlock); } void EnterRead() { pthread_rwlock_rdlock(rwlock); } void LeaveRead() { pthread_rwlock_unlock(rwlock); } RWMutex(); ~RWMutex(); class ReadLock; class WriteLock; }; class ConditionVariable { pthread_cond_t cv[1]; public: void Wait(Mutex& m) { pthread_cond_wait(cv, m.mutex); } void Signal() { pthread_cond_signal(cv); } void Broadcast() { pthread_cond_broadcast(cv); } ConditionVariable() { pthread_cond_init(cv, NULL); } ~ConditionVariable() { pthread_cond_destroy(cv); } }; #endif inline int AtomicRead(const volatile Atomic& t) { return ReadWithBarrier(t); } inline void AtomicWrite(volatile Atomic& t, int val) { BarrierWrite(t, val); } class Mutex::Lock : NoCopy { Mutex& s; public: Lock(Mutex& s) : s(s) { s.Enter(); } ~Lock() { s.Leave(); } }; class RWMutex::ReadLock : NoCopy { RWMutex& s; public: ReadLock(RWMutex& s) : s(s) { s.EnterRead(); } ~ReadLock() { s.LeaveRead(); } }; class RWMutex::WriteLock : NoCopy { RWMutex& s; public: WriteLock(RWMutex& s) : s(s) { s.EnterWrite(); } ~WriteLock() { s.LeaveWrite(); } }; class StaticMutex : NoCopy { volatile Mutex *section; byte buffer[sizeof(Mutex)]; void Initialize(); public: Mutex& Get() { if(!ReadWithBarrier(section)) Initialize(); return *const_cast(section); } operator Mutex&() { return Get(); } bool TryEnter() { return Get().TryEnter();} void Enter() { Get().Enter();} void Leave() { Get().Leave(); } #ifdef flagPROFILEMT void Set(MtInspector& mti) { Get().Set(mti); } #endif }; class StaticRWMutex : NoCopy { volatile RWMutex *rw; byte buffer[sizeof(RWMutex)]; void Initialize(); public: RWMutex& Get() { if(!ReadWithBarrier(rw)) Initialize(); return *const_cast(rw); } operator RWMutex&() { return Get(); } void EnterRead() { Get().EnterRead();} void LeaveRead() { Get().LeaveRead(); } void EnterWrite() { Get().EnterWrite();} void LeaveWrite() { Get().LeaveWrite(); } }; class StaticConditionVariable : NoCopy { volatile ConditionVariable *cv; byte buffer[sizeof(ConditionVariable)]; void Initialize(); public: ConditionVariable& Get() { if(!ReadWithBarrier(cv)) Initialize(); return *const_cast(cv); } operator ConditionVariable&() { return Get(); } void Wait(Mutex& m) { Get().Wait(m); } void Signal() { Get().Signal(); } void Broadcast() { Get().Broadcast(); } }; #define INTERLOCKED \ for(bool i_b_ = true; i_b_;) \ for(static UPP::StaticMutex i_ss_; i_b_;) \ for(UPP::Mutex::Lock i_ss_lock__(i_ss_); i_b_; i_b_ = false) struct H_l_ : Mutex::Lock { bool b; H_l_(Mutex& cs) : Mutex::Lock(cs) { b = true; } }; #define INTERLOCKED_(cs) \ for(UPP::H_l_ i_ss_lock__(cs); i_ss_lock__.b; i_ss_lock__.b = false) void Set__(volatile bool& b); #define ONCELOCK \ for(static volatile bool o_b_; !ReadWithBarrier(o_b_);) \ for(static StaticMutex o_ss_; !o_b_;) \ for(Mutex::Lock o_ss_lock__(o_ss_); !o_b_; BarrierWrite(o_b_, true)) #define ONCELOCK_(o_b_) \ for(static StaticMutex o_ss_; !ReadWithBarrier(o_b_);) \ for(Mutex::Lock o_ss_lock__(o_ss_); !o_b_; BarrierWrite(o_b_, true)) #define ONCELOCK_PTR(ptr, init) \ if(!ReadWithBarrier(ptr)) { \ static StaticMutex cs; \ cs.Enter(); \ if(!ptr) \ BarrierWrite(ptr, init); \ cs.Leave(); \ } class LazyUpdate { mutable Mutex mutex; mutable bool dirty; public: void Invalidate(); bool BeginUpdate() const; void EndUpdate() const; LazyUpdate(); }; inline bool IsMainThread() { return Thread::IsMain(); } #else inline bool IsMainThread() { return true; } #define thread__ #define PROFILEMT(mutex) #define PROFILEMT_(mutex, id) typedef int Atomic; inline int AtomicRead(const volatile Atomic& t) { return t; } inline void AtomicWrite(volatile Atomic& t, int data) { t = data; } inline int AtomicInc(volatile Atomic& t) { ++t; return t; } inline int AtomicDec(volatile Atomic& t) { --t; return t; } inline int AtomicXAdd(volatile Atomic& t, int incr) { Atomic x = t; t += incr; return x; } class Mutex : NoCopy { public: bool TryEnter() { return true; } void Enter() {} void Leave() {} class Lock; }; typedef Mutex StaticMutex; class Mutex::Lock : NoCopy { public: Lock(Mutex&) {} ~Lock() {} }; class RWMutex : NoCopy { public: void EnterWrite() {} void LeaveWrite() {} void EnterRead() {} void LeaveRead() {} class ReadLock; class WriteLock; }; class RWMutex::ReadLock : NoCopy { public: ReadLock(RWMutex&) {} ~ReadLock() {} }; class RWMutex::WriteLock : NoCopy { public: WriteLock(RWMutex&) {} ~WriteLock() {} }; typedef RWMutex StaticRWMutex; class LazyUpdate { mutable bool dirty; public: void Invalidate() { dirty = true; } bool BeginUpdate() const { return dirty; } void EndUpdate() const { dirty = false; } LazyUpdate() { dirty = true; } }; #define INTERLOCKED #define INTERLOCKED_(x) { x.Enter(); } #define ONCELOCK \ for(static bool o_b_; !o_b_; o_b_ = true) #define ONCELOCK_(o_b_) \ for(; !o_b_; o_b_ = true) \ #define ONCELOCK_PTR(ptr, init) \ if(!ptr) ptr = init; inline void ReadMemoryBarrier() {} inline void WriteMemoryBarrier() {} #ifdef _DEBUG inline void AssertST() {} #endif #endif typedef Mutex CriticalSection; // deprecated typedef StaticMutex StaticCriticalSection; // deprecated