]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/thread/include/boost/thread/testable_mutex.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / thread / include / boost / thread / testable_mutex.hpp
1 // (C) Copyright 2012 Vicente J. Botet Escriba
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6
7 #ifndef BOOST_THREAD_TESTABLE_LOCKABLE_HPP
8 #define BOOST_THREAD_TESTABLE_LOCKABLE_HPP
9
10 #include <boost/thread/detail/config.hpp>
11
12 #include <boost/thread/thread_only.hpp>
13
14 #include <boost/atomic.hpp>
15 #include <boost/assert.hpp>
16
17 #include <boost/config/abi_prefix.hpp>
18
19 namespace boost
20 {
21 /**
22 * Based on Associate Mutexes with Data to Prevent Races, By Herb Sutter, May 13, 2010
23 * http://www.drdobbs.com/windows/associate-mutexes-with-data-to-prevent-r/224701827?pgno=3
24 *
25 * Make our mutex testable if it isn't already.
26 *
27 * Many mutex services (including boost::mutex) don't provide a way to ask,
28 * "Do I already hold a lock on this mutex?"
29 * Sometimes it is needed to know if a method like is_locked to be available.
30 * This wrapper associates an arbitrary lockable type with a thread id that stores the ID of the thread that
31 * currently holds the lockable. The thread id initially holds an invalid value that means no threads own the mutex.
32 * When we acquire a lock, we set the thread id; and when we release a lock, we reset it back to its default no id state.
33 *
34 */
35 template <typename Lockable>
36 class testable_mutex
37 {
38 Lockable mtx_;
39 atomic<thread::id> id_;
40 public:
41 /// the type of the wrapped lockable
42 typedef Lockable lockable_type;
43
44 /// Non copyable
45 BOOST_THREAD_NO_COPYABLE(testable_mutex)
46
47 testable_mutex() : id_(thread::id()) {}
48
49 void lock()
50 {
51 BOOST_ASSERT(! is_locked_by_this_thread());
52 mtx_.lock();
53 id_ = this_thread::get_id();
54 }
55
56 void unlock()
57 {
58 BOOST_ASSERT(is_locked_by_this_thread());
59 id_ = thread::id();
60 mtx_.unlock();
61 }
62
63 bool try_lock()
64 {
65 BOOST_ASSERT(! is_locked_by_this_thread());
66 if (mtx_.try_lock())
67 {
68 id_ = this_thread::get_id();
69 return true;
70 }
71 else
72 {
73 return false;
74 }
75 }
76 #ifdef BOOST_THREAD_USES_CHRONO
77 template <class Rep, class Period>
78 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
79 {
80 BOOST_ASSERT(! is_locked_by_this_thread());
81 if (mtx_.try_lock_for(rel_time))
82 {
83 id_ = this_thread::get_id();
84 return true;
85 }
86 else
87 {
88 return false;
89 }
90 }
91 template <class Clock, class Duration>
92 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
93 {
94 BOOST_ASSERT(! is_locked_by_this_thread());
95 if (mtx_.try_lock_until(abs_time))
96 {
97 id_ = this_thread::get_id();
98 return true;
99 }
100 else
101 {
102 return false;
103 }
104 }
105 #endif
106
107 bool is_locked_by_this_thread() const
108 {
109 return this_thread::get_id() == id_;
110 }
111 bool is_locked() const
112 {
113 return ! (thread::id() == id_);
114 }
115
116 thread::id get_id() const
117 {
118 return id_;
119 }
120
121 // todo add the shared and upgrade mutex functions
122 };
123
124 template <typename Lockable>
125 struct is_testable_lockable : false_type
126 {};
127
128 template <typename Lockable>
129 struct is_testable_lockable<testable_mutex<Lockable> > : true_type
130 {};
131
132 // /**
133 // * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise.
134 // *
135 // * This function is used usually to assert the pre-condition when the function can only be called when the mutex
136 // * must be locked by the current thread.
137 // */
138 // template <typename Lockable>
139 // bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx)
140 // {
141 // return mtx.is_locked();
142 // }
143 // template <typename Lockable>
144 // bool is_locked_by_this_thread(Lockable const&)
145 // {
146 // return true;
147 // }
148 }
149
150 #include <boost/config/abi_suffix.hpp>
151
152 #endif // header