X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FMicroSpinLock.h;h=8996f8c328e1016922a2881ffa6cf98efd5c2fcc;hb=59f59178ba38bc793f809d21fc532e160ae5e34b;hp=cccba15d88b6a8523f115d42537c481d7678cdfc;hpb=406822b8462145dc26be2a1a837eda9c6706dfb2;p=folly.git diff --git a/folly/MicroSpinLock.h b/folly/MicroSpinLock.h index cccba15d..8996f8c3 100644 --- a/folly/MicroSpinLock.h +++ b/folly/MicroSpinLock.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 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. @@ -14,6 +14,22 @@ * limitations under the License. */ +/* + * N.B. You most likely do _not_ want to use MicroSpinLock or any + * other kind of spinlock. Consider MicroLock instead. + * + * In short, spinlocks in preemptive multi-tasking operating systems + * have serious problems and fast mutexes like std::mutex are almost + * certainly the better choice, because letting the OS scheduler put a + * thread to sleep is better for system responsiveness and throughput + * than wasting a timeslice repeatedly querying a lock held by a + * thread that's blocked, and you can't prevent userspace + * programs blocking. + * + * Spinlocks in an operating system kernel make much more sense than + * they do in userspace. + */ + #pragma once /* @@ -22,17 +38,15 @@ */ #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include -#include -#include #include +#include +#include namespace folly { @@ -70,11 +84,11 @@ struct MicroSpinLock { sleeper.wait(); } } while (!try_lock()); - DCHECK(payload()->load() == LOCKED); + assert(payload()->load() == LOCKED); } void unlock() { - CHECK(payload()->load() == LOCKED); + assert(payload()->load() == LOCKED); payload()->store(FREE, std::memory_order_release); } @@ -89,6 +103,9 @@ struct MicroSpinLock { std::memory_order_relaxed); } }; +static_assert( + std::is_pod::value, + "MicroSpinLock must be kept a POD type."); ////////////////////////////////////////////////////////////////////// @@ -102,7 +119,7 @@ struct MicroSpinLock { #define FOLLY_CACHE_LINE_SIZE 64 template -struct SpinLockArray { +struct alignas(max_align_v) SpinLockArray { T& operator[](size_t i) { return data_[i].lock; } @@ -123,16 +140,14 @@ struct SpinLockArray { "Invalid size of PaddedSpinLock"); // Check if T can theoretically cross a cache line. - // NOTE: It should be alignof(std::max_align_t), but max_align_t - // isn't supported by gcc 4.6.2. - static_assert(alignof(MaxAlign) > 0 && - FOLLY_CACHE_LINE_SIZE % alignof(MaxAlign) == 0 && - sizeof(T) <= alignof(MaxAlign), - "T can cross cache line boundaries"); + static_assert( + max_align_v > 0 && FOLLY_CACHE_LINE_SIZE % max_align_v == 0 && + sizeof(T) <= max_align_v, + "T can cross cache line boundaries"); char padding_[FOLLY_CACHE_LINE_SIZE]; std::array data_; -} __attribute__((__aligned__)); +}; ////////////////////////////////////////////////////////////////////// @@ -140,4 +155,4 @@ typedef std::lock_guard MSLGuard; ////////////////////////////////////////////////////////////////////// -} +} // namespace folly