proxygen
AtomicSharedPtrTest.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 // AtomicSharedPtr-detail.h only works with libstdc++, so skip these tests for
18 // other vendors
19 #ifdef FOLLY_USE_LIBSTDCPP
20 
21 #include <atomic>
22 #include <memory>
23 #include <thread>
24 
28 
30 
31 using namespace folly;
32 using namespace folly::test;
33 using namespace std;
34 static int c_count{0};
35 static int d_count{0};
36 
38 
39 DEFINE_int64(seed, 0, "Seed for random number generators");
40 DEFINE_int32(num_threads, 32, "Number of threads");
41 
42 struct foo {
43  foo() {
44  c_count++;
45  }
46  ~foo() {
47  d_count++;
48  }
49 };
50 
51 TEST(AtomicSharedPtr, operators) {
53  EXPECT_TRUE(fooptr.is_lock_free());
54  auto i = new int(5);
55  std::shared_ptr<int> s(i);
56  fooptr.store(s);
57  shared_ptr<int> bar(fooptr);
58  EXPECT_TRUE(fooptr.compare_exchange_strong(s, nullptr));
59  s.reset();
60  bar.reset();
61 }
62 
63 TEST(AtomicSharedPtr, exchange) {
65  auto a = make_shared<int>(1);
66  fooptr.store(std::move(a));
67  auto b = fooptr.exchange(make_shared<int>());
68  EXPECT_EQ(*b, 1);
69 }
70 
71 TEST(AtomicSharedPtr, foo) {
72  c_count = 0;
73  d_count = 0;
74  {
76  fooptr.store(make_shared<foo>());
77  EXPECT_EQ(1, c_count);
78  EXPECT_EQ(0, d_count);
79  {
80  auto res = fooptr.load();
81  EXPECT_EQ(1, c_count);
82  EXPECT_EQ(0, d_count);
83  }
84  EXPECT_EQ(1, c_count);
85  EXPECT_EQ(0, d_count);
86  }
87  EXPECT_EQ(1, c_count);
88  EXPECT_EQ(1, d_count);
89 }
90 
91 TEST(AtomicSharedPtr, counted) {
92  c_count = 0;
93  d_count = 0;
94  {
96  fooptr;
97  fooptr.store(make_counted<std::atomic, foo>());
98  EXPECT_EQ(1, c_count);
99  EXPECT_EQ(0, d_count);
100  {
101  auto res = fooptr.load();
102  EXPECT_EQ(1, c_count);
103  EXPECT_EQ(0, d_count);
104  }
105  EXPECT_EQ(1, c_count);
106  EXPECT_EQ(0, d_count);
107  }
108  EXPECT_EQ(1, c_count);
109  EXPECT_EQ(1, d_count);
110 }
111 
112 TEST(AtomicSharedPtr, counted2) {
113  auto foo = make_counted<std::atomic, bool>();
115  fooptr(foo);
116  fooptr.store(foo);
117  fooptr.load();
118 }
119 
120 TEST(AtomicSharedPtr, ConstTest) {
121  const auto a(std::make_shared<foo>());
123  atom.store(a);
124 
126 }
127 TEST(AtomicSharedPtr, AliasingConstructorTest) {
128  c_count = 0;
129  d_count = 0;
130  auto a = std::make_shared<foo>();
131  auto b = new foo;
132  auto alias = std::shared_ptr<foo>(a, b);
133 
135  asp.store(alias);
136  a.reset();
137  alias.reset();
138  auto res1 = asp.load();
139  auto res2 = asp.exchange(nullptr);
140  EXPECT_EQ(b, res1.get());
141  EXPECT_EQ(b, res2.get());
142  EXPECT_EQ(2, c_count);
143  EXPECT_EQ(0, d_count);
144  res1.reset();
145  res2.reset();
146  EXPECT_EQ(2, c_count);
147  EXPECT_EQ(1, d_count);
148  delete b;
149  EXPECT_EQ(2, c_count);
150  EXPECT_EQ(2, d_count);
151 }
152 
153 TEST(AtomicSharedPtr, MaxPtrs) {
154  shared_ptr<long> p(new long);
155  int max_atomic_shared_ptrs = 262144;
156  atomic_shared_ptr<long> ptrs[max_atomic_shared_ptrs];
157  for (int i = 0; i < max_atomic_shared_ptrs - 1; i++) {
158  ptrs[i].store(p);
159  }
161  EXPECT_DEATH(fail.store(p), "");
162 }
163 
164 TEST(AtomicSharedPtr, DeterministicTest) {
165  DSched sched(DSched::uniform(FLAGS_seed));
166 
167  auto foo = make_counted<DeterministicAtomic, bool>();
169  bool,
172  fooptr(foo);
173  std::vector<std::thread> threads(FLAGS_num_threads);
174  for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
175  threads[tid] = DSched::thread([&]() {
176  for (int i = 0; i < 1000; i++) {
177  auto l = fooptr.load();
178  EXPECT_TRUE(l.get() != nullptr);
179  fooptr.compare_exchange_strong(l, l);
180  fooptr.store(make_counted<DeterministicAtomic, bool>());
182  l, make_counted<DeterministicAtomic, bool>()));
183  }
184  });
185  }
186  for (auto& t : threads) {
187  DSched::join(t);
188  }
189 }
190 #endif // #ifdef FOLLY_USE_LIBSTDCPP
char b
SharedPtr load(std::memory_order order=std::memory_order_seq_cst) const noexcept
static const int seed
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
DeterministicAtomicImpl< T, DeterministicSchedule > DeterministicAtomic
STL namespace.
SharedPtr exchange(SharedPtr n, std::memory_order order=std::memory_order_seq_cst)
static std::thread thread(Func &&func, Args &&...args)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
DEFINE_int64(threadtimeout_ms, 60000,"Idle time before ThreadPoolExecutor threads are joined")
std::vector< std::thread::id > threads
static std::function< size_t(size_t)> uniform(uint64_t seed)
auto const foo
Definition: LazyTest.cpp:49
void fail()
bool compare_exchange_strong(SharedPtr &expected, const SharedPtr &n, std::memory_order mo=std::memory_order_seq_cst) noexcept
char a
folly::Singleton< int > bar
TEST(ProgramOptionsTest, Errors)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
T exchange(T &obj, U &&new_value)
Definition: Utility.h:120
#define DEFINE_int32(_name, _default, _description)
Definition: GFlags.h:54
bool is_lock_free() const noexcept
static set< string > s
void store(SharedPtr n, std::memory_order order=std::memory_order_seq_cst)
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static void join(std::thread &child)