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