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 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=win32::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=win32::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=win32::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& timeout)
69             {
70                 return timed_lock(get_system_time()+timeout);
71             }
72 #endif
73 
74 #ifdef BOOST_THREAD_USES_CHRONO
75         template <class Rep, class Period>
try_lock_forboost::detail::basic_recursive_mutex_impl76         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
77         {
78                 long const current_thread_id=win32::GetCurrentThreadId();
79                 return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time);
80         }
81         template <class Clock, class Duration>
try_lock_untilboost::detail::basic_recursive_mutex_impl82         bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
83         {
84                 long const current_thread_id=win32::GetCurrentThreadId();
85                 return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t);
86         }
87 #endif
unlockboost::detail::basic_recursive_mutex_impl88             void unlock()
89             {
90                 if(!--recursion_count)
91                 {
92                     BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0);
93                     mutex.unlock();
94                 }
95             }
96 
97         private:
try_recursive_lockboost::detail::basic_recursive_mutex_impl98             bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT
99             {
100                 if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id)
101                 {
102                     ++recursion_count;
103                     return true;
104                 }
105                 return false;
106             }
107 
try_basic_lockboost::detail::basic_recursive_mutex_impl108             bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT
109             {
110                 if(mutex.try_lock())
111                 {
112                     BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
113                     recursion_count=1;
114                     return true;
115                 }
116                 return false;
117             }
118 
119 #if defined BOOST_THREAD_USES_DATETIME
try_timed_lockboost::detail::basic_recursive_mutex_impl120             bool try_timed_lock(long current_thread_id,::boost::system_time const& target)
121             {
122                 if(mutex.timed_lock(target))
123                 {
124                     BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
125                     recursion_count=1;
126                     return true;
127                 }
128                 return false;
129             }
130 #endif
131             template <typename TP>
try_timed_lock_untilboost::detail::basic_recursive_mutex_impl132             bool try_timed_lock_until(long current_thread_id,TP const& target)
133             {
134                 if(mutex.try_lock_until(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             template <typename D>
try_timed_lock_forboost::detail::basic_recursive_mutex_impl143             bool try_timed_lock_for(long current_thread_id,D const& target)
144             {
145                 if(mutex.try_lock_for(target))
146                 {
147                     BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
148                     recursion_count=1;
149                     return true;
150                 }
151                 return false;
152             }
153         };
154 
155         typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;
156         typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex;
157     }
158 }
159 
160 #define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
161 
162 #include <boost/config/abi_suffix.hpp>
163 
164 #endif
165