diff options
Diffstat (limited to 'test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp')
-rw-r--r-- | test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp b/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp new file mode 100644 index 0000000000000..25dd31190685c --- /dev/null +++ b/test/libcxx/utilities/memory/util.smartptr/race_condition.pass.cpp @@ -0,0 +1,94 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: libcpp-has-no-threads +// +// <memory> +// +// class shared_ptr +// +// This test attempts to create a race condition surrounding use_count() +// with the hope that TSAN will diagnose it. + +#include <memory> +#include <atomic> +#include <thread> +#include <cassert> + +typedef std::shared_ptr<int> Ptr; +typedef std::weak_ptr<int> WeakPtr; + +std::atomic_bool Start; +std::atomic_bool KeepRunning; + +struct TestRunner { + TestRunner(Ptr xx) : x(xx) {} + void operator()() { + while (Start == false) {} + while (KeepRunning) { + // loop to prevent always checking the atomic. + for (int i=0; i < 100000; ++i) { + Ptr x2 = x; // increment shared count + WeakPtr x3 = x; // increment weak count + Ptr x4 = x3.lock(); // increment shared count via lock + WeakPtr x5 = x3; // increment weak count + } + } + } + Ptr x; +}; + +void run_test(Ptr p) { + Start = false; + KeepRunning = true; + assert(p.use_count() == 2); + TestRunner r(p); + assert(p.use_count() == 3); + std::thread t1(r); // Start the test thread. + assert(p.use_count() == 4); + Start = true; + // Run until we witness 25 use count changes via both + // shared and weak pointer methods. + WeakPtr w = p; + int shared_changes_count = 0; + int weak_changes_count = 0; + while (shared_changes_count < 25 && weak_changes_count < 25) { + // check use_count on the shared_ptr + int last = p.use_count(); + int new_val = p.use_count(); + assert(last >= 4); + assert(new_val >= 4); + if (last != new_val) ++shared_changes_count; + // Check use_count on the weak_ptr + last = w.use_count(); + new_val = w.use_count(); + assert(last >= 4); + assert(new_val >= 4); + if (last != new_val) ++weak_changes_count; + } + // kill the test thread. + KeepRunning = false; + t1.join(); + assert(p.use_count() == 3); +} + +int main() { + { + // Test with out-of-place shared_count. + Ptr p(new int(42)); + run_test(p); + assert(p.use_count() == 1); + } + { + // Test with in-place shared_count. + Ptr p = std::make_shared<int>(42); + run_test(p); + assert(p.use_count() == 1); + } +} |