Generalize FOLLY_SPIN_WAIT to use Portability methods
authorOrvid King <blah38621@gmail.com>
Fri, 31 Jul 2015 19:43:41 +0000 (12:43 -0700)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Fri, 31 Jul 2015 20:22:26 +0000 (13:22 -0700)
Summary: Improves MSVC support.
Closes #274

Note that this diff has been heavily modified from @Orvid's original PR by @yfeldblum and @sgolemon

Reviewed By: @yfeldblum

Differential Revision: D2284035

Pulled By: @sgolemon

folly/AtomicHashArray-inl.h
folly/AtomicHashMap-inl.h
folly/detail/AtomicHashUtils.h

index d455bbce7919383525de2f54e6bed586b4fa0be3..6ab54850beec6c5acec22d40679255e86abf4471 100644 (file)
@@ -114,10 +114,11 @@ insertInternal(KeyT key_in, T&& value) {
         // another thread now does ++numPendingEntries_, we expect it
         // to pass the isFull_.load() test above. (It shouldn't insert
         // a new entry.)
-        FOLLY_SPIN_WAIT(
-          isFull_.load(std::memory_order_acquire) != NO_PENDING_INSERTS
-            && numPendingEntries_.readFull() != 0
-        );
+        detail::atomic_hash_spin_wait([&] {
+          return
+            (isFull_.load(std::memory_order_acquire) != NO_PENDING_INSERTS) &&
+            (numPendingEntries_.readFull() != 0);
+        });
         isFull_.store(NO_PENDING_INSERTS, std::memory_order_release);
 
         if (relaxedLoadKey(*cell) == kEmptyKey_) {
@@ -161,9 +162,9 @@ insertInternal(KeyT key_in, T&& value) {
     }
     DCHECK(relaxedLoadKey(*cell) != kEmptyKey_);
     if (kLockedKey_ == acquireLoadKey(*cell)) {
-      FOLLY_SPIN_WAIT(
-        kLockedKey_ == acquireLoadKey(*cell)
-      );
+      detail::atomic_hash_spin_wait([&] {
+        return kLockedKey_ == acquireLoadKey(*cell);
+      });
     }
 
     const KeyT thisKey = acquireLoadKey(*cell);
@@ -397,5 +398,3 @@ struct AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::aha_iterator
 }; // aha_iterator
 
 } // namespace folly
-
-#undef FOLLY_SPIN_WAIT
index 4752cdd3aec69c345e36f12b8553e422ba421a30..4f7c6a12e91497ee573b07fb88d85413bfc18951 100644 (file)
@@ -130,9 +130,9 @@ insertInternal(key_type key, T&& value) {
   } else {
     // If we lost the race, we'll have to wait for the next map to get
     // allocated before doing any insertion here.
-    FOLLY_SPIN_WAIT(
-      nextMapIdx >= numMapsAllocated_.load(std::memory_order_acquire)
-    );
+    detail::atomic_hash_spin_wait([&] {
+      return nextMapIdx >= numMapsAllocated_.load(std::memory_order_acquire);
+    });
   }
 
   // Relaxed is ok here because either we just created this map, or we
@@ -427,5 +427,3 @@ struct AtomicHashMap<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::ahm_iterator
 }; // ahm_iterator
 
 } // namespace folly
-
-#undef FOLLY_SPIN_WAIT
index a896ba3a5812ec6133f6e87b6e44733d8df10b62..ebc96562de037f8f8b9c9c7241dd8e5585973935 100644 (file)
  * limitations under the License.
  */
 
+#ifndef incl_FOLLY_ATOMIC_HASH_UTILS_H
+#define incl_FOLLY_ATOMIC_HASH_UTILS_H
+
+#include <folly/Portability.h>
+#include <thread>
+
 // Some utilities used by AtomicHashArray and AtomicHashMap
 //
-// Note: no include guard; different -inl.h files include this and
-// undef it more than once in a translation unit.
-// override-include-guard
 
-#if !(defined(__x86__) || defined(__i386__) || FOLLY_X64)
-#define FOLLY_SPIN_WAIT(condition)                \
-   for (int counter = 0; condition; ++counter) {  \
-     if (counter < 10000) continue;               \
-     pthread_yield();                             \
-   }
-#else
-#define FOLLY_SPIN_WAIT(condition)              \
-  for (int counter = 0; condition; ++counter) { \
-    if (counter < 10000) {                      \
-      asm volatile("pause");                    \
-      continue;                                 \
-    }                                           \
-    pthread_yield();                            \
+namespace folly { namespace detail {
+
+template <typename Cond>
+void atomic_hash_spin_wait(Cond condition) {
+  constexpr size_t kPauseLimit = 10000;
+  for (size_t i = 0; condition(); ++i) {
+    if (i < kPauseLimit) {
+      folly::asm_pause();
+    } else {
+      std::this_thread::yield();
+    }
   }
+}
+
+}} // namespace folly::detail
+
 #endif