fix rest of non-portable includes
[folly.git] / folly / detail / Futex.cpp
index 0e4292370ad58833f8454f7336c14eb4e2fd45bc..f8a8dbc7819182ad1991948f9863a7d06fbcfa62 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include <folly/detail/Futex.h>
+#include <boost/intrusive/list.hpp>
+#include <folly/Hash.h>
+#include <folly/ScopeGuard.h>
+#include <folly/portability/SysSyscall.h>
 #include <stdint.h>
 #include <string.h>
+#include <cerrno>
 #include <condition_variable>
 #include <mutex>
-#include <boost/intrusive/list.hpp>
-#include <folly/Hash.h>
-#include <folly/ScopeGuard.h>
 
 #ifdef __linux__
-# include <errno.h>
-# include <linux/futex.h>
-# include <sys/syscall.h>
+#include <linux/futex.h>
 #endif
 
 using namespace std::chrono;
@@ -186,22 +186,15 @@ struct EmulatedFutexBucket {
   boost::intrusive::list<EmulatedFutexWaitNode> waiters_;
 
   static const size_t kNumBuckets = 4096;
-  static EmulatedFutexBucket* gBuckets;
-  static std::once_flag gBucketInit;
 
   static EmulatedFutexBucket& bucketFor(void* addr) {
-    std::call_once(gBucketInit, [](){
-      gBuckets = new EmulatedFutexBucket[kNumBuckets];
-    });
+    static auto gBuckets = new EmulatedFutexBucket[kNumBuckets];
     uint64_t mixedBits = folly::hash::twang_mix64(
         reinterpret_cast<uintptr_t>(addr));
     return gBuckets[mixedBits % kNumBuckets];
   }
 };
 
-EmulatedFutexBucket* EmulatedFutexBucket::gBuckets;
-std::once_flag EmulatedFutexBucket::gBucketInit;
-
 int emulatedFutexWake(void* addr, int count, uint32_t waitMask) {
   auto& bucket = EmulatedFutexBucket::bucketFor(addr);
   std::unique_lock<std::mutex> bucketLock(bucket.mutex_);
@@ -225,21 +218,25 @@ int emulatedFutexWake(void* addr, int count, uint32_t waitMask) {
   return numAwoken;
 }
 
+template <typename F>
 FutexResult emulatedFutexWaitImpl(
-        void* addr,
-        uint32_t expected,
-        time_point<system_clock>* absSystemTime,
-        time_point<steady_clock>* absSteadyTime,
-        uint32_t waitMask) {
+    F* futex,
+    uint32_t expected,
+    time_point<system_clock>* absSystemTime,
+    time_point<steady_clock>* absSteadyTime,
+    uint32_t waitMask) {
+  static_assert(
+      std::is_same<F, Futex<std::atomic>>::value ||
+          std::is_same<F, Futex<EmulatedFutexAtomic>>::value,
+      "Type F must be either Futex<std::atomic> or Futex<EmulatedFutexAtomic>");
+  void* addr = static_cast<void*>(futex);
   auto& bucket = EmulatedFutexBucket::bucketFor(addr);
   EmulatedFutexWaitNode node(addr, waitMask);
 
   {
     std::unique_lock<std::mutex> bucketLock(bucket.mutex_);
 
-    uint32_t actual;
-    memcpy(&actual, addr, sizeof(uint32_t));
-    if (actual != expected) {
+    if (futex->load(std::memory_order_relaxed) != expected) {
       return FutexResult::VALUE_CHANGED;
     }