X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FCachelinePadded.h;h=27a06b4a917bbd96b1dcd9e16bf34616b9fb92ae;hp=d71b24eb513f74e66c4376c613fcd1a1aabe2c0a;hb=3f4a8ae005738662fbbca4a85c959df2bf0d059b;hpb=e0ac799a799a72413a1b4b74b1b4d4f3cb64259d diff --git a/folly/CachelinePadded.h b/folly/CachelinePadded.h index d71b24eb..27a06b4a 100644 --- a/folly/CachelinePadded.h +++ b/folly/CachelinePadded.h @@ -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. @@ -16,48 +16,37 @@ #pragma once -#include +#include +#include + +#include namespace folly { /** - * Holds a type T, in addition to enough padding to round the size up to the - * next multiple of the false sharing range used by folly. - * - * If T is standard-layout, then casting a T* you get from this class to a - * CachelinePadded* is safe. - * - * This class handles padding, but imperfectly handles alignment. (Note that - * alignment matters for false-sharing: imagine a cacheline size of 64, and two - * adjacent 64-byte objects, with the first starting at an offset of 32. The - * last 32 bytes of the first object share a cacheline with the first 32 bytes - * of the second.). We alignas this class to be at least cacheline-sized, but - * it's implementation-defined what that means (since a cacheline is almost - * certainly larger than the maximum natural alignment). The following should be - * true for recent compilers on common architectures: - * - * For heap objects, alignment needs to be handled at the allocator level, such - * as with posix_memalign (this isn't necessary with jemalloc, which aligns - * objects that are a multiple of cacheline size to a cacheline). + * Holds a type T, in addition to enough padding to ensure that it isn't subject + * to false sharing within the range used by folly. * - * For static and stack objects, the alignment should be obeyed, and no specific - * intervention is necessary. + * If `sizeof(T) <= alignof(T)` then the inner `T` will be entirely within one + * false sharing range (AKA cache line). */ template class CachelinePadded { + static_assert( + alignof(T) <= max_align_v, + "CachelinePadded does not support over-aligned types."); + public: template explicit CachelinePadded(Args&&... args) - : impl_(std::forward(args)...) {} - - CachelinePadded() {} + : inner_(std::forward(args)...) {} T* get() { - return &impl_.item; + return &inner_; } const T* get() const { - return &impl_.item; + return &inner_; } T* operator->() { @@ -77,6 +66,12 @@ class CachelinePadded { } private: - detail::CachelinePaddedImpl impl_; + static constexpr size_t paddingSize() noexcept { + return hardware_destructive_interference_size - + (alignof(T) % hardware_destructive_interference_size); + } + char paddingPre_[paddingSize()]; + T inner_; + char paddingPost_[paddingSize()]; }; -} +} // namespace folly