Commit d383a116 authored by Orvid King's avatar Orvid King Committed by facebook-github-bot-4

Generalize FOLLY_SPIN_WAIT to use Portability methods

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
parent f02969df
...@@ -114,10 +114,11 @@ insertInternal(KeyT key_in, T&& value) { ...@@ -114,10 +114,11 @@ insertInternal(KeyT key_in, T&& value) {
// another thread now does ++numPendingEntries_, we expect it // another thread now does ++numPendingEntries_, we expect it
// to pass the isFull_.load() test above. (It shouldn't insert // to pass the isFull_.load() test above. (It shouldn't insert
// a new entry.) // a new entry.)
FOLLY_SPIN_WAIT( detail::atomic_hash_spin_wait([&] {
isFull_.load(std::memory_order_acquire) != NO_PENDING_INSERTS return
&& numPendingEntries_.readFull() != 0 (isFull_.load(std::memory_order_acquire) != NO_PENDING_INSERTS) &&
); (numPendingEntries_.readFull() != 0);
});
isFull_.store(NO_PENDING_INSERTS, std::memory_order_release); isFull_.store(NO_PENDING_INSERTS, std::memory_order_release);
if (relaxedLoadKey(*cell) == kEmptyKey_) { if (relaxedLoadKey(*cell) == kEmptyKey_) {
...@@ -161,9 +162,9 @@ insertInternal(KeyT key_in, T&& value) { ...@@ -161,9 +162,9 @@ insertInternal(KeyT key_in, T&& value) {
} }
DCHECK(relaxedLoadKey(*cell) != kEmptyKey_); DCHECK(relaxedLoadKey(*cell) != kEmptyKey_);
if (kLockedKey_ == acquireLoadKey(*cell)) { if (kLockedKey_ == acquireLoadKey(*cell)) {
FOLLY_SPIN_WAIT( detail::atomic_hash_spin_wait([&] {
kLockedKey_ == acquireLoadKey(*cell) return kLockedKey_ == acquireLoadKey(*cell);
); });
} }
const KeyT thisKey = acquireLoadKey(*cell); const KeyT thisKey = acquireLoadKey(*cell);
...@@ -397,5 +398,3 @@ struct AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::aha_iterator ...@@ -397,5 +398,3 @@ struct AtomicHashArray<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::aha_iterator
}; // aha_iterator }; // aha_iterator
} // namespace folly } // namespace folly
#undef FOLLY_SPIN_WAIT
...@@ -130,9 +130,9 @@ insertInternal(key_type key, T&& value) { ...@@ -130,9 +130,9 @@ insertInternal(key_type key, T&& value) {
} else { } else {
// If we lost the race, we'll have to wait for the next map to get // If we lost the race, we'll have to wait for the next map to get
// allocated before doing any insertion here. // allocated before doing any insertion here.
FOLLY_SPIN_WAIT( detail::atomic_hash_spin_wait([&] {
nextMapIdx >= numMapsAllocated_.load(std::memory_order_acquire) return nextMapIdx >= numMapsAllocated_.load(std::memory_order_acquire);
); });
} }
// Relaxed is ok here because either we just created this map, or we // 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 ...@@ -427,5 +427,3 @@ struct AtomicHashMap<KeyT, ValueT, HashFcn, EqualFcn, Allocator>::ahm_iterator
}; // ahm_iterator }; // ahm_iterator
} // namespace folly } // namespace folly
#undef FOLLY_SPIN_WAIT
...@@ -14,25 +14,29 @@ ...@@ -14,25 +14,29 @@
* limitations under the License. * 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 // 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) namespace folly { namespace detail {
#define FOLLY_SPIN_WAIT(condition) \
for (int counter = 0; condition; ++counter) { \ template <typename Cond>
if (counter < 10000) continue; \ void atomic_hash_spin_wait(Cond condition) {
pthread_yield(); \ constexpr size_t kPauseLimit = 10000;
} for (size_t i = 0; condition(); ++i) {
#else if (i < kPauseLimit) {
#define FOLLY_SPIN_WAIT(condition) \ folly::asm_pause();
for (int counter = 0; condition; ++counter) { \ } else {
if (counter < 10000) { \ std::this_thread::yield();
asm volatile("pause"); \ }
continue; \
} \
pthread_yield(); \
} }
}
}} // namespace folly::detail
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment