#pragma once
-#include <folly/detail/CachelinePaddedImpl.h>
+#include <cstddef>
+
+#include <folly/Portability.h>
+#include <folly/concurrency/CacheLocality.h>
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<T>* 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 <typename T>
class CachelinePadded {
+ static_assert(
+ alignof(T) <= folly::max_align_v,
+ "CachelinePadded does not support over-aligned types.");
+
public:
template <typename... Args>
explicit CachelinePadded(Args&&... args)
- : impl_(std::forward<Args>(args)...) {}
-
- CachelinePadded() {}
+ : inner_(std::forward<Args>(args)...) {}
T* get() {
- return &impl_.item;
+ return &inner_;
}
const T* get() const {
- return &impl_.item;
+ return &inner_;
}
T* operator->() {
}
private:
- detail::CachelinePaddedImpl<T> impl_;
+ static constexpr size_t paddingSize() noexcept {
+ return CacheLocality::kFalseSharingRange -
+ (alignof(T) % CacheLocality::kFalseSharingRange);
+ }
+ char paddingPre_[paddingSize()];
+ T inner_;
+ char paddingPost_[paddingSize()];
};
-}
+} // namespace folly