#include <mutex>
#include <type_traits>
-#include <glog/logging.h>
#include <folly/detail/Sleeper.h>
+#include <glog/logging.h>
#if !FOLLY_X64 && !FOLLY_A64 && !FOLLY_PPC64
# error "PicoSpinLock.h is currently x64, aarch64 and ppc64 only."
public:
static const UIntType kLockBitMask_ = UIntType(1) << Bit;
- UIntType lock_;
+ mutable UIntType lock_;
/*
* You must call this function before using this class, if you
*/
void init(IntType initialValue = 0) {
CHECK(!(initialValue & kLockBitMask_));
- lock_ = UIntType(initialValue);
+ reinterpret_cast<std::atomic<UIntType>*>(&lock_)->store(
+ UIntType(initialValue), std::memory_order_release);
}
/*
* as you normally get.)
*/
IntType getData() const {
- return static_cast<IntType>(lock_ & ~kLockBitMask_);
+ auto res = reinterpret_cast<std::atomic<UIntType>*>(&lock_)->load(
+ std::memory_order_relaxed) &
+ ~kLockBitMask_;
+ return res;
}
/*
*/
void setData(IntType w) {
CHECK(!(w & kLockBitMask_));
- lock_ = UIntType((lock_ & kLockBitMask_) | w);
+ auto l = reinterpret_cast<std::atomic<UIntType>*>(&lock_);
+ l->store(
+ (l->load(std::memory_order_relaxed) & kLockBitMask_) | w,
+ std::memory_order_relaxed);
}
/*
bool try_lock() const {
bool ret = false;
-#ifdef _MSC_VER
+#if defined(FOLLY_SANITIZE_THREAD)
+ // TODO: Might be able to fully move to std::atomic when gcc emits lock btr:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49244
+ ret =
+ !(reinterpret_cast<std::atomic<UIntType>*>(&lock_)->fetch_or(
+ kLockBitMask_, std::memory_order_acquire) &
+ kLockBitMask_);
+#elif _MSC_VER
switch (sizeof(IntType)) {
case 2:
// There is no _interlockedbittestandset16 for some reason :(
void doTest() {
using UT = typename std::make_unsigned<T>::type;
T ourVal = rand() % T(UT(1) << (sizeof(UT) * 8 - 1));
- for (int i = 0; i < 10000; ++i) {
+ for (int i = 0; i < 100; ++i) {
std::lock_guard<PicoSpinLock<T>> guard(lock);
lock.setData(ourVal);
for (int n = 0; n < 10; ++n) {
// affect bits outside the ones MicroLock is defined to affect.
struct {
uint8_t a;
- volatile uint8_t b;
+ std::atomic<uint8_t> b;
MicroLock alock;
- volatile uint8_t d;
+ std::atomic<uint8_t> d;
} x;
uint8_t origB = 'b';
void trylockTestThread(TryLockState<LOCK>* state, size_t count) {
while (true) {
folly::asm_pause();
+ bool ret = state->lock2.try_lock();
SpinLockGuardImpl<LOCK> g(state->lock1);
if (state->obtained >= count) {
+ if (ret) {
+ state->lock2.unlock();
+ }
break;
}
- bool ret = state->lock2.try_lock();
- EXPECT_NE(state->locked, ret);
if (ret) {
// We got lock2.
+ EXPECT_NE(state->locked, ret);
++state->obtained;
state->locked = true;