proxygen
F14InterprocessTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 <ios>
18 #include <iostream>
19 #include <memory>
20 #include <scoped_allocator>
21 #include <string>
22 #include <vector>
23 
24 #include <boost/interprocess/allocators/adaptive_pool.hpp>
25 #include <boost/interprocess/managed_shared_memory.hpp>
26 
27 #include <folly/Format.h>
28 #include <folly/Random.h>
29 #include <folly/Traits.h>
30 #include <folly/container/F14Map.h>
31 #include <folly/container/F14Set.h>
34 
35 using namespace boost::interprocess;
36 
37 template <typename T>
38 using ShmAllocator = adaptive_pool<T, managed_shared_memory::segment_manager>;
39 
40 template <typename K, typename M>
42  K,
43  M,
47 
48 template <typename K, typename M>
50  K,
51  M,
52  folly::f14::DefaultHasher<K>,
53  folly::f14::DefaultKeyEqual<K>,
55 
56 template <typename K, typename M>
58  K,
59  M,
60  folly::f14::DefaultHasher<K>,
61  folly::f14::DefaultKeyEqual<K>,
63 
64 template <typename K>
66  K,
67  folly::f14::DefaultHasher<K>,
68  folly::f14::DefaultKeyEqual<K>,
70 
71 template <typename K>
73  K,
74  folly::f14::DefaultHasher<K>,
75  folly::f14::DefaultKeyEqual<K>,
77 
78 template <typename K>
80  K,
81  folly::f14::DefaultHasher<K>,
82  folly::f14::DefaultKeyEqual<K>,
84 
85 using ShmVI = std::vector<int, ShmAllocator<int>>;
86 using ShmVVI =
87  std::vector<ShmVI, std::scoped_allocator_adaptor<ShmAllocator<ShmVI>>>;
88 
90  int,
91  ShmVVI,
94  std::scoped_allocator_adaptor<ShmAllocator<std::pair<int const, ShmVVI>>>>;
95 
97  int,
98  ShmVVI,
99  folly::f14::DefaultHasher<int>,
100  folly::f14::DefaultKeyEqual<int>,
101  std::scoped_allocator_adaptor<ShmAllocator<std::pair<int const, ShmVVI>>>>;
102 
104  int,
105  ShmVVI,
106  folly::f14::DefaultHasher<int>,
107  folly::f14::DefaultKeyEqual<int>,
108  std::scoped_allocator_adaptor<ShmAllocator<std::pair<int const, ShmVVI>>>>;
109 
110 namespace {
111 std::string makeRandomName() {
112  return folly::sformat("f14test_{}", folly::Random::rand64());
113 }
114 
115 std::shared_ptr<managed_shared_memory> makeShmSegment(
116  std::size_t n,
117  std::string name = makeRandomName()) {
118  auto deleter = [=](managed_shared_memory* p) {
119  delete p;
120  shared_memory_object::remove(name.c_str());
121  };
122 
123  auto segment = new managed_shared_memory(create_only, name.c_str(), n);
124  return std::shared_ptr<managed_shared_memory>(segment, deleter);
125 }
126 } // namespace
127 
128 template <typename M>
130  auto segment = makeShmSegment(8192);
131  auto mgr = segment->get_segment_manager();
133  M m{alloc};
134  for (int i = 0; i < 20; ++i) {
135  m[i] = i * 10;
136  }
137  EXPECT_EQ(m.size(), 20);
138  for (int i = 0; i < 20; ++i) {
139  EXPECT_EQ(m[i], i * 10);
140  }
141 }
142 
143 template <typename S>
145  auto segment = makeShmSegment(8192);
146  auto mgr = segment->get_segment_manager();
147  S s{typename S::allocator_type{mgr}};
148  for (int i = 0; i < 20; ++i) {
149  s.insert(i);
150  }
151  EXPECT_EQ(s.size(), 20);
152  for (int i = 0; i < 40; ++i) {
153  EXPECT_EQ(s.count(i), (i < 20 ? 1 : 0));
154  }
155 }
156 
158  runSimpleMapTest<ShmF14ValueMap<int, int>>();
159 }
161  runSimpleMapTest<ShmF14NodeMap<int, int>>();
162 }
164  runSimpleMapTest<ShmF14VectorMap<int, int>>();
165 }
167  runSimpleSetTest<ShmF14ValueSet<int>>();
168 }
170  runSimpleSetTest<ShmF14NodeSet<int>>();
171 }
173  runSimpleSetTest<ShmF14VectorSet<int>>();
174 }
175 
176 template <typename M>
178  using namespace folly::f14::detail;
179 
180  // fallback std::unordered_map on libstdc++ doesn't pass this test
181  if (getF14IntrinsicsMode() != F14IntrinsicsMode::None) {
182  auto name = makeRandomName();
183  auto segment1 = makeShmSegment(8192, name);
184  auto segment2 =
185  std::make_shared<managed_shared_memory>(open_only, name.c_str());
186 
187  auto m1 = segment1->construct<M>("m")(
188  typename M::allocator_type{segment1->get_segment_manager()});
189  auto m2 = segment2->find<M>("m").first;
190 
191  std::cout << "m in segment1 @ " << (uintptr_t)m1 << "\n";
192  std::cout << "m in segment2 @ " << (uintptr_t)m2 << "\n";
193 
194  EXPECT_NE(&*m1, &*m2);
195 
196  (*m1)[1] = 10;
197  EXPECT_EQ(m2->count(0), 0);
198  EXPECT_EQ((*m2)[1], 10);
199  (*m2)[2] = 20;
200  EXPECT_EQ(m1->size(), 2);
201  EXPECT_EQ(m1->find(2)->second, 20);
202  (*m1)[3] = 30;
203  EXPECT_EQ(m2->size(), 3);
204  EXPECT_FALSE(m2->emplace(std::make_pair(3, 33)).second);
205  }
206 }
207 
208 TEST(ShmF14ValueMap, simultaneous) {
209  runSimultaneousAccessMapTest<ShmF14ValueMap<int, int>>();
210 }
211 TEST(ShmF14NodeMap, simultaneous) {
212  runSimultaneousAccessMapTest<ShmF14NodeMap<int, int>>();
213 }
214 TEST(ShmF14VectorMap, simultaneous) {
215  runSimultaneousAccessMapTest<ShmF14VectorMap<int, int>>();
216 }
217 
218 template <typename T>
221  std::shared_ptr<managed_shared_memory> const& segment,
222  T const& val) {
223  auto beginAddr = reinterpret_cast<uintptr_t>(segment->get_address());
224  auto endAddr = beginAddr + segment->get_size();
225  auto addr = reinterpret_cast<uintptr_t>(&val);
226  EXPECT_TRUE(beginAddr <= addr && addr + sizeof(T) <= endAddr)
227  << name << ": begin @" << std::hex << beginAddr << ", val @" << std::hex
228  << addr << ", size" << std::hex << sizeof(T) << ", end @" << std::hex
229  << endAddr;
230 }
231 
232 void checkLocation(
234  std::shared_ptr<managed_shared_memory> const& segment,
235  int const& val);
236 
237 template <typename A, typename B>
238 void checkLocation(
240  std::shared_ptr<managed_shared_memory> const& segment,
241  std::pair<A, B> const& val);
242 
243 template <typename T>
244 auto checkLocation(
246  std::shared_ptr<managed_shared_memory> const& segment,
247  T const& val) -> folly::void_t<decltype(val.begin())>;
248 
251  std::shared_ptr<managed_shared_memory> const& segment,
252  int const& val) {
253  checkSingleLocation(name, segment, val);
254 }
255 
256 template <typename A, typename B>
259  std::shared_ptr<managed_shared_memory> const& segment,
260  std::pair<A, B> const& val) {
261  checkSingleLocation(name, segment, val);
262  checkLocation(name + ".first", segment, val.first);
263  checkLocation(name + ".second", segment, val.second);
264 }
265 
266 template <typename T>
269  std::shared_ptr<managed_shared_memory> const& segment,
270  T const& val) -> folly::void_t<decltype(val.begin())> {
271  typename T::allocator_type alloc{segment->get_segment_manager()};
272  EXPECT_TRUE(alloc == val.get_allocator());
273  checkSingleLocation(name, segment, val);
274  for (auto&& v : val) {
275  checkLocation(name + "[]", segment, v);
276  }
277 }
278 
279 template <typename M>
281  auto segment = makeShmSegment(8192);
282  auto mgr = segment->get_segment_manager();
283 
284  auto vi = segment->construct<ShmVI>(anonymous_instance)(
285  typename ShmVI::allocator_type{mgr});
286  vi->push_back(10);
287  checkLocation("vi", segment, *vi);
288 
289  auto vvi = segment->construct<ShmVVI>(anonymous_instance)(
290  typename ShmVVI::allocator_type{mgr});
291  vvi->resize(1);
292  vvi->at(0).push_back(2);
293  checkLocation("vvi", segment, *vvi);
294 
295  auto m = segment->construct<M>(anonymous_instance)(
296  typename M::allocator_type{mgr});
297  (*m)[1].emplace_back();
298  (*m)[1][0].push_back(3);
299 
300  checkLocation("m", segment, *m);
301  m->clear();
302 }
303 
304 TEST(ShmF14ValueI2VVI, scopedAllocator) {
305  runScopedAllocatorTest<ShmF14ValueI2VVI>();
306 }
307 TEST(ShmF14NodeI2VVI, scopedAllocator) {
308  runScopedAllocatorTest<ShmF14NodeI2VVI>();
309 }
310 TEST(ShmF14VectorI2VVI, scopedAllocator) {
311  runScopedAllocatorTest<ShmF14VectorI2VVI>();
312 }
313 
314 template <typename M>
316  auto segment1 = makeShmSegment(8192);
317  auto mgr1 = segment1->get_segment_manager();
318 
319  auto segment2 = makeShmSegment(8192);
320  auto mgr2 = segment2->get_segment_manager();
321 
322  auto a1 = segment1->construct<M>(anonymous_instance)(
323  typename M::allocator_type{mgr1});
324  (*a1)[1].emplace_back();
325  (*a1)[1][0].push_back(3);
326  auto b1 = segment1->construct<M>(anonymous_instance)(*a1);
327  auto c1 = segment1->construct<M>(anonymous_instance)(std::move(*a1));
328 
329  auto d2 = segment2->construct<M>(anonymous_instance)(
330  typename M::allocator_type{mgr2});
331  (*d2)[10].emplace_back();
332  (*d2)[10][0].push_back(6);
333  auto e2 = segment2->construct<M>(anonymous_instance)(*d2);
334  auto f2 = segment2->construct<M>(anonymous_instance)(
335  *b1, typename M::allocator_type{mgr2});
336 
337  checkLocation("a1", segment1, *a1);
338  checkLocation("b1", segment1, *b1);
339  checkLocation("c1", segment1, *c1);
340  checkLocation("d2", segment2, *d2);
341  checkLocation("e2", segment2, *e2);
342  checkLocation("f2", segment2, *f2);
343 
344  EXPECT_EQ(a1->size(), 0);
345  EXPECT_FALSE(*a1 == *b1);
346  EXPECT_TRUE(*b1 == *c1);
347  EXPECT_TRUE(*b1 == *f2);
348  EXPECT_EQ(d2->size(), 1);
349  EXPECT_EQ(e2->size(), 1);
350  EXPECT_FALSE(*e2 == *f2);
351 
352  checkLocation("d2", segment2, *d2);
353 
354  EXPECT_TRUE(*d2 == *e2);
355 
356  f2->clear();
357  *f2 = std::move(*d2);
358 
359  checkLocation("d2", segment2, *d2);
360  checkLocation("f2", segment2, *f2);
361 
362  EXPECT_TRUE(*f2 == *e2);
363  EXPECT_TRUE(d2->empty());
364 
365  {
366  using std::swap;
367  swap(*a1, *b1);
368  }
369  checkLocation("a1", segment1, *a1);
370  checkLocation("b1", segment1, *b1);
371  EXPECT_TRUE(*a1 == *c1);
372 
373  *a1 = std::move(*e2);
374 
375  EXPECT_TRUE(*f2 == *a1);
376 
377  checkLocation("a1", segment1, *a1);
378  checkLocation("e2", segment2, *e2);
379 
380  auto g2 = segment2->construct<M>(anonymous_instance)(
381  std::move(*a1), typename M::allocator_type{mgr2});
382 
383  EXPECT_TRUE(*f2 == *g2);
384 
385  checkLocation("f2", segment2, *f2);
386  checkLocation("g2", segment2, *g2);
387 
388  segment1->destroy_ptr(a1);
389  segment1->destroy_ptr(b1);
390  segment1->destroy_ptr(c1);
391  segment2->destroy_ptr(d2);
392  segment2->destroy_ptr(e2);
393  segment2->destroy_ptr(f2);
394  segment2->destroy_ptr(g2);
395 }
396 
397 TEST(ShmF14ValueI2VVI, multiScope) {
398  runMultiScopeTest<ShmF14ValueI2VVI>();
399 }
400 TEST(ShmF14NodeI2VVI, multiScope) {
401  runMultiScopeTest<ShmF14NodeI2VVI>();
402 }
403 TEST(ShmF14VectorI2VVI, multiScope) {
404  runMultiScopeTest<ShmF14VectorI2VVI>();
405 }
#define T(v)
Definition: http_parser.c:233
void runSimultaneousAccessMapTest()
void runScopedAllocatorTest()
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
void runMultiScopeTest()
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void runSimpleSetTest()
double val
Definition: String.cpp:273
static bool simple
void checkSingleLocation(std::string name, std::shared_ptr< managed_shared_memory > const &segment, T const &val)
std::vector< ShmVI, std::scoped_allocator_adaptor< ShmAllocator< ShmVI >>> ShmVVI
const char * name
Definition: http_parser.c:437
static constexpr F14IntrinsicsMode getF14IntrinsicsMode()
static map< string, int > m
type_t< void, Ts... > void_t
Definition: Traits.h:302
adaptive_pool< T, managed_shared_memory::segment_manager > ShmAllocator
void checkLocation(std::string name, std::shared_ptr< managed_shared_memory > const &segment, int const &val)
**Optimized Holders **The template hazptr_array< M > provides most of the functionality *of M hazptr_holder s but with faster construction destruction *for M
Definition: Hazptr.h:104
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
std::vector< int, ShmAllocator< int >> ShmVI
void runSimpleMapTest()
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static uint64_t rand64()
Definition: Random.h:263
ThreadPoolListHook * addr
TEST(ShmF14ValueMap, simple)
constexpr detail::First first
Definition: Base-inl.h:2553