Chris@16
|
1 #ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
Chris@16
|
2 #define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
Chris@16
|
3
|
Chris@16
|
4 // basic_recursive_mutex.hpp
|
Chris@16
|
5 //
|
Chris@16
|
6 // (C) Copyright 2006-8 Anthony Williams
|
Chris@16
|
7 // (C) Copyright 2011-2012 Vicente J. Botet Escriba
|
Chris@16
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
10 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12
|
Chris@16
|
13 #include <boost/thread/win32/thread_primitives.hpp>
|
Chris@16
|
14 #include <boost/thread/win32/basic_timed_mutex.hpp>
|
Chris@16
|
15 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
16 #include <boost/chrono/system_clocks.hpp>
|
Chris@16
|
17 #include <boost/chrono/ceil.hpp>
|
Chris@16
|
18 #endif
|
Chris@16
|
19
|
Chris@16
|
20 #include <boost/config/abi_prefix.hpp>
|
Chris@16
|
21
|
Chris@16
|
22 namespace boost
|
Chris@16
|
23 {
|
Chris@16
|
24 namespace detail
|
Chris@16
|
25 {
|
Chris@16
|
26 template<typename underlying_mutex_type>
|
Chris@16
|
27 struct basic_recursive_mutex_impl
|
Chris@16
|
28 {
|
Chris@16
|
29 long recursion_count;
|
Chris@16
|
30 long locking_thread_id;
|
Chris@16
|
31 underlying_mutex_type mutex;
|
Chris@16
|
32
|
Chris@16
|
33 void initialize()
|
Chris@16
|
34 {
|
Chris@16
|
35 recursion_count=0;
|
Chris@16
|
36 locking_thread_id=0;
|
Chris@16
|
37 mutex.initialize();
|
Chris@16
|
38 }
|
Chris@16
|
39
|
Chris@16
|
40 void destroy()
|
Chris@16
|
41 {
|
Chris@16
|
42 mutex.destroy();
|
Chris@16
|
43 }
|
Chris@16
|
44
|
Chris@16
|
45 bool try_lock() BOOST_NOEXCEPT
|
Chris@16
|
46 {
|
Chris@16
|
47 long const current_thread_id=win32::GetCurrentThreadId();
|
Chris@16
|
48 return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
|
Chris@16
|
49 }
|
Chris@16
|
50
|
Chris@16
|
51 void lock()
|
Chris@16
|
52 {
|
Chris@16
|
53 long const current_thread_id=win32::GetCurrentThreadId();
|
Chris@16
|
54 if(!try_recursive_lock(current_thread_id))
|
Chris@16
|
55 {
|
Chris@16
|
56 mutex.lock();
|
Chris@16
|
57 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
Chris@16
|
58 recursion_count=1;
|
Chris@16
|
59 }
|
Chris@16
|
60 }
|
Chris@16
|
61 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
62 bool timed_lock(::boost::system_time const& target)
|
Chris@16
|
63 {
|
Chris@16
|
64 long const current_thread_id=win32::GetCurrentThreadId();
|
Chris@16
|
65 return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
Chris@16
|
66 }
|
Chris@16
|
67 template<typename Duration>
|
Chris@16
|
68 bool timed_lock(Duration const& timeout)
|
Chris@16
|
69 {
|
Chris@16
|
70 return timed_lock(get_system_time()+timeout);
|
Chris@16
|
71 }
|
Chris@16
|
72 #endif
|
Chris@16
|
73
|
Chris@16
|
74 #ifdef BOOST_THREAD_USES_CHRONO
|
Chris@16
|
75 template <class Rep, class Period>
|
Chris@16
|
76 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
|
Chris@16
|
77 {
|
Chris@16
|
78 long const current_thread_id=win32::GetCurrentThreadId();
|
Chris@16
|
79 return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
|
Chris@16
|
80 }
|
Chris@16
|
81 template <class Clock, class Duration>
|
Chris@16
|
82 bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
|
Chris@16
|
83 {
|
Chris@16
|
84 long const current_thread_id=win32::GetCurrentThreadId();
|
Chris@16
|
85 return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
|
Chris@16
|
86 }
|
Chris@16
|
87 #endif
|
Chris@16
|
88 void unlock()
|
Chris@16
|
89 {
|
Chris@16
|
90 if(!--recursion_count)
|
Chris@16
|
91 {
|
Chris@16
|
92 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0);
|
Chris@16
|
93 mutex.unlock();
|
Chris@16
|
94 }
|
Chris@16
|
95 }
|
Chris@16
|
96
|
Chris@16
|
97 private:
|
Chris@16
|
98 bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
|
Chris@16
|
99 {
|
Chris@16
|
100 if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
|
Chris@16
|
101 {
|
Chris@16
|
102 ++recursion_count;
|
Chris@16
|
103 return true;
|
Chris@16
|
104 }
|
Chris@16
|
105 return false;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
|
Chris@16
|
109 {
|
Chris@16
|
110 if(mutex.try_lock())
|
Chris@16
|
111 {
|
Chris@16
|
112 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
Chris@16
|
113 recursion_count=1;
|
Chris@16
|
114 return true;
|
Chris@16
|
115 }
|
Chris@16
|
116 return false;
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 #if defined BOOST_THREAD_USES_DATETIME
|
Chris@16
|
120 bool try_timed_lock(long current_thread_id,::boost::system_time const& target)
|
Chris@16
|
121 {
|
Chris@16
|
122 if(mutex.timed_lock(target))
|
Chris@16
|
123 {
|
Chris@16
|
124 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
Chris@16
|
125 recursion_count=1;
|
Chris@16
|
126 return true;
|
Chris@16
|
127 }
|
Chris@16
|
128 return false;
|
Chris@16
|
129 }
|
Chris@16
|
130 #endif
|
Chris@16
|
131 template <typename TP>
|
Chris@16
|
132 bool try_timed_lock_until(long current_thread_id,TP const& target)
|
Chris@16
|
133 {
|
Chris@16
|
134 if(mutex.try_lock_until(target))
|
Chris@16
|
135 {
|
Chris@16
|
136 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
Chris@16
|
137 recursion_count=1;
|
Chris@16
|
138 return true;
|
Chris@16
|
139 }
|
Chris@16
|
140 return false;
|
Chris@16
|
141 }
|
Chris@16
|
142 template <typename D>
|
Chris@16
|
143 bool try_timed_lock_for(long current_thread_id,D const& target)
|
Chris@16
|
144 {
|
Chris@16
|
145 if(mutex.try_lock_for(target))
|
Chris@16
|
146 {
|
Chris@16
|
147 BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
Chris@16
|
148 recursion_count=1;
|
Chris@16
|
149 return true;
|
Chris@16
|
150 }
|
Chris@16
|
151 return false;
|
Chris@16
|
152 }
|
Chris@16
|
153 };
|
Chris@16
|
154
|
Chris@16
|
155 typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;
|
Chris@16
|
156 typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex;
|
Chris@16
|
157 }
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 #define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
|
Chris@16
|
161
|
Chris@16
|
162 #include <boost/config/abi_suffix.hpp>
|
Chris@16
|
163
|
Chris@16
|
164 #endif
|