proxygen
CachelinePaddedTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/CachelinePadded.h>
18 
19 #include <type_traits>
20 
21 #include <folly/lang/Align.h>
23 
25 
26 static_assert(
27  std::is_standard_layout<CachelinePadded<int>>::value,
28  "CachelinePadded<T> must be standard-layout if T is.");
29 
30 static constexpr int kCachelineSize =
32 
33 template <size_t dataSize, size_t alignment = alignof(void*)>
34 struct alignas(alignment) SizedData {
36  size_t i = 0;
37  for (auto& datum : data) {
38  datum = i++;
39  }
40  }
41 
42  void doModifications() {
43  size_t i = 0;
44  for (auto& datum : data) {
45  EXPECT_EQ(static_cast<unsigned char>(i), datum);
46  ++i;
47  ++datum;
48  }
49  }
50 
52  size_t i = 1;
53  for (auto& datum : data) {
54  EXPECT_EQ(static_cast<unsigned char>(i), datum);
55  ++i;
56  }
57  }
58 
59  unsigned char data[dataSize];
60 };
61 
62 template <typename T, size_t N = 1>
64 
65 template <typename T>
67 
68 using CachelinePaddedTypes = ::testing::Types<
73  // Mimic single basic types:
84  // Mimic small arrays of basic types:
95  // Mimic large arrays of basic types:
107 
109  EXPECT_EQ(alignof(TypeParam), alignof(CachelinePadded<TypeParam>));
110 }
111 
114  item.get()->doModifications();
115 }
116 
118  EXPECT_GT(
119  sizeof(TypeParam) + 2 * kCachelineSize,
121  size_t const rawSize = sizeof(TypeParam);
122  size_t const rawAlign = alignof(TypeParam);
123  size_t const expectedPadding = kCachelineSize - (rawAlign % kCachelineSize);
124  size_t const expectedPaddedSize = rawSize + 2 * expectedPadding;
125  EXPECT_EQ(expectedPaddedSize, sizeof(CachelinePadded<TypeParam>));
126 }
127 
128 TEST(CachelinePadded, PtrOperator) {
129  CachelinePadded<int> padded;
130  EXPECT_TRUE(padded.get() == padded.operator->());
131  EXPECT_TRUE(&*padded == padded.get());
132  const auto constPadded = CachelinePadded<int>{};
133  EXPECT_TRUE(constPadded.get() == constPadded.operator->());
134  EXPECT_TRUE(constPadded.get() == &*constPadded.get());
135 }
136 
137 TEST(CachelinePadded, PropagatesConstness) {
138  struct OverloadedOnConst {
139  void assign(int* dst) {
140  *dst = 31415;
141  }
142  void assign(int* dst) const {
143  *dst = 271828;
144  }
145  };
146 
148 
149  int i = 0;
150  padded->assign(&i);
151  EXPECT_EQ(31415, i);
152 
153  const auto constPadded = CachelinePadded<OverloadedOnConst>{};
154  constPadded->assign(&i);
155  EXPECT_EQ(271828, i);
156 }
157 
158 TEST(CachelinePadded, ConstructsAndDestructs) {
159  enum LifetimeStatus {
160  kNone,
161  kConstructed,
162  kDestroyed,
163  };
164  struct WriteOnLifetimeOp {
165  explicit WriteOnLifetimeOp(LifetimeStatus* dst) : dst_(dst) {
166  *dst = kConstructed;
167  }
168  ~WriteOnLifetimeOp() {
169  *dst_ = kDestroyed;
170  }
171  LifetimeStatus* dst_;
172  };
173  LifetimeStatus status = kNone;
176  EXPECT_EQ(kConstructed, status);
177  delete ptr;
178  EXPECT_EQ(kDestroyed, status);
179 }
180 
181 TEST(CachelinePadded, ConstructsAndDestructsArrays) {
182  static thread_local int numConstructions;
183  static thread_local int numDestructions;
184  numConstructions = 0;
185  numDestructions = 0;
186  struct LifetimeCountingClass {
187  LifetimeCountingClass() {
188  ++numConstructions;
189  }
190  ~LifetimeCountingClass() {
191  ++numDestructions;
192  }
193  };
194  const static int kNumItems = 123;
197  EXPECT_EQ(kNumItems, numConstructions);
198  delete[] ptr;
199  EXPECT_EQ(kNumItems, numDestructions);
200 }
201 
202 TEST(CachelinePadded, ForwardsCorrectly) {
203  struct RvalueOverloadedConstructor {
204  RvalueOverloadedConstructor(int* dst, int& /* ignored */) {
205  *dst = 0;
206  }
207  RvalueOverloadedConstructor(int* dst, int&& /* ignored */) {
208  *dst = 1;
209  }
210  };
211  int shouldBeZero = 12345;
212  int shouldBeOne = 67890;
213  {
214  int ignored = 42;
216  &shouldBeZero, ignored);
218  &shouldBeOne, static_cast<int&&>(ignored));
219  }
220  EXPECT_EQ(0, shouldBeZero);
221  EXPECT_EQ(1, shouldBeOne);
222 }
void * ptr
TEST(CachelinePadded, PtrOperator)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TYPED_TEST_CASE(CachelinePaddedTests, CachelinePaddedTypes)
constexpr std::size_t hardware_destructive_interference_size
Definition: Align.h:107
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
static const char *const value
Definition: Conv.cpp:50
::testing::Types< SizedData< kCachelineSize >, SizedData< 2 *kCachelineSize >, SizedData< kCachelineSize/2 >, SizedData< kCachelineSize+kCachelineSize/2 >, SizedDataMimic< folly::max_align_t >, SizedDataMimic< void * >, SizedDataMimic< long double >, SizedDataMimic< double >, SizedDataMimic< float >, SizedDataMimic< long long >, SizedDataMimic< long >, SizedDataMimic< int >, SizedDataMimic< short >, SizedDataMimic< char >, SizedDataMimic< folly::max_align_t, 3 >, SizedDataMimic< void *, 3 >, SizedDataMimic< long double, 3 >, SizedDataMimic< double, 3 >, SizedDataMimic< float, 3 >, SizedDataMimic< long long, 3 >, SizedDataMimic< long, 3 >, SizedDataMimic< int, 3 >, SizedDataMimic< short, 3 >, SizedDataMimic< char, 3 >, SizedDataMimic< folly::max_align_t, kCachelineSize+3 >, SizedDataMimic< void *, kCachelineSize+3 >, SizedDataMimic< long double, kCachelineSize+3 >, SizedDataMimic< double, kCachelineSize+3 >, SizedDataMimic< float, kCachelineSize+3 >, SizedDataMimic< long long, kCachelineSize+3 >, SizedDataMimic< long, kCachelineSize+3 >, SizedDataMimic< int, kCachelineSize+3 >, SizedDataMimic< short, kCachelineSize+3 >, SizedDataMimic< char, kCachelineSize+3 >> CachelinePaddedTypes
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
static constexpr int kCachelineSize
TYPED_TEST(CachelinePaddedTests, alignment)
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
#define EXPECT_GT(val1, val2)
Definition: gtest.h:1934