38 #ifndef BLOCXX_THREAD_ONCE_HPP_INCLUDE_GUARD_
39 #define BLOCXX_THREAD_ONCE_HPP_INCLUDE_GUARD_
40 #include "blocxx/BLOCXX_config.h"
43 #if defined(BLOCXX_USE_PTHREAD)
48 #elif defined(BLOCXX_WIN32)
49 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
53 namespace BLOCXX_NAMESPACE
57 #ifndef PTHREAD_MUTEX_INITIALIZER
58 #define PTHREAD_MUTEX_INITIALIZER {NULL, 0, 0}
62 #if defined(BLOCXX_USE_PTHREAD)
66 volatile ::sig_atomic_t flag;
67 ::pthread_mutex_t mtx;
70 #define BLOCXX_ONCE_INIT {0, PTHREAD_MUTEX_INITIALIZER}
72 #elif defined(BLOCXX_WIN32)
74 typedef long OnceFlag;
75 #define BLOCXX_ONCE_INIT 0
85 template <
typename FuncT>
86 void BLOCXX_COMMON_API
callOnce(OnceFlag& flag, FuncT
F);
90 #if defined(BLOCXX_USE_PTHREAD)
92 class CallOnce_pthread_MutexLock
95 CallOnce_pthread_MutexLock(::pthread_mutex_t* mtx)
98 #ifdef BLOCXX_NCR //we get coredump without initialization
99 if (m_mtx->field1 == NULL)
101 pthread_mutexattr_t attr;
102 int ret = pthread_mutexattr_create(&attr);
104 ret = pthread_mutex_init(m_mtx, attr);
106 pthread_mutexattr_delete(&attr);
112 #endif // Avoid unused variable warnings
113 pthread_mutex_lock(m_mtx);
116 ~CallOnce_pthread_MutexLock()
120 #endif // Avoid unused variable warnings
121 pthread_mutex_unlock(m_mtx);
125 pthread_mutex_destroy(m_mtx);
129 ::pthread_mutex_t* m_mtx;
132 template <
typename FuncT>
133 inline void callOnce(OnceFlag& flag, FuncT f)
138 CallOnce_pthread_MutexLock lock(&flag.mtx);
149 #if defined(BLOCXX_WIN32)
151 template <
typename FuncT>
152 inline void callOnce(OnceFlag& flag, FuncT f)
155 if (InterlockedCompareExchange(&flag, 1, 1) == 0)
157 wchar_t mutexName[MAX_PATH];
158 _snwprintf(mutexName, MAX_PATH, L
"%X-%p-587ccea9-c95a-4e81-ac51-ab0ddc6cef63", GetCurrentProcessId(), &flag);
159 mutexName[MAX_PATH - 1] = 0;
161 HANDLE mutex = CreateMutexW(NULL, FALSE, mutexName);
165 res = WaitForSingleObject(mutex, INFINITE);
168 if (InterlockedCompareExchange(&flag, 1, 1) == 0)
176 res = ReleaseMutex(mutex);
178 res = CloseHandle(mutex);
182 InterlockedExchange(&flag, 1);
185 res = ReleaseMutex(mutex);
187 res = CloseHandle(mutex);
#define BLOCXX_ASSERT(CON)
BLOCXX_ASSERT works similar to the assert() macro, but instead of calling abort(), it throws an AssertionException.
void readWriteMemoryBarrier()
This function is solely for the use of libblocxx threading primitives.
void BLOCXX_COMMON_API callOnce(OnceFlag &flag, FuncT F)
The first time callOnce is called with a given onceFlag argument, it calls func with no argument and ...