1 #ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
2 #define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
4 // basic_timed_mutex_win32.hpp
6 // (C) Copyright 2006-8 Anthony Williams
8 // Distributed under the Boost Software License, Version 1.0. (See
9 // accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
12 #include <boost/assert.hpp>
13 #include <boost/thread/win32/thread_primitives.hpp>
14 #include <boost/thread/win32/interlocked_read.hpp>
15 #include <boost/thread/thread_time.hpp>
16 #include <boost/thread/xtime.hpp>
17 #include <boost/detail/interlocked.hpp>
19 #include <boost/config/abi_prefix.hpp>
25 struct basic_timed_mutex
27 BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
28 BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
29 BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
30 BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
44 #pragma warning(disable:4312)
46 void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
52 win32::CloseHandle(old_event);
59 return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
68 long old_count=active_count;
69 mark_waiting_and_try_lock(old_count);
71 if(old_count&lock_flag_value)
73 bool lock_acquired=false;
74 void* const sem=get_event();
78 BOOST_VERIFY(win32::WaitForSingleObject(
79 sem,::boost::detail::win32::infinite)==0);
80 clear_waiting_and_try_lock(old_count);
81 lock_acquired=!(old_count&lock_flag_value);
83 while(!lock_acquired);
86 void mark_waiting_and_try_lock(long& old_count)
90 long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
91 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
92 if(current==old_count)
100 void clear_waiting_and_try_lock(long& old_count)
102 old_count&=~lock_flag_value;
103 old_count|=event_set_flag_value;
106 long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
107 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
108 if(current==old_count)
117 bool timed_lock(::boost::system_time const& wait_until)
123 long old_count=active_count;
124 mark_waiting_and_try_lock(old_count);
126 if(old_count&lock_flag_value)
128 bool lock_acquired=false;
129 void* const sem=get_event();
133 if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
135 BOOST_INTERLOCKED_DECREMENT(&active_count);
138 clear_waiting_and_try_lock(old_count);
139 lock_acquired=!(old_count&lock_flag_value);
141 while(!lock_acquired);
146 template<typename Duration>
147 bool timed_lock(Duration const& timeout)
149 return timed_lock(get_system_time()+timeout);
152 bool timed_lock(boost::xtime const& timeout)
154 return timed_lock(system_time(timeout));
159 long const offset=lock_flag_value;
160 long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
161 if(!(old_count&event_set_flag_value) && (old_count>offset))
163 if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
165 win32::SetEvent(get_event());
173 void* current_event=::boost::detail::interlocked_read_acquire(&event);
177 void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
179 #pragma warning(push)
180 #pragma warning(disable:4311)
181 #pragma warning(disable:4312)
183 void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
189 win32::CloseHandle(new_event);
197 return current_event;
205 #define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
207 #include <boost/config/abi_suffix.hpp>