15a83710eSEric Fiselier //===----------------------------------------------------------------------===// 25a83710eSEric 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 65a83710eSEric Fiselier // 75a83710eSEric Fiselier //===----------------------------------------------------------------------===// 85a83710eSEric Fiselier // 9*a7f9895cSLouis Dionne // UNSUPPORTED: no-threads 1031cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11 11a55632a0SLouis Dionne // ALLOW_RETRIES: 2 122659663eSLouis Dionne 132659663eSLouis Dionne // dylib support for shared_mutex was added in macosx10.12 14c360553cSLouis Dionne // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}} 155a83710eSEric Fiselier 165a83710eSEric Fiselier // <shared_mutex> 175a83710eSEric Fiselier 185a83710eSEric Fiselier // template <class Mutex> class shared_lock; 195a83710eSEric Fiselier 205a83710eSEric Fiselier // explicit shared_lock(mutex_type& m); 215a83710eSEric Fiselier 226015dd11SMarshall Clow // template<class _Mutex> shared_lock(shared_lock<_Mutex>) 236015dd11SMarshall Clow // -> shared_lock<_Mutex>; // C++17 246015dd11SMarshall Clow 255a83710eSEric Fiselier #include <shared_mutex> 265a83710eSEric Fiselier #include <thread> 275a83710eSEric Fiselier #include <vector> 285a83710eSEric Fiselier #include <cstdlib> 295a83710eSEric Fiselier #include <cassert> 305a83710eSEric Fiselier 3156462801SLouis Dionne #include "make_test_thread.h" 324c0a2a98SEric Fiselier #include "test_macros.h" 335a83710eSEric Fiselier 345a83710eSEric Fiselier typedef std::chrono::system_clock Clock; 355a83710eSEric Fiselier typedef Clock::time_point time_point; 365a83710eSEric Fiselier typedef Clock::duration duration; 375a83710eSEric Fiselier typedef std::chrono::milliseconds ms; 385a83710eSEric Fiselier typedef std::chrono::nanoseconds ns; 395a83710eSEric Fiselier 404c0a2a98SEric Fiselier ms WaitTime = ms(250); 414c0a2a98SEric Fiselier 424c0a2a98SEric Fiselier // Thread sanitizer causes more overhead and will sometimes cause this test 434c0a2a98SEric Fiselier // to fail. To prevent this we give Thread sanitizer more time to complete the 444c0a2a98SEric Fiselier // test. 457362982eSEric Fiselier #if !defined(TEST_HAS_SANITIZERS) 464c0a2a98SEric Fiselier ms Tolerance = ms(50); 474c0a2a98SEric Fiselier #else 487362982eSEric Fiselier ms Tolerance = ms(50 * 5); 494c0a2a98SEric Fiselier #endif 504c0a2a98SEric Fiselier 514c0a2a98SEric Fiselier std::shared_timed_mutex m; 524c0a2a98SEric Fiselier f()535a83710eSEric Fiseliervoid f() 545a83710eSEric Fiselier { 555a83710eSEric Fiselier time_point t0 = Clock::now(); 565a83710eSEric Fiselier time_point t1; 575a83710eSEric Fiselier { 585a83710eSEric Fiselier std::shared_lock<std::shared_timed_mutex> ul(m); 595a83710eSEric Fiselier t1 = Clock::now(); 605a83710eSEric Fiselier } 614c0a2a98SEric Fiselier ns d = t1 - t0 - WaitTime; 624c0a2a98SEric Fiselier assert(d < Tolerance); // within tolerance 635a83710eSEric Fiselier } 645a83710eSEric Fiselier g()655a83710eSEric Fiseliervoid g() 665a83710eSEric Fiselier { 675a83710eSEric Fiselier time_point t0 = Clock::now(); 685a83710eSEric Fiselier time_point t1; 695a83710eSEric Fiselier { 705a83710eSEric Fiselier std::shared_lock<std::shared_timed_mutex> ul(m); 715a83710eSEric Fiselier t1 = Clock::now(); 725a83710eSEric Fiselier } 735a83710eSEric Fiselier ns d = t1 - t0; 744c0a2a98SEric Fiselier assert(d < Tolerance); // within tolerance 755a83710eSEric Fiselier } 765a83710eSEric Fiselier main(int,char **)772df59c50SJF Bastienint main(int, char**) 785a83710eSEric Fiselier { 795a83710eSEric Fiselier std::vector<std::thread> v; 804c0a2a98SEric Fiselier { 814c0a2a98SEric Fiselier m.lock(); 825a83710eSEric Fiselier for (int i = 0; i < 5; ++i) 8356462801SLouis Dionne v.push_back(support::make_test_thread(f)); 844c0a2a98SEric Fiselier std::this_thread::sleep_for(WaitTime); 855a83710eSEric Fiselier m.unlock(); 865a83710eSEric Fiselier for (auto& t : v) 875a83710eSEric Fiselier t.join(); 884c0a2a98SEric Fiselier } 894c0a2a98SEric Fiselier { 905a83710eSEric Fiselier m.lock_shared(); 915a83710eSEric Fiselier for (auto& t : v) 9256462801SLouis Dionne t = support::make_test_thread(g); 9356462801SLouis Dionne std::thread q = support::make_test_thread(f); 944c0a2a98SEric Fiselier std::this_thread::sleep_for(WaitTime); 955a83710eSEric Fiselier m.unlock_shared(); 965a83710eSEric Fiselier for (auto& t : v) 975a83710eSEric Fiselier t.join(); 985a83710eSEric Fiselier q.join(); 994c0a2a98SEric Fiselier } 1006015dd11SMarshall Clow 10101666904SLouis Dionne #if TEST_STD_VER >= 17 1026015dd11SMarshall Clow std::shared_lock sl(m); 1036015dd11SMarshall Clow static_assert((std::is_same<decltype(sl), std::shared_lock<decltype(m)>>::value), "" ); 1046015dd11SMarshall Clow #endif 1052df59c50SJF Bastien 1062df59c50SJF Bastien return 0; 1075a83710eSEric Fiselier } 108