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// UNSUPPORTED: c++98, c++03, c++11
12
13// <shared_mutex>
14
15// template <class Mutex> class shared_lock;
16
17// void lock();
18
19#include <shared_mutex>
20#include <thread>
21#include <vector>
22#include <cstdlib>
23#include <cassert>
24
25#include "test_macros.h"
26
27std::shared_timed_mutex m;
28
29typedef std::chrono::system_clock Clock;
30typedef Clock::time_point time_point;
31typedef Clock::duration duration;
32typedef std::chrono::milliseconds ms;
33typedef std::chrono::nanoseconds ns;
34
35ms WaitTime = ms(250);
36
37// Thread sanitizer causes more overhead and will sometimes cause this test
38// to fail. To prevent this we give Thread sanitizer more time to complete the
39// test.
40#if !defined(TEST_HAS_SANITIZERS)
41ms Tolerance = ms(25);
42#else
43ms Tolerance = ms(25 * 5);
44#endif
45
46
47void f()
48{
49    std::shared_lock<std::shared_timed_mutex> lk(m, std::defer_lock);
50    time_point t0 = Clock::now();
51    lk.lock();
52    time_point t1 = Clock::now();
53    assert(lk.owns_lock() == true);
54    ns d = t1 - t0 - WaitTime;
55    assert(d < Tolerance);  // within tolerance
56#ifndef TEST_HAS_NO_EXCEPTIONS
57    try
58    {
59        lk.lock();
60        assert(false);
61    }
62    catch (std::system_error& e)
63    {
64        assert(e.code().value() == EDEADLK);
65    }
66#endif
67    lk.unlock();
68    lk.release();
69#ifndef TEST_HAS_NO_EXCEPTIONS
70    try
71    {
72        lk.lock();
73        assert(false);
74    }
75    catch (std::system_error& e)
76    {
77        assert(e.code().value() == EPERM);
78    }
79#endif
80}
81
82int main()
83{
84    m.lock();
85    std::vector<std::thread> v;
86    for (int i = 0; i < 5; ++i)
87        v.push_back(std::thread(f));
88    std::this_thread::sleep_for(WaitTime);
89    m.unlock();
90    for (auto& t : v)
91        t.join();
92}
93