proxygen
SingletonThreadLocalTest.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 <thread>
18 #include <unordered_set>
19 #include <vector>
20 
22 #include <folly/Synchronized.h>
24 
25 using namespace folly;
26 
27 namespace {
28 static std::atomic<std::size_t> fooCreatedCount{0};
29 static std::atomic<std::size_t> fooDeletedCount{0};
30 struct Foo {
31  Foo() {
32  ++fooCreatedCount;
33  }
34  ~Foo() {
35  ++fooDeletedCount;
36  }
37 };
38 using FooSingletonTL = SingletonThreadLocal<Foo>;
39 } // namespace
40 
41 TEST(SingletonThreadLocalTest, OneSingletonPerThread) {
42  static constexpr std::size_t targetThreadCount{64};
43  std::atomic<std::size_t> completedThreadCount{0};
45  std::vector<std::thread> threads{};
46  auto threadFunction = [&fooAddresses, &completedThreadCount] {
47  fooAddresses.wlock()->emplace(&FooSingletonTL::get());
48  ++completedThreadCount;
49  while (completedThreadCount < targetThreadCount) {
51  }
52  };
53  {
54  for (std::size_t threadCount{0}; threadCount < targetThreadCount;
55  ++threadCount) {
56  threads.emplace_back(threadFunction);
57  }
58  }
59  for (auto& thread : threads) {
60  thread.join();
61  }
62  EXPECT_EQ(threads.size(), fooAddresses.rlock()->size());
63  EXPECT_EQ(threads.size(), fooCreatedCount);
64  EXPECT_EQ(threads.size(), fooDeletedCount);
65 }
66 
67 TEST(SingletonThreadLocalTest, MoveConstructibleMake) {
68  struct Foo {
69  int a, b;
70  Foo(int a_, int b_) : a(a_), b(b_) {}
71  Foo(Foo&&) = default;
72  Foo& operator=(Foo&&) = default;
73  };
74  struct Tag {};
75  struct Make {
76  Foo operator()() const {
77  return Foo(3, 4);
78  }
79  };
81  EXPECT_EQ(4, single.b);
82 }
83 
84 TEST(SingletonThreadLocalTest, NotMoveConstructibleMake) {
85  struct Foo {
86  int a, b;
87  Foo(int a_, int b_) : a(a_), b(b_) {}
88  Foo(Foo&&) = delete;
89  Foo& operator=(Foo&&) = delete;
90  };
91  struct Tag {};
92  struct Make {
93  Foo* operator()(unsigned char (&buf)[sizeof(Foo)]) const {
94  return new (buf) Foo(3, 4);
95  }
96  };
98  EXPECT_EQ(4, single.b);
99 }
100 
101 TEST(SingletonThreadLocalTest, AccessAfterFastPathDestruction) {
102  static std::atomic<int> counter{};
103  struct Foo {
104  int i = 3;
105  };
106  struct Bar {
107  ~Bar() {
109  }
110  };
111  auto th = std::thread([] {
114  });
115  th.join();
116  EXPECT_EQ(6, counter);
117 }
118 
119 TEST(ThreadLocal, DependencyTest) {
121 
122  struct mytag {};
123 
124  typedef SingletonThreadLocal<int> SingletonInt;
125  struct barstruct {
126  ~barstruct() {
127  SingletonInt::get()++;
128  Data data;
129  data.reset(new int(0));
130  }
131  };
132  typedef SingletonThreadLocal<barstruct, mytag> BarSingleton;
133 
134  std::thread([&]() {
135  Data data;
136  data.reset(new int(0));
139  })
140  .join();
141 }
142 
143 TEST(SingletonThreadLocalTest, Reused) {
144  for (auto i = 0u; i < 2u; ++i) {
146  if (i == 0u) {
147  data = "hello";
148  }
149  EXPECT_EQ(i == 0u ? "hello" : "", data);
150  }
151 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define FOLLY_DECLARE_REUSED(name,...)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::vector< std::thread::id > threads
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
char a
countdownsingle single
FOLLY_EXPORT static FOLLY_ALWAYS_INLINE T & get()
std::atomic< int > counter
const char * string
Definition: Conv.cpp:212
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
Definition: String-inl.h:498
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
Definition: submit.h:391
TEST(SequencedExecutor, CPUThreadPoolExecutor)