#pragma once
-#include <syscall.h>
-#include <linux/futex.h>
-#include <climits>
#include <atomic>
+#include <climits>
#include <thread>
+
#include <glog/logging.h>
#include <folly/Bits.h>
#include <folly/Likely.h>
+#include <folly/detail/Futex.h>
#include <folly/portability/SysTime.h>
#include <folly/portability/Unistd.h>
namespace folly {
-namespace detail {
-
-inline int futex(int* uaddr, int op, int val, const timespec* timeout,
- int* uaddr2, int val3) noexcept {
- return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
-}
-
-} // namespace detail
-
/**
* Event count: a condition variable for lock free algorithms.
*
static_assert(sizeof(int) == 4, "bad platform");
static_assert(sizeof(uint32_t) == 4, "bad platform");
static_assert(sizeof(uint64_t) == 8, "bad platform");
+ static_assert(sizeof(std::atomic<uint64_t>) == 8, "bad platform");
+ static_assert(sizeof(detail::Futex<std::atomic>) == 4, "bad platform");
static constexpr size_t kEpochOffset = kIsLittleEndian ? 1 : 0;
inline void EventCount::doNotify(int n) noexcept {
uint64_t prev = val_.fetch_add(kAddEpoch, std::memory_order_acq_rel);
if (UNLIKELY(prev & kWaiterMask)) {
- detail::futex(reinterpret_cast<int*>(&val_) + kEpochOffset,
- FUTEX_WAKE, n, nullptr, nullptr, 0);
+ (reinterpret_cast<detail::Futex<std::atomic>*>(&val_) + kEpochOffset)
+ ->futexWake(n);
}
}
inline void EventCount::wait(Key key) noexcept {
while ((val_.load(std::memory_order_acquire) >> kEpochShift) == key.epoch_) {
- detail::futex(reinterpret_cast<int*>(&val_) + kEpochOffset,
- FUTEX_WAIT, key.epoch_, nullptr, nullptr, 0);
+ (reinterpret_cast<detail::Futex<std::atomic>*>(&val_) + kEpochOffset)
+ ->futexWait(key.epoch_);
}
// memory_order_relaxed would suffice for correctness, but the faster
// #waiters gets to 0, the less likely it is that we'll do spurious wakeups