34 #define FOLLY_PICO_SPIN_LOCK_H_ 46 #include <type_traits> 48 #include <glog/logging.h> 53 #if !FOLLY_X64 && !FOLLY_AARCH64 && !FOLLY_PPC64 54 #error "PicoSpinLock.h is currently x64, aarch64 and ppc64 only." 72 template <
class IntType,
int Bit =
sizeof(IntType) * 8 - 1>
79 "PicoSpinLock needs an integral type");
81 sizeof(IntType) == 2 ||
sizeof(IntType) == 4 ||
sizeof(IntType) == 8,
82 "PicoSpinLock can't work on integers smaller than 2 bytes");
85 static const UIntType kLockBitMask_ = UIntType(1) << Bit;
96 void init(IntType initialValue = 0) {
97 CHECK(!(initialValue & kLockBitMask_));
98 reinterpret_cast<std::atomic<UIntType>*
>(&lock_)->store(
99 UIntType(initialValue), std::memory_order_release);
112 auto res =
reinterpret_cast<std::atomic<UIntType>*
>(&lock_)->
load(
113 std::memory_order_relaxed) &
125 CHECK(!(w & kLockBitMask_));
126 auto l =
reinterpret_cast<std::atomic<UIntType>*
>(&lock_);
128 (l->load(std::memory_order_relaxed) & kLockBitMask_) | w,
129 std::memory_order_relaxed);
139 #if defined(FOLLY_SANITIZE_THREAD) 143 !(
reinterpret_cast<std::atomic<UIntType>*
>(&lock_)->fetch_or(
144 kLockBitMask_, std::memory_order_acquire) &
147 switch (
sizeof(IntType)) {
150 ret = _InterlockedOr16((
volatile short*)&lock_, (
short)kLockBitMask_) &
154 ret = _interlockedbittestandset((
volatile long*)&lock_, Bit);
157 ret = _interlockedbittestandset64((
volatile long long*)&lock_, Bit);
161 #define FB_DOBTS(size) \ 162 asm volatile("lock; bts" #size " %1, (%2); setnc %0" \ 164 : "i"(Bit), "r"(&lock_) \ 167 switch (
sizeof(IntType)) {
182 auto const lock =
reinterpret_cast<SIntType*
>(&lock_);
183 auto const mask =
static_cast<SIntType
>(kLockBitMask_);
184 return !(mask & __atomic_fetch_or(
lock, mask, __ATOMIC_ACQUIRE));
186 #define FB_DOBTS(size) \ 190 "arx 14,0,%[lockPtr]\n" \ 192 "\tsldi 15,15,%[bit]\n" \ 193 "\tand. 16,15,14\n" \ 197 "cx. 14,0,%[lockPtr]\n" \ 199 "\tori %[output],%[output],1\n" \ 202 : [output] "+r"(ret) \ 203 : [lockPtr] "r"(&lock_), [bit] "i"(Bit) \ 204 : "cr0", "memory", "r14", "r15", "r16") 206 switch (
sizeof(IntType)) {
220 #error "x86 aarch64 ppc64 only" 231 while (!try_lock()) {
242 switch (
sizeof(IntType)) {
245 _InterlockedAnd16((
volatile short*)&lock_, (
short)~kLockBitMask_);
248 _interlockedbittestandreset((
volatile long*)&lock_, Bit);
251 _interlockedbittestandreset64((
volatile long long*)&lock_, Bit);
255 #define FB_DOBTR(size) \ 256 asm volatile("lock; btr" #size " %0, (%1)" \ 258 : "i"(Bit), "r"(&lock_) \ 263 switch (
sizeof(IntType)) {
278 auto const lock =
reinterpret_cast<SIntType*
>(&lock_);
279 auto const mask =
static_cast<SIntType
>(kLockBitMask_);
280 __atomic_fetch_and(
lock, ~mask, __ATOMIC_RELEASE);
282 #define FB_DOBTR(size) \ 286 "arx 14,0,%[lockPtr]\n" \ 288 "\tsldi 15,15,%[bit]\n" \ 291 "cx. 14,0,%[lockPtr]\n" \ 295 : [lockPtr] "r"(&lock_), [bit] "i"(Bit) \ 296 : "cr0", "memory", "r14", "r15") 298 switch (
sizeof(IntType)) {
312 #error "x64 aarch64 ppc64 only"
—— Concurrent Priority Queue Implementation ——
void init(IntType initialValue=0)
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
static const char *const value
std::make_unsigned< IntType >::type UIntType