2 * Copyright 2017-present Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <folly/concurrency/AtomicSharedPtr.h>
21 #include <folly/concurrency/test/AtomicSharedPtrCounted.h>
22 #include <folly/portability/GTest.h>
24 #include <folly/test/DeterministicSchedule.h>
26 using namespace folly;
27 using namespace folly::test;
29 static int c_count{0};
30 static int d_count{0};
32 using DSched = DeterministicSchedule;
34 DEFINE_int64(seed, 0, "Seed for random number generators");
35 DEFINE_int32(num_threads, 32, "Number of threads");
46 TEST(AtomicSharedPtr, operators) {
47 atomic_shared_ptr<int> fooptr;
48 EXPECT_TRUE(fooptr.is_lock_free());
50 std::shared_ptr<int> s(i);
52 shared_ptr<int> bar(fooptr);
53 EXPECT_TRUE(fooptr.compare_exchange_strong(s, nullptr));
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>());
66 TEST(AtomicSharedPtr, foo) {
70 atomic_shared_ptr<foo> fooptr;
71 fooptr.store(make_shared<foo>());
72 EXPECT_EQ(1, c_count);
73 EXPECT_EQ(0, d_count);
75 auto res = fooptr.load();
76 EXPECT_EQ(1, c_count);
77 EXPECT_EQ(0, d_count);
79 EXPECT_EQ(1, c_count);
80 EXPECT_EQ(0, d_count);
82 EXPECT_EQ(1, c_count);
83 EXPECT_EQ(1, d_count);
86 TEST(AtomicSharedPtr, counted) {
90 atomic_shared_ptr<foo, std::atomic, counted_ptr_internals<std::atomic>>
92 fooptr.store(make_counted<std::atomic, foo>());
93 EXPECT_EQ(1, c_count);
94 EXPECT_EQ(0, d_count);
96 auto res = fooptr.load();
97 EXPECT_EQ(1, c_count);
98 EXPECT_EQ(0, d_count);
100 EXPECT_EQ(1, c_count);
101 EXPECT_EQ(0, d_count);
103 EXPECT_EQ(1, c_count);
104 EXPECT_EQ(1, d_count);
107 TEST(AtomicSharedPtr, counted2) {
108 auto foo = make_counted<std::atomic, bool>();
109 atomic_shared_ptr<bool, std::atomic, counted_ptr_internals<std::atomic>>
115 TEST(AtomicSharedPtr, ConstTest) {
116 const auto a(std::make_shared<foo>());
117 atomic_shared_ptr<foo> atom;
120 atomic_shared_ptr<const foo> catom;
122 TEST(AtomicSharedPtr, AliasingConstructorTest) {
125 auto a = std::make_shared<foo>();
127 auto alias = std::shared_ptr<foo>(a, b);
129 atomic_shared_ptr<foo> asp;
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);
141 EXPECT_EQ(2, c_count);
142 EXPECT_EQ(1, d_count);
144 EXPECT_EQ(2, c_count);
145 EXPECT_EQ(2, d_count);
148 TEST(AtomicSharedPtr, MaxPtrs) {
149 shared_ptr<long> p(new long);
150 int max_atomic_shared_ptrs = 262144;
151 atomic_shared_ptr<long> ptrs[max_atomic_shared_ptrs];
152 for (int i = 0; i < max_atomic_shared_ptrs - 1; i++) {
155 atomic_shared_ptr<long> fail;
156 EXPECT_DEATH(fail.store(p), "");
159 TEST(AtomicSharedPtr, DeterministicTest) {
160 DSched sched(DSched::uniform(FLAGS_seed));
162 auto foo = make_counted<DeterministicAtomic, bool>();
166 counted_ptr_internals<DeterministicAtomic>>
168 std::vector<std::thread> threads(FLAGS_num_threads);
169 for (int tid = 0; tid < FLAGS_num_threads; ++tid) {
170 threads[tid] = DSched::thread([&]() {
171 for (int i = 0; i < 1000; i++) {
172 auto l = fooptr.load();
173 EXPECT_TRUE(l.get() != nullptr);
174 fooptr.compare_exchange_strong(l, l);
175 fooptr.store(make_counted<DeterministicAtomic, bool>());
176 EXPECT_FALSE(fooptr.compare_exchange_strong(
177 l, make_counted<DeterministicAtomic, bool>()));
181 for (auto& t : threads) {