1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// UNSUPPORTED: libcpp-has-no-threads
11//
12// <memory>
13//
14// class shared_ptr
15//
16// This test attempts to create a race condition surrounding use_count()
17// with the hope that TSAN will diagnose it.
18
19#include <memory>
20#include <atomic>
21#include <thread>
22#include <cassert>
23
24typedef std::shared_ptr<int> Ptr;
25typedef std::weak_ptr<int> WeakPtr;
26
27std::atomic_bool Start;
28std::atomic_bool KeepRunning;
29
30struct TestRunner {
31    TestRunner(Ptr xx) : x(xx) {}
32    void operator()() {
33        while (Start == false) {}
34        while (KeepRunning) {
35            // loop to prevent always checking the atomic.
36            for (int i=0; i < 100000; ++i) {
37                Ptr x2 = x; // increment shared count
38                WeakPtr x3 = x; // increment weak count
39                Ptr x4 = x3.lock(); // increment shared count via lock
40                WeakPtr x5 = x3; // increment weak count
41            }
42        }
43    }
44    Ptr x;
45};
46
47void run_test(Ptr p) {
48    Start = false;
49    KeepRunning = true;
50    assert(p.use_count() == 2);
51    TestRunner r(p);
52    assert(p.use_count() == 3);
53    std::thread t1(r); // Start the test thread.
54    assert(p.use_count() == 4);
55    Start = true;
56    // Run until we witness 25 use count changes via both
57    // shared and weak pointer methods.
58    WeakPtr w = p;
59    int shared_changes_count = 0;
60    int weak_changes_count = 0;
61    while (shared_changes_count < 25 && weak_changes_count < 25) {
62        // check use_count on the shared_ptr
63       int last = p.use_count();
64       int new_val = p.use_count();
65       assert(last >= 4);
66       assert(new_val >= 4);
67       if (last != new_val) ++shared_changes_count;
68       // Check use_count on the weak_ptr
69       last = w.use_count();
70       new_val = w.use_count();
71       assert(last >= 4);
72       assert(new_val >= 4);
73       if (last != new_val) ++weak_changes_count;
74    }
75    // kill the test thread.
76    KeepRunning = false;
77    t1.join();
78    assert(p.use_count() == 3);
79}
80
81int main() {
82  {
83    // Test with out-of-place shared_count.
84    Ptr p(new int(42));
85    run_test(p);
86    assert(p.use_count() == 1);
87  }
88  {
89    // Test with in-place shared_count.
90    int val = 42;
91    Ptr p = std::make_shared<int>(val);
92    run_test(p);
93    assert(p.use_count() == 1);
94  }
95}
96