Fix violations of unused-lambda-capture
[folly.git] / folly / experimental / test / AtomicSharedPtrTest.cpp
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 #include <atomic>
17 #include <memory>
18 #include <thread>
19
20 #include <folly/experimental/AtomicSharedPtr.h>
21 #include <folly/experimental/test/AtomicSharedPtrCounted.h>
22 #include <folly/portability/GTest.h>
23
24 #include <folly/test/DeterministicSchedule.h>
25
26 using namespace folly;
27 using namespace folly::test;
28 using namespace std;
29 static int c_count{0};
30 static int d_count{0};
31
32 using DSched = DeterministicSchedule;
33
34 DEFINE_int64(seed, 0, "Seed for random number generators");
35 DEFINE_int32(num_threads, 32, "Number of threads");
36
37 struct foo {
38   foo() {
39     c_count++;
40   }
41   ~foo() {
42     d_count++;
43   }
44 };
45
46 TEST(AtomicSharedPtr, operators) {
47   atomic_shared_ptr<int> fooptr;
48   EXPECT_TRUE(fooptr.is_lock_free());
49   auto i = new int(5);
50   std::shared_ptr<int> s(i);
51   fooptr.store(s);
52   shared_ptr<int> bar(fooptr);
53   EXPECT_TRUE(fooptr.compare_exchange_strong(s, nullptr));
54   s.reset();
55   bar.reset();
56 }
57
58 TEST(AtomicSharedPtr, exchange) {
59   atomic_shared_ptr<int> fooptr;
60   auto a = make_shared<int>(1);
61   fooptr.store(std::move(a));
62   auto b = fooptr.exchange(make_shared<int>());
63   EXPECT_EQ(*b, 1);
64 }
65
66 TEST(AtomicSharedPtr, foo) {
67   c_count = 0;
68   d_count = 0;
69   {
70     atomic_shared_ptr<foo> fooptr;
71     fooptr.store(make_shared<foo>());
72     EXPECT_EQ(1, c_count);
73     EXPECT_EQ(0, d_count);
74     {
75       auto res = fooptr.load();
76       EXPECT_EQ(1, c_count);
77       EXPECT_EQ(0, d_count);
78     }
79     EXPECT_EQ(1, c_count);
80     EXPECT_EQ(0, d_count);
81   }
82   EXPECT_EQ(1, c_count);
83   EXPECT_EQ(1, d_count);
84 }
85
86 TEST(AtomicSharedPtr, counted) {
87   c_count = 0;
88   d_count = 0;
89   {
90     atomic_shared_ptr<foo, std::atomic, counted_ptr_internals<std::atomic>>
91         fooptr;
92     fooptr.store(make_counted<std::atomic, foo>());
93     EXPECT_EQ(1, c_count);
94     EXPECT_EQ(0, d_count);
95     {
96       auto res = fooptr.load();
97       EXPECT_EQ(1, c_count);
98       EXPECT_EQ(0, d_count);
99     }
100     EXPECT_EQ(1, c_count);
101     EXPECT_EQ(0, d_count);
102   }
103   EXPECT_EQ(1, c_count);
104   EXPECT_EQ(1, d_count);
105 }
106
107 TEST(AtomicSharedPtr, counted2) {
108   auto foo = make_counted<std::atomic, bool>();
109   atomic_shared_ptr<bool, std::atomic, counted_ptr_internals<std::atomic>>
110       fooptr(foo);
111   fooptr.store(foo);
112   fooptr.load();
113 }
114
115 TEST(AtomicSharedPtr, ConstTest) {
116   const auto a(std::make_shared<foo>());
117   atomic_shared_ptr<foo> atom;
118   atom.store(a);
119
120   atomic_shared_ptr<const foo> catom;
121 }
122 TEST(AtomicSharedPtr, AliasingConstructorTest) {
123   c_count = 0;
124   d_count = 0;
125   auto a = std::make_shared<foo>();
126   auto b = new foo;
127   auto alias = std::shared_ptr<foo>(a, b);
128
129   atomic_shared_ptr<foo> asp;
130   asp.store(alias);
131   a.reset();
132   alias.reset();
133   auto res1 = asp.load();
134   auto res2 = asp.exchange(nullptr);
135   EXPECT_EQ(b, res1.get());
136   EXPECT_EQ(b, res2.get());
137   EXPECT_EQ(2, c_count);
138   EXPECT_EQ(0, d_count);
139   res1.reset();
140   res2.reset();
141   EXPECT_EQ(2, c_count);
142   EXPECT_EQ(1, d_count);
143   delete b;
144   EXPECT_EQ(2, c_count);
145   EXPECT_EQ(2, d_count);
146 }
147
148 TEST(AtomicSharedPtr, DeterministicTest) {
149   DSched sched(DSched::uniform(FLAGS_seed));
150
151   auto foo = make_counted<DeterministicAtomic, bool>();
152   atomic_shared_ptr<
153       bool,
154       DeterministicAtomic,
155       counted_ptr_internals<DeterministicAtomic>>
156       fooptr(foo);
157   std::vector<std::thread> threads(FLAGS_num_threads);
158   for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
159     threads[tid] = DSched::thread([&]() {
160       for (int i = 0; i < 1000; i++) {
161         auto l = fooptr.load();
162         EXPECT_TRUE(l.get() != nullptr);
163         fooptr.compare_exchange_strong(l, l);
164         fooptr.store(make_counted<DeterministicAtomic, bool>());
165         EXPECT_FALSE(fooptr.compare_exchange_strong(
166             l, make_counted<DeterministicAtomic, bool>()));
167       }
168     });
169   }
170   for (auto& t : threads) {
171     DSched::join(t);
172   }
173 }