Move max_align_v and max_align_t to folly/lang/Align.h
authorYedidya Feldblum <yfeldblum@fb.com>
Thu, 14 Dec 2017 00:29:37 +0000 (16:29 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 14 Dec 2017 00:38:14 +0000 (16:38 -0800)
Summary:
[Folly] Move `max_align_v` and `max_align_t` to `folly/lang/Align.h`.

And drop the macro `FOLLY_ALIGNED_MAX` - just use `alignas(max_align_v)` instead.

Reviewed By: Orvid

Differential Revision: D6554677

fbshipit-source-id: cacb335b141623506a41e95e0740613374279c6f

13 files changed:
folly/CachelinePadded.h
folly/Makefile.am
folly/MicroSpinLock.h
folly/Portability.h
folly/concurrency/CacheLocality.cpp
folly/concurrency/CacheLocality.h
folly/experimental/hazptr/memory_resource.cpp
folly/experimental/hazptr/memory_resource.h
folly/io/IOBuf.cpp
folly/lang/Align.h [new file with mode: 0644]
folly/memory/Arena.h
folly/memory/test/ThreadCachedArenaTest.cpp
folly/test/CachelinePaddedTest.cpp

index 233d4bd7c53b4dfd34bd4fd8ad03ec42a7b99360..cf10ecb7a8baadf63f1a046983f45051f3314b99 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <folly/Portability.h>
 #include <folly/concurrency/CacheLocality.h>
+#include <folly/lang/Align.h>
 
 namespace folly {
 
@@ -33,7 +34,7 @@ namespace folly {
 template <typename T>
 class CachelinePadded {
   static_assert(
-      alignof(T) <= folly::max_align_v,
+      alignof(T) <= max_align_v,
       "CachelinePadded does not support over-aligned types.");
 
  public:
index 2b077c754b67a777762e432d27b9f50882b9cadd..468320904fdeafa457da974bdbc1494e11071178 100644 (file)
@@ -324,6 +324,7 @@ nobase_follyinclude_HEADERS = \
        io/async/test/UndelayedDestruction.h \
        io/async/test/Util.h \
        json.h \
+       lang/Align.h \
        lang/Assume.h \
        lang/Bits.h \
        lang/ColdClass.h \
index b36998a7d4a56bc8210a25e30330be4e2953bbfa..dab80c67609ca38c34b59009a963637034e86174 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <folly/Portability.h>
 #include <folly/detail/Sleeper.h>
+#include <folly/lang/Align.h>
 
 namespace folly {
 
@@ -118,7 +119,7 @@ static_assert(
 #define FOLLY_CACHE_LINE_SIZE 64
 
 template <class T, size_t N>
-struct FOLLY_ALIGNED_MAX SpinLockArray {
+struct alignas(max_align_v) SpinLockArray {
   T& operator[](size_t i) {
     return data_[i].lock;
   }
@@ -140,9 +141,8 @@ struct FOLLY_ALIGNED_MAX SpinLockArray {
 
   // Check if T can theoretically cross a cache line.
   static_assert(
-      folly::max_align_v > 0 &&
-          FOLLY_CACHE_LINE_SIZE % folly::max_align_v == 0 &&
-          sizeof(T) <= folly::max_align_v,
+      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];
index da1fff85407fa09c4d8a25e19530aa6252c40194..1498db30bfca9f4b6512f090491e4360eadad9e2 100644 (file)
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <cstddef>
-#include <type_traits>
 
 #include <folly/portability/Config.h>
 
@@ -30,73 +29,6 @@ constexpr bool kHasUnalignedAccess = true;
 #else
 constexpr bool kHasUnalignedAccess = false;
 #endif
-
-namespace portability_detail {
-
-template <typename I, I A, I B>
-using integral_max = std::integral_constant<I, (A < B) ? B : A>;
-
-template <typename I, I A, I... Bs>
-struct integral_sequence_max
-    : integral_max<I, A, integral_sequence_max<I, Bs...>::value> {};
-
-template <typename I, I A>
-struct integral_sequence_max<I, A> : std::integral_constant<I, A> {};
-
-template <typename... Ts>
-using max_alignment = integral_sequence_max<size_t, alignof(Ts)...>;
-
-using max_basic_alignment = max_alignment<
-    std::max_align_t,
-    long double,
-    double,
-    float,
-    long long int,
-    long int,
-    int,
-    short int,
-    bool,
-    char,
-    char16_t,
-    char32_t,
-    wchar_t,
-    std::nullptr_t>;
-} // namespace portability_detail
-
-constexpr size_t max_align_v = portability_detail::max_basic_alignment::value;
-
-// max_align_t is a type which is aligned at least as strictly as the
-// most-aligned basic type (see the specification of std::max_align_t). This
-// implementation exists because 32-bit iOS platforms have a broken
-// std::max_align_t (see below).
-//
-// You should refer to this as `::folly::max_align_t` in portable code, even if
-// you have `using namespace folly;` because C11 defines a global namespace
-// `max_align_t` type.
-//
-// To be certain, we consider every non-void fundamental type specified by the
-// standard. On most platforms `long double` would be enough, but iOS 32-bit
-// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned
-// `long double`.
-//
-// So far we've covered locals and other non-allocated storage, but we also need
-// confidence that allocated storage from `malloc`, `new`, etc will also be
-// suitable for objects with this alignment reuirement.
-//
-// Apple document that their implementation of malloc will issue 16-byte
-// granularity chunks for small allocations (large allocations are page-size
-// granularity and page-aligned). We think that allocated storage will be
-// suitable for these objects based on the following assumptions:
-//
-// 1. 16-byte granularity also means 16-byte aligned.
-// 2. `new` and other allocators follow the `malloc` rules.
-//
-// We also have some anecdotal evidence: we don't see lots of misaligned-storage
-// crashes on 32-bit iOS apps that use `double`.
-//
-// Apple's allocation reference: http://bit.ly/malloc-small
-struct alignas(max_align_v) max_align_t {};
-
 } // namespace folly
 
 // compiler specific attribute translation
@@ -109,7 +41,6 @@ struct alignas(max_align_v) max_align_t {};
 #else
 # error Cannot define FOLLY_ALIGNED on this platform
 #endif
-#define FOLLY_ALIGNED_MAX FOLLY_ALIGNED(::folly::max_align_v)
 
 // NOTE: this will only do checking in msvc with versions that support /analyze
 #if _MSC_VER
index 7f1253d18bce95749af68d758c985632e8779d18..d400ddb2ab0d77297133914150fd1fa159ea841b 100644 (file)
@@ -256,9 +256,8 @@ void* SimpleAllocator::allocateHard() {
 
   // Install a pointer to ourselves as the allocator.
   *reinterpret_cast<SimpleAllocator**>(mem_) = this;
-  static_assert(
-      folly::max_align_v >= sizeof(SimpleAllocator*), "alignment too small");
-  mem_ += std::min(sz_, folly::max_align_v);
+  static_assert(max_align_v >= sizeof(SimpleAllocator*), "alignment too small");
+  mem_ += std::min(sz_, max_align_v);
 
   // New allocation.
   auto mem = mem_;
index caae2395ab5e9c79065db06c9e3b7193aff3500a..7751b7dc91b624a3d3137694990ebea271f88ee0 100644 (file)
@@ -33,6 +33,7 @@
 #include <folly/Memory.h>
 #include <folly/Portability.h>
 #include <folly/hash/Hash.h>
+#include <folly/lang/Align.h>
 #include <folly/portability/BitsFunctexcept.h>
 #include <folly/portability/Memory.h>
 #include <folly/system/ThreadId.h>
@@ -390,7 +391,7 @@ class SimpleAllocator {
     if (intptr_t(mem_) % 128 == 0) {
       // Avoid allocating pointers that may look like malloc
       // pointers.
-      mem_ += std::min(sz_, folly::max_align_v);
+      mem_ += std::min(sz_, max_align_v);
     }
     if (mem_ && (mem_ + sz_ <= end_)) {
       auto mem = mem_;
index 4c8da83d66d832de07c39a54c60354f19cc84fd2..7d702e68cf4033c5d807242d43162b1b83985da4 100644 (file)
@@ -39,9 +39,8 @@ void set_default_resource(memory_resource* mr) {
 memory_resource* new_delete_resource() {
   class new_delete : public memory_resource {
    public:
-    void* allocate(
-        const size_t bytes,
-        const size_t alignment = folly::max_align_v) override {
+    void* allocate(const size_t bytes, const size_t alignment = max_align_v)
+        override {
       (void)alignment;
       void* p = static_cast<void*>(new char[bytes]);
       DEBUG_PRINT(this << " " << p << " " << bytes);
@@ -50,7 +49,7 @@ memory_resource* new_delete_resource() {
     void deallocate(
         void* p,
         const size_t bytes,
-        const size_t alignment = folly::max_align_v) override {
+        const size_t alignment = max_align_v) override {
       (void)alignment;
       (void)bytes;
       DEBUG_PRINT(p << " " << bytes);
index c9759ae84fc307b76450d7934530b5b2d996db8f..f75e2ac952033b06d2947bd59c8ef3f6abeb6ba7 100644 (file)
 /// hazptr prototype.
 ////////////////////////////////////////////////////////////////////////////////
 
-#include <folly/Portability.h>
 #include <memory>
 
+#include <folly/Portability.h>
+#include <folly/lang/Align.h>
+
 namespace folly {
 namespace hazptr {
 
@@ -34,11 +36,11 @@ class memory_resource {
   virtual ~memory_resource() = default;
   virtual void* allocate(
       const size_t bytes,
-      const size_t alignment = folly::max_align_v) = 0;
+      const size_t alignment = max_align_v) = 0;
   virtual void deallocate(
       void* p,
       const size_t bytes,
-      const size_t alignment = folly::max_align_v) = 0;
+      const size_t alignment = max_align_v) = 0;
 };
 
 memory_resource* get_default_resource();
index 7206fc4652e13202d4c796d05d84b138c97ddbc6..87df7f8b58fff8dde07f2e7cfd6fce9d74d79cc8 100644 (file)
@@ -31,6 +31,7 @@
 #include <folly/ScopeGuard.h>
 #include <folly/hash/SpookyHashV2.h>
 #include <folly/io/Cursor.h>
+#include <folly/lang/Align.h>
 #include <folly/memory/Malloc.h>
 
 using std::unique_ptr;
diff --git a/folly/lang/Align.h b/folly/lang/Align.h
new file mode 100644 (file)
index 0000000..8b878d4
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstddef>
+
+namespace folly {
+
+namespace detail {
+
+union max_align_ {
+  std::max_align_t mat;
+  long double ld;
+  double d;
+  float f;
+  long long int lli;
+  long int li;
+  int i;
+  short int si;
+  bool b;
+  char c;
+  char16_t c16;
+  char32_t c32;
+  wchar_t wc;
+  std::nullptr_t n;
+};
+
+} // namespace detail
+
+// max_align_v is the alignment of max_align_t.
+//
+// max_align_t is a type which is aligned at least as strictly as the
+// most-aligned basic type (see the specification of std::max_align_t). This
+// implementation exists because 32-bit iOS platforms have a broken
+// std::max_align_t (see below).
+//
+// You should refer to this as `::folly::max_align_t` in portable code, even if
+// you have `using namespace folly;` because C11 defines a global namespace
+// `max_align_t` type.
+//
+// To be certain, we consider every non-void fundamental type specified by the
+// standard. On most platforms `long double` would be enough, but iOS 32-bit
+// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned
+// `long double`.
+//
+// So far we've covered locals and other non-allocated storage, but we also need
+// confidence that allocated storage from `malloc`, `new`, etc will also be
+// suitable for objects with this alignment requirement.
+//
+// Apple document that their implementation of malloc will issue 16-byte
+// granularity chunks for small allocations (large allocations are page-size
+// granularity and page-aligned). We think that allocated storage will be
+// suitable for these objects based on the following assumptions:
+//
+// 1. 16-byte granularity also means 16-byte aligned.
+// 2. `new` and other allocators follow the `malloc` rules.
+//
+// We also have some anecdotal evidence: we don't see lots of misaligned-storage
+// crashes on 32-bit iOS apps that use `double`.
+//
+// Apple's allocation reference: http://bit.ly/malloc-small
+constexpr std::size_t max_align_v = alignof(detail::max_align_);
+struct alignas(max_align_v) max_align_t {};
+
+} // namespace folly
index ffe9f38bcec75a86e8370d7d0ea2d4a798a3319a..81a3396776388aae55fbd3ee3909c338c079e6e9 100644 (file)
@@ -27,6 +27,7 @@
 #include <folly/Conv.h>
 #include <folly/Likely.h>
 #include <folly/Memory.h>
+#include <folly/lang/Align.h>
 #include <folly/memory/Malloc.h>
 
 namespace folly {
@@ -133,7 +134,7 @@ class Arena {
   typedef boost::intrusive::slist_member_hook<
     boost::intrusive::tag<Arena>> BlockLink;
 
-  struct FOLLY_ALIGNED_MAX Block {
+  struct alignas(max_align_v) Block {
     BlockLink link;
 
     // Allocate a block with at least size bytes of storage.
index 4401ae0a145309a8011132d8f60e9f337ad5158c..f34f81ea8df981cc3dceb68c4a4585007f84cafe 100644 (file)
@@ -29,6 +29,7 @@
 #include <folly/Benchmark.h>
 #include <folly/Memory.h>
 #include <folly/Range.h>
+#include <folly/lang/Align.h>
 #include <folly/portability/GTest.h>
 
 using namespace folly;
@@ -92,7 +93,7 @@ void ArenaTester::merge(ArenaTester&& other) {
 } // namespace
 
 TEST(ThreadCachedArena, BlockSize) {
-  static const size_t alignment = folly::max_align_v;
+  static const size_t alignment = max_align_v;
   static const size_t requestedBlockSize = 64;
 
   ThreadCachedArena arena(requestedBlockSize);
index 9c1253019bcb1123c45b0bf317d9f3cfa173e057..148493e31c66163043a5977df0d78d3d841e52ae 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <type_traits>
 
+#include <folly/lang/Align.h>
 #include <folly/portability/GTest.h>
 
 using folly::CachelinePadded;