30 # ifndef WIN32_LEAN_AND_MEAN
31 # define WIN32_LEAN_AND_MEAN
36 # include <Processthreadsapi.h>
37 # include <Synchapi.h>
39 #elif defined(__i386__) || defined(__x86_64__)
40 # if defined(__clang__)
41 # include <emmintrin.h>
42 # elif defined(__INTEL_COMPILER)
43 # include <immintrin.h>
47 #include <libcopp/utils/config/libcopp_build_features.h>
63 # ifdef YieldProcessor
64 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE() YieldProcessor()
67 #elif defined(__GNUC__) || defined(__clang__)
68 # if defined(__i386__) || defined(__x86_64__)
75 # if defined(__clang__) || defined(__INTEL_COMPILER)
76 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE() _mm_pause()
78 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE() __builtin_ia32_pause()
81 # elif defined(__ia64__) || defined(__ia64)
87 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE() __asm__ __volatile__("hint @pause")
88 # elif defined(__arm__) && !defined(__ANDROID__)
93 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE() __asm__ __volatile__("yield")
99 #if !defined(__LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE)
100 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE()
108 #if 0 && defined(_MSC_VER)
112 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD() SwitchToThread()
114 #elif defined(__linux__) || defined(__unix__)
116 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD() sched_yield()
119 #ifndef __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD
120 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD() __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE()
128 #if defined(__LIBCOPP_UTIL_LOCK_ATOMIC_INT_TYPE_ATOMIC_STD)
138 # if defined(__GNUC__) && !defined(__clang__)
139 # if (__GNUC__ * 100 + __GNUC_MINOR__) <= 407
140 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD() __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD()
141 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP() __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD()
145 # ifndef __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD
146 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD() ::std::this_thread::yield()
148 # ifndef __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP
149 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP() ::std::this_thread::sleep_for(::std::chrono::milliseconds(1))
152 #elif defined(_MSC_VER)
153 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD() Sleep(0)
154 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP() Sleep(1)
157 #ifndef __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD
158 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD()
159 # define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP() __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD()
174 #define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_WAIT(x) \
176 unsigned char try_lock_times = static_cast<unsigned char>(x); \
177 if (try_lock_times < 4) { \
178 } else if (try_lock_times < 16) { \
179 __LIBCOPP_UTIL_LOCK_SPIN_LOCK_PAUSE(); \
180 } else if (try_lock_times < 32) { \
181 __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_YIELD(); \
182 } else if (try_lock_times < 64) { \
183 __LIBCOPP_UTIL_LOCK_SPIN_LOCK_CPU_YIELD(); \
185 __LIBCOPP_UTIL_LOCK_SPIN_LOCK_THREAD_SLEEP(); \
189 LIBCOPP_COPP_NAMESPACE_BEGIN
199 typedef enum { UNLOCKED = 0, LOCKED = 1 } lock_state_t;
200 LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type<
201 #if defined(LIBCOPP_LOCK_DISABLE_MT) && LIBCOPP_LOCK_DISABLE_MT
202 LIBCOPP_COPP_NAMESPACE_ID::util::lock::unsafe_int_type<unsigned int>
210 inline spin_lock() noexcept { lock_status_.store(UNLOCKED); }
213 unsigned char try_times = 0;
214 while (lock_status_.exchange(
static_cast<unsigned int>(LOCKED),
220 lock_status_.store(
static_cast<unsigned int>(UNLOCKED),
229 return lock_status_.exchange(
static_cast<unsigned int>(LOCKED),
234 return lock_status_.exchange(
static_cast<unsigned int>(UNLOCKED),
240 LIBCOPP_COPP_NAMESPACE_END
atomic wrapper fo integers Licensed under the MIT licenses.
LIBCOPP_COPP_NAMESPACE_ID::util::lock::atomic_int_type< unsigned int > lock_status_
bool try_unlock() noexcept
bool is_locked() noexcept
#define __LIBCOPP_UTIL_LOCK_SPIN_LOCK_WAIT(x)