11faf289eSEric Fiselier //===----------------------------------------------------------------------===// 21faf289eSEric Fiselier // 357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61faf289eSEric Fiselier // 71faf289eSEric Fiselier //===----------------------------------------------------------------------===// 81faf289eSEric Fiselier // 9*a7f9895cSLouis Dionne // UNSUPPORTED: no-threads 101faf289eSEric Fiselier // 111faf289eSEric Fiselier // <memory> 121faf289eSEric Fiselier // 131faf289eSEric Fiselier // class shared_ptr 141faf289eSEric Fiselier // 151faf289eSEric Fiselier // This test attempts to create a race condition surrounding use_count() 161faf289eSEric Fiselier // with the hope that TSAN will diagnose it. 171faf289eSEric Fiselier 181faf289eSEric Fiselier #include <memory> 191faf289eSEric Fiselier #include <atomic> 201faf289eSEric Fiselier #include <thread> 211faf289eSEric Fiselier #include <cassert> 221faf289eSEric Fiselier 2356462801SLouis Dionne #include "make_test_thread.h" 247fc6a556SMarshall Clow #include "test_macros.h" 257fc6a556SMarshall Clow 261faf289eSEric Fiselier typedef std::shared_ptr<int> Ptr; 271faf289eSEric Fiselier typedef std::weak_ptr<int> WeakPtr; 281faf289eSEric Fiselier 291faf289eSEric Fiselier std::atomic_bool Start; 301faf289eSEric Fiselier std::atomic_bool KeepRunning; 311faf289eSEric Fiselier 321faf289eSEric Fiselier struct TestRunner { TestRunnerTestRunner331faf289eSEric Fiselier TestRunner(Ptr xx) : x(xx) {} operator ()TestRunner341faf289eSEric Fiselier void operator()() { 351faf289eSEric Fiselier while (Start == false) {} 361faf289eSEric Fiselier while (KeepRunning) { 371faf289eSEric Fiselier // loop to prevent always checking the atomic. 381faf289eSEric Fiselier for (int i=0; i < 100000; ++i) { 391faf289eSEric Fiselier Ptr x2 = x; // increment shared count 401faf289eSEric Fiselier WeakPtr x3 = x; // increment weak count 411faf289eSEric Fiselier Ptr x4 = x3.lock(); // increment shared count via lock 421faf289eSEric Fiselier WeakPtr x5 = x3; // increment weak count 431faf289eSEric Fiselier } 441faf289eSEric Fiselier } 451faf289eSEric Fiselier } 461faf289eSEric Fiselier Ptr x; 471faf289eSEric Fiselier }; 481faf289eSEric Fiselier run_test(Ptr p)491faf289eSEric Fiseliervoid run_test(Ptr p) { 501faf289eSEric Fiselier Start = false; 511faf289eSEric Fiselier KeepRunning = true; 521faf289eSEric Fiselier assert(p.use_count() == 2); 531faf289eSEric Fiselier TestRunner r(p); 541faf289eSEric Fiselier assert(p.use_count() == 3); 5556462801SLouis Dionne std::thread t1 = support::make_test_thread(r); // Start the test thread. 561faf289eSEric Fiselier assert(p.use_count() == 4); 571faf289eSEric Fiselier Start = true; 581faf289eSEric Fiselier // Run until we witness 25 use count changes via both 591faf289eSEric Fiselier // shared and weak pointer methods. 601faf289eSEric Fiselier WeakPtr w = p; 611faf289eSEric Fiselier int shared_changes_count = 0; 621faf289eSEric Fiselier int weak_changes_count = 0; 631faf289eSEric Fiselier while (shared_changes_count < 25 && weak_changes_count < 25) { 641faf289eSEric Fiselier // check use_count on the shared_ptr 651faf289eSEric Fiselier int last = p.use_count(); 661faf289eSEric Fiselier int new_val = p.use_count(); 671faf289eSEric Fiselier assert(last >= 4); 681faf289eSEric Fiselier assert(new_val >= 4); 691faf289eSEric Fiselier if (last != new_val) ++shared_changes_count; 701faf289eSEric Fiselier // Check use_count on the weak_ptr 711faf289eSEric Fiselier last = w.use_count(); 721faf289eSEric Fiselier new_val = w.use_count(); 731faf289eSEric Fiselier assert(last >= 4); 741faf289eSEric Fiselier assert(new_val >= 4); 751faf289eSEric Fiselier if (last != new_val) ++weak_changes_count; 761faf289eSEric Fiselier } 771faf289eSEric Fiselier // kill the test thread. 781faf289eSEric Fiselier KeepRunning = false; 791faf289eSEric Fiselier t1.join(); 801faf289eSEric Fiselier assert(p.use_count() == 3); 811faf289eSEric Fiselier } 821faf289eSEric Fiselier main(int,char **)832df59c50SJF Bastienint main(int, char**) { 841faf289eSEric Fiselier { 851faf289eSEric Fiselier // Test with out-of-place shared_count. 861faf289eSEric Fiselier Ptr p(new int(42)); 871faf289eSEric Fiselier run_test(p); 881faf289eSEric Fiselier assert(p.use_count() == 1); 891faf289eSEric Fiselier } 901faf289eSEric Fiselier { 911faf289eSEric Fiselier // Test with in-place shared_count. 921e051aabSEric Fiselier int val = 42; 931e051aabSEric Fiselier Ptr p = std::make_shared<int>(val); 941faf289eSEric Fiselier run_test(p); 951faf289eSEric Fiselier assert(p.use_count() == 1); 961faf289eSEric Fiselier } 972df59c50SJF Bastien 982df59c50SJF Bastien return 0; 991faf289eSEric Fiselier } 100