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