// still not overflow uint16_t.
constexpr int32_t OOR = 10000;
-FOLLY_ALIGNED(16) constexpr uint16_t shift1[] = {
+alignas(16) constexpr uint16_t shift1[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
-FOLLY_ALIGNED(16) constexpr uint16_t shift10[] = {
+alignas(16) constexpr uint16_t shift10[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
-FOLLY_ALIGNED(16) constexpr uint16_t shift100[] = {
+alignas(16) constexpr uint16_t shift100[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
OOR, OOR, OOR, OOR, OOR, OOR // 250
};
-FOLLY_ALIGNED(16) constexpr uint16_t shift1000[] = {
+alignas(16) constexpr uint16_t shift1000[] = {
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 0-9
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 10
OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, OOR, // 20
// 10^i, defined for i 0 through 19.
// This is 20 * 8 == 160 bytes, which fits neatly into 5 cache lines
// (assuming a cache line size of 64).
- static const uint64_t powersOf10[20] FOLLY_ALIGNED(64) = {
+ alignas(64) static const uint64_t powersOf10[20] = {
1,
10,
100,
}
};
- struct FOLLY_ALIGN_TO_AVOID_FALSE_SHARING LocalList {
+ struct alignas(hardware_destructive_interference_size) LocalList {
AtomicStruct<TaggedPtr,Atom> head;
LocalList() : head(TaggedPtr{}) {}
/// raw storage, only 1..min(size_,actualCapacity_) (inclusive) are
/// actually constructed. Note that slots_[0] is not constructed or used
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING Slot* slots_;
+ alignas(hardware_destructive_interference_size) Slot* slots_;
/// use AccessSpreader to find your list. We use stripes instead of
/// thread-local to avoid the need to grow or shrink on thread start
/// this is the head of a list of node chained by globalNext, that are
/// themselves each the head of a list chained by localNext
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING AtomicStruct<TaggedPtr,Atom> globalHead_;
+ alignas(hardware_destructive_interference_size)
+ AtomicStruct<TaggedPtr, Atom> globalHead_;
///////////// private methods
};
/// The maximum number of items in the queue at once
- size_t FOLLY_ALIGN_TO_AVOID_FALSE_SHARING capacity_;
+ alignas(hardware_destructive_interference_size) size_t capacity_;
/// Anonymous union for use when Dynamic = false and true, respectively
union {
Atom<size_t> dcapacity_;
/// Enqueuers get tickets from here
- Atom<uint64_t> FOLLY_ALIGN_TO_AVOID_FALSE_SHARING pushTicket_;
+ alignas(hardware_destructive_interference_size) Atom<uint64_t> pushTicket_;
/// Dequeuers get tickets from here
- Atom<uint64_t> FOLLY_ALIGN_TO_AVOID_FALSE_SHARING popTicket_;
+ alignas(hardware_destructive_interference_size) Atom<uint64_t> popTicket_;
/// This is how many times we will spin before using FUTEX_WAIT when
/// the queue is full on enqueue, adaptively computed by occasionally
/// spinning for longer and smoothing with an exponential moving average
- Atom<uint32_t> FOLLY_ALIGN_TO_AVOID_FALSE_SHARING pushSpinCutoff_;
+ alignas(
+ hardware_destructive_interference_size) Atom<uint32_t> pushSpinCutoff_;
/// The adaptive spin cutoff when the queue is empty on dequeue
- Atom<uint32_t> FOLLY_ALIGN_TO_AVOID_FALSE_SHARING popSpinCutoff_;
+ alignas(hardware_destructive_interference_size) Atom<uint32_t> popSpinCutoff_;
/// Alignment doesn't prevent false sharing at the end of the struct,
/// so fill out the last cache line
// compiler specific attribute translation
// msvc should come first, so if clang is in msvc mode it gets the right defines
-#if defined(__clang__) || defined(__GNUC__)
-# define FOLLY_ALIGNED(size) __attribute__((__aligned__(size)))
-#elif defined(_MSC_VER)
-# define FOLLY_ALIGNED(size) __declspec(align(size))
-#else
-# error Cannot define FOLLY_ALIGNED on this platform
-#endif
-
// NOTE: this will only do checking in msvc with versions that support /analyze
#if _MSC_VER
# ifdef _USE_ATTRIBUTES_FOR_SAL
const uint32_t size_;
T* const records_;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING std::atomic<unsigned int> readIndex_;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING std::atomic<unsigned int> writeIndex_;
+ alignas(hardware_destructive_interference_size)
+ std::atomic<unsigned int> readIndex_;
+ alignas(hardware_destructive_interference_size)
+ std::atomic<unsigned int> writeIndex_;
char pad1_[hardware_destructive_interference_size - sizeof(writeIndex_)];
};
typedef Atom<uintptr_t> DeferredReaderSlot;
private:
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING static DeferredReaderSlot deferredReaders
- [kMaxDeferredReaders *
- kDeferredSeparationFactor];
+ alignas(hardware_destructive_interference_size) static DeferredReaderSlot
+ deferredReaders[kMaxDeferredReaders * kDeferredSeparationFactor];
// Performs an exclusive lock, waiting for state_ & waitMask to be
// zero first
typename Tag_,
template <typename> class Atom,
bool BlockImmediately>
-typename SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
- DeferredReaderSlot
- SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
- deferredReaders[kMaxDeferredReaders * kDeferredSeparationFactor] =
- {};
+alignas(hardware_destructive_interference_size)
+ typename SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
+ DeferredReaderSlot
+ SharedMutexImpl<ReaderPriority, Tag_, Atom, BlockImmediately>::
+ deferredReaders[kMaxDeferredReaders * kDeferredSeparationFactor] = {};
template <
bool ReaderPriority,
return true;
}
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING std::atomic<double> zeroTime_;
+ alignas(hardware_destructive_interference_size) std::atomic<double> zeroTime_;
};
/**
static CacheLocality uniform(size_t numCpus);
};
-// TODO replace with alignas(hardware_destructive_interference_size)
-
-/// An attribute that will cause a variable or field to be aligned so that
-/// it doesn't have false sharing with anything at a smaller memory address.
-#define FOLLY_ALIGN_TO_AVOID_FALSE_SHARING FOLLY_ALIGNED(128)
-
/// Knows how to derive a function pointer to the VDSO implementation of
/// getcpu(2), if available
struct Getcpu {
Atom<Segment*> next_;
const Ticket min_;
bool marked_; // used for iterative deletion
- FOLLY_ALIGNED(Align)
- Entry b_[SegmentSize];
+ alignas(Align) Entry b_[SegmentSize];
public:
explicit Segment(const Ticket t)
typename Allocator = std::allocator<uint8_t>,
template <typename> class Atom = std::atomic,
class Mutex = std::mutex>
-class FOLLY_ALIGNED(64) ConcurrentHashMapSegment {
+class alignas(64) ConcurrentHashMapSegment {
enum class InsertType {
DOES_NOT_EXIST, // insert/emplace operations. If key exists, return false.
MUST_EXIST, // assign operations. If key does not exist, return false.
folly::EventBaseManager* getEventBaseManager();
private:
- struct FOLLY_ALIGN_TO_AVOID_FALSE_SHARING IOThread : public Thread {
+ struct alignas(hardware_destructive_interference_size) IOThread
+ : public Thread {
IOThread(IOThreadPoolExecutor* pool)
: Thread(pool), shouldRun(true), pendingTasks(0) {}
std::atomic<bool> shouldRun;
struct TaskStatsCallbackRegistry;
- struct FOLLY_ALIGN_TO_AVOID_FALSE_SHARING Thread : public ThreadHandle {
+ struct alignas(hardware_destructive_interference_size) Thread
+ : public ThreadHandle {
explicit Thread(ThreadPoolExecutor* pool)
: id(nextId++),
handle(),
public:
/// Combining request record.
class Rec {
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
- folly::SaturatingSemaphore<false, Atom> valid_;
+ alignas(hardware_destructive_interference_size)
+ folly::SaturatingSemaphore<false, Atom> valid_;
folly::SaturatingSemaphore<false, Atom> done_;
folly::SaturatingSemaphore<false, Atom> disconnected_;
size_t index_;
const uint64_t kDefaultNumRecs = 64;
const uint64_t kIdleThreshold = 10;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
- Mutex m_;
+ alignas(hardware_destructive_interference_size) Mutex m_;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
- folly::SaturatingSemaphore<true, Atom> pending_;
+ alignas(hardware_destructive_interference_size)
+ folly::SaturatingSemaphore<true, Atom> pending_;
Atom<bool> shutdown_{false};
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
- uint32_t numRecs_;
+ alignas(hardware_destructive_interference_size) uint32_t numRecs_;
uint32_t maxOps_;
Atom<size_t> recs_;
bool dedicated_;
std::thread combiner_;
Pool recsPool_;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
- uint64_t uncombined_ = 0;
+ alignas(hardware_destructive_interference_size) uint64_t uncombined_ = 0;
uint64_t combined_ = 0;
uint64_t passes_ = 0;
uint64_t sessions_ = 0;
namespace folly {
-struct Line {
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
+struct alignas(hardware_destructive_interference_size) Line {
uint64_t val_;
};
* hazptr_rec
*/
-class hazptr_rec {
+class alignas(hardware_destructive_interference_size) hazptr_rec {
friend class hazptr_domain;
friend class hazptr_holder;
friend struct hazptr_tc_entry;
- FOLLY_ALIGN_TO_AVOID_FALSE_SHARING
std::atomic<const void*> hazptr_{nullptr};
hazptr_rec* next_{nullptr};
std::atomic<bool> active_{false};