summaryrefslogtreecommitdiff
path: root/libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h')
-rw-r--r--libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h392
1 files changed, 392 insertions, 0 deletions
diff --git a/libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h b/libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h
new file mode 100644
index 0000000000..71fc1b7943
--- /dev/null
+++ b/libs/backends/wavesaudio/wavesapi/threads/WCThreadSafe.h
@@ -0,0 +1,392 @@
+#ifndef __WCThreadSafe_h_
+ #define __WCThreadSafe_h_
+
+/* Copy to include
+#include "Threads/WCThreadSafe.h"
+*/
+
+//
+// * WCThreadSafe.h (used to be called XPlatformOSServices.hpp)
+// *
+// * Consistent C++ interfaces to common Operating System services.
+// *
+// *
+// *
+// *
+// * Created 2004-December-13 by Udi Barzilai as XPlatformOSServices.hpp
+// * Moved to WCThreadSafe.h by Shai 26/10/2005
+// * 26/10/2005: ThreadMutex now inhetites from ThreadMutexInited
+// * namespace changed to wvThread
+
+#include "WavesPublicAPI/wstdint.h"
+#include <string>
+
+#include "BasicTypes/WUDefines.h"
+
+#if defined(__linux__) || defined(__APPLE__)
+ #define XPLATFORMOSSERVICES_UNIX 1
+#endif
+
+#if defined(_WIN32)
+ #define XPLATFORMOSSERVICES_WIN32 1
+#endif
+
+#if XPLATFORMOSSERVICES_WIN32
+ #define XPLATFORMTHREADS_WINDOWS 1
+#elif XPLATFORMOSSERVICES_UNIX
+ #define XPLATFORMTHREADS_POSIX 1
+#endif
+namespace wvNS {
+typedef uint32_t WTThreadSafetyType;
+const WTThreadSafetyType kNoThreadSafetyNeeded = 0;
+const WTThreadSafetyType kpthreadsmutexThreadSafety = 1;
+
+
+namespace wvThread
+{
+ //#include "BasicTypes/WavesAPISetAligment.h"
+ //Packing affects the layout of classes, and commonly, if packing changes across header files, there can be problems.
+#ifdef PLATFORM_WINDOWS
+#pragma pack(push)
+#pragma pack(8)
+#endif
+
+#ifdef __APPLE__
+#ifdef __GNUC__
+#pragma pack(push, 8)
+#endif
+#endif
+
+ //--------------------------------------------------------
+ typedef int32_t timediff; // in microseconds
+ static const timediff ktdOneSecond = 1000*1000;
+ //--------------------------------------------------------
+ class timestamp
+ {
+ protected:
+ typedef uint32_t tickcount;
+ tickcount m_nMicroseconds; // may wrap around
+ static const tickcount ms_knWraparoundThreshold = ~tickcount(0) ^ (~tickcount(0)>>1); // half the range
+
+ public:
+ timestamp() : m_nMicroseconds(0) { /* uninitialized */ }
+ timestamp(const timestamp &_ts) : m_nMicroseconds(_ts.m_nMicroseconds) {}
+ timestamp &operator=(const timestamp &_rhs) { m_nMicroseconds = _rhs.m_nMicroseconds; return *this; }
+ explicit timestamp(tickcount _i) : m_nMicroseconds(_i) {}
+ uint32_t ticks() const { return m_nMicroseconds; }
+ timediff operator-(timestamp _rhs) const { return timediff(m_nMicroseconds-_rhs.m_nMicroseconds); }
+ timestamp & operator+=(timediff _t) { m_nMicroseconds+=_t; return *this; }
+ timestamp & operator-=(timediff _t) { m_nMicroseconds-=_t; return *this; }
+ timestamp operator+(timediff _t) const { return timestamp(m_nMicroseconds+_t); }
+ timestamp operator-(timediff _t) const { return timestamp(m_nMicroseconds-_t); }
+ bool operator==(timestamp _rhs) const { return m_nMicroseconds==_rhs.m_nMicroseconds; }
+ bool operator!=(timestamp _rhs) const { return m_nMicroseconds!=_rhs.m_nMicroseconds; }
+ bool operator< (timestamp _rhs) const { return m_nMicroseconds-_rhs.m_nMicroseconds >= ms_knWraparoundThreshold; }
+ static timestamp null() { return timestamp(0); }
+ bool is_null() const { return m_nMicroseconds==0; }
+ };
+ //--------------------------------------------------------
+#ifdef __APPLE__
+ bool FindNetInterfaceByIPAddress(const char *sIP, char *sInterface);
+#endif // MACOS
+ //--------------------------------------------------------
+ timestamp now();
+ //--------------------------------------------------------
+ DllExport void sleep(timediff);
+ DllExport void sleep_milliseconds(unsigned int nMillisecs);
+ //--------------------------------------------------------
+ void yield();
+ //--------------------------------------------------------
+
+
+
+ typedef uintptr_t os_dependent_handle_type;
+
+ //--------------------------------------------------------
+ typedef int ThreadFunctionReturnType;
+ typedef void * ThreadFunctionArgument;
+ //--------------------------------------------------------
+ typedef ThreadFunctionReturnType (ThreadFunction)(ThreadFunctionArgument);
+ //--------------------------------------------------------
+ class ThreadHandle
+ {
+ public:
+ class OSDependent;
+ protected:
+ uintptr_t m_oshandle; // hopefully this is good enough for all systems
+ public:
+ static const ThreadHandle Invalid;
+ protected:
+ ThreadHandle(uintptr_t n) : m_oshandle(n) {}
+ public:
+ ThreadHandle() : m_oshandle(Invalid.m_oshandle) {}
+ bool is_invalid() const { return !m_oshandle || m_oshandle==Invalid.m_oshandle; }
+ };
+ //--------------------------------------------------------
+ class ThreadPriority
+ {
+ public: enum value { BelowNormal=1, Normal=2, AboveNormal=3, TimeCritical=4 };
+ protected: value m_value;
+ public: ThreadPriority(value v) : m_value(v) {}
+ public: operator value() const { return m_value; }
+ };
+ //--------------------------------------------------------
+ void SetMyThreadPriority(ThreadPriority);
+ //--------------------------------------------------------
+ ThreadHandle StartThread(ThreadFunction, ThreadFunctionArgument, ThreadPriority=ThreadPriority::Normal);
+ bool JoinThread(ThreadHandle, ThreadFunctionReturnType * = 0);
+ bool KillThread(ThreadHandle); // use only for abnormal termination
+ void Close(ThreadHandle); // should be called once for every handle obtained from StartThread.
+ //--------------------------------------------------------
+
+
+
+
+ //--------------------------------------------------------
+ class DllExport noncopyableobject
+ {
+ protected:
+ noncopyableobject() {}
+ private:
+ noncopyableobject(const noncopyableobject &);
+ noncopyableobject & operator=(const noncopyableobject &);
+ };
+ //--------------------------------------------------------
+
+
+ //--------------------------------------------------------
+ // Thread Mutex class that needs to be explicitly initialized
+ class DllExport ThreadMutexInited : public noncopyableobject
+ {
+ protected:
+ class OSDependentMutex;
+ OSDependentMutex* m_osdmutex;
+
+ public:
+ ThreadMutexInited();
+ ~ThreadMutexInited();
+
+ void init();
+ void uninit();
+ inline bool is_init() { return 0 != m_osdmutex; }
+ void obtain();
+ bool tryobtain();
+ void release();
+
+ private:
+ ThreadMutexInited(const ThreadMutexInited&); // cannot be copied
+ ThreadMutexInited& operator=(const ThreadMutexInited&); // cannot be copied
+
+ public:
+ class lock : public noncopyableobject
+ {
+ protected:
+ ThreadMutexInited &m_mutex;
+ public:
+ inline lock(ThreadMutexInited &mtx) : m_mutex(mtx) { m_mutex.obtain(); }
+ inline ~lock() { m_mutex.release(); }
+ };
+ class trylock : public noncopyableobject
+ {
+ protected:
+ ThreadMutexInited &m_mutex;
+ bool m_bObtained;
+ public:
+ inline trylock(ThreadMutexInited &mtx) : m_mutex(mtx), m_bObtained(false) { m_bObtained = m_mutex.tryobtain(); }
+ inline ~trylock() { if (m_bObtained) m_mutex.release(); }
+ inline operator bool() const { return m_bObtained; }
+ };
+ };
+ //--------------------------------------------------------
+
+ // Thread Mutex class that is automatically initialized
+ class ThreadMutex : public ThreadMutexInited
+ {
+ public:
+ ThreadMutex() {init();}
+ };
+
+ //--------------------------------------------------------
+ class DllExport ThreadConditionSignal : public noncopyableobject
+ {
+ protected:
+ class OSDependentObject;
+ OSDependentObject &m_osdepobj;
+
+ protected:
+ void obtain_mutex();
+ bool tryobtain_mutex();
+ void release_mutex();
+
+ public:
+ class lock : public noncopyableobject
+ {
+ protected:
+ ThreadConditionSignal &m_tcs;
+ public:
+ lock(ThreadConditionSignal &tcs) : m_tcs(tcs) { m_tcs.obtain_mutex(); }
+ ~lock() { m_tcs.release_mutex(); }
+ };
+ class trylock : public noncopyableobject
+ {
+ protected:
+ ThreadConditionSignal &m_tcs;
+ bool m_bObtained;
+ public:
+ trylock(ThreadConditionSignal &tcs) : m_tcs(tcs), m_bObtained(false) { m_bObtained = m_tcs.tryobtain_mutex(); }
+ ~trylock() { if (m_bObtained) m_tcs.release_mutex(); }
+ operator bool() const { return m_bObtained; }
+ };
+
+ public:
+ ThreadConditionSignal();
+ ~ThreadConditionSignal();
+
+ // IMPORTANT: All of the functions below MUST be called ONLY while holding a lock for this object !!!
+ void await_condition();
+ bool await_condition(timediff tdTimeout);
+ void signal_condition_single();
+ void signal_condition_broadcast();
+ };
+ //--------------------------------------------------------
+
+
+
+
+
+ //--------------------------------------------------------
+ // A doorbell is a simple communication mechanism that allows
+ // one thread two wake another when there is some work to be done.
+ // The signal is 'clear on read'. This class is not intended for
+ // multi-way communication (i.e. more than two threads).
+//#define XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR (!XPLATFORMTHREADS_WINDOWS && !XPLATFORMOSSERVICES_MACOS)
+#ifdef XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR
+#undef XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR
+#endif
+#define XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR 1
+#if XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR
+ class doorbell_type
+ {
+ protected:
+ ThreadConditionSignal m_signal;
+ bool m_rang;
+ protected:
+ template<bool wait_forever> bool wait_for_ring_internal(timediff timeout)
+ {// mutex
+ ThreadConditionSignal::lock guard(m_signal);
+ if (!m_rang)
+ {
+ if (wait_forever)
+ {
+ m_signal.await_condition();
+ }
+ else
+ {
+ m_signal.await_condition(timeout);
+ }
+ }
+ const bool rang = m_rang;
+ m_rang = false;
+ return rang;
+ }// mutex
+
+ public:
+ doorbell_type() : m_rang(false) {}
+ inline ~doorbell_type() {}
+ inline void ring()
+ {// mutex
+ ThreadConditionSignal::lock guard(m_signal);
+ m_rang = true;
+ m_signal.signal_condition_single();
+ }// mutex
+ inline bool wait_for_ring() { return wait_for_ring_internal<true>(0); }
+ inline bool wait_for_ring(timediff timeout) { return wait_for_ring_internal<false>(timeout); }
+ };
+#else
+ class doorbell_type : public noncopyableobject
+ {
+ protected:
+ os_dependent_handle_type m_os_dependent_handle;
+ protected:
+ template<bool wait_forever> bool wait_for_ring_internal(timediff);
+ public:
+ doorbell_type();
+ ~doorbell_type();
+ void ring();
+ bool wait_for_ring();
+ bool wait_for_ring(timediff timeout);
+ };
+#endif // XPLATFORMTHREADS_DOORBELL_INLINE_USING_COND_VAR
+ //--------------------------------------------------------
+
+ //---------------------------------------------------------------
+ class DllExport WCThreadRef // Class which holds the threadRef, DWORD in Windows and pthread_t in POSIX (Mac, Unix)
+ {
+ public:
+ class OSDependent; // the class which contains the OS Dependent implementation
+
+ WCThreadRef() : m_osThreadRef(0) {}
+ bool is_invalid() const { return m_osThreadRef == 0;}
+
+ operator uintptr_t() const {return m_osThreadRef;}
+
+ protected:
+ uintptr_t m_osThreadRef;
+ WCThreadRef(uintptr_t n) : m_osThreadRef(n) {}
+
+ friend DllExport bool operator==(const WCThreadRef& first, const WCThreadRef& second);
+ friend DllExport bool operator!=(const WCThreadRef& first, const WCThreadRef& second);
+ friend DllExport bool operator<(const WCThreadRef& first, const WCThreadRef& second);
+ friend DllExport bool operator>(const WCThreadRef& first, const WCThreadRef& second);
+ };
+
+ DllExport WCThreadRef GetCurrentThreadRef(); // getting the current thread reference - cross-platform implemented
+ bool IsThreadExists(const WCThreadRef& threadRef); // correct to the very snapshot of time of execution
+
+ //---------------------------------------------------------------
+
+ class DllExport WCAtomicLock
+ {
+ public:
+ WCAtomicLock() : m_the_lock(0) {}
+ bool obtain(const uint32_t in_num_trys = 1);
+ void release();
+ private:
+ int32_t m_the_lock;
+ };
+
+ //#include "BasicTypes/WavesAPIResetAligment.h"
+#ifdef PLATFORM_WINDOWS
+#pragma pack(pop)
+#endif
+
+#ifdef __APPLE__
+#ifdef __GNUC__
+#pragma pack(pop)
+#endif
+#endif
+
+class WCStThreadMutexLocker
+{
+public:
+ WCStThreadMutexLocker(wvNS::wvThread::ThreadMutexInited& in_mutex) :
+ m_mutex(in_mutex)
+ {
+ m_mutex.obtain();
+ }
+
+ ~WCStThreadMutexLocker()
+ {
+ m_mutex.release();
+ }
+protected:
+ wvNS::wvThread::ThreadMutexInited& m_mutex;
+ WCStThreadMutexLocker(const WCStThreadMutexLocker&);
+ WCStThreadMutexLocker& operator=(const WCStThreadMutexLocker&);
+};
+
+} // namespace wvThread
+
+
+} //namespace wvNS {
+#endif // #ifndef __WCThreadSafe_h_