fix doc example typo
[boost.git] / boost / thread / win32 / basic_timed_mutex.hpp
blob751bdbdacc016011c5b5030b190d3df95fae1225
1 #ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
2 #define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
4 // basic_timed_mutex_win32.hpp
5 //
6 // (C) Copyright 2006-8 Anthony Williams
7 //
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 "thread_primitives.hpp"
14 #include "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>
21 namespace boost
23 namespace detail
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);
31 long active_count;
32 void* event;
34 void initialize()
36 active_count=0;
37 event=0;
40 void destroy()
42 #ifdef BOOST_MSVC
43 #pragma warning(push)
44 #pragma warning(disable:4312)
45 #endif
46 void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
47 #ifdef BOOST_MSVC
48 #pragma warning(pop)
49 #endif
50 if(old_event)
52 win32::CloseHandle(old_event);
57 bool try_lock()
59 return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
62 void lock()
64 BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
66 bool timed_lock(::boost::system_time const& wait_until)
68 if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
70 return true;
72 long old_count=active_count;
73 for(;;)
75 long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
76 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
77 if(current==old_count)
79 break;
81 old_count=current;
84 if(old_count&lock_flag_value)
86 bool lock_acquired=false;
87 void* const sem=get_event();
91 if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
93 BOOST_INTERLOCKED_DECREMENT(&active_count);
94 return false;
96 old_count&=~lock_flag_value;
97 old_count|=event_set_flag_value;
98 for(;;)
100 long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
101 long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
102 if(current==old_count)
104 break;
106 old_count=current;
108 lock_acquired=!(old_count&lock_flag_value);
110 while(!lock_acquired);
112 return true;
115 template<typename Duration>
116 bool timed_lock(Duration const& timeout)
118 return timed_lock(get_system_time()+timeout);
121 bool timed_lock(boost::xtime const& timeout)
123 return timed_lock(system_time(timeout));
126 void unlock()
128 long const offset=lock_flag_value;
129 long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
130 if(!(old_count&event_set_flag_value) && (old_count>offset))
132 if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
134 win32::SetEvent(get_event());
139 private:
140 void* get_event()
142 void* current_event=::boost::detail::interlocked_read_acquire(&event);
144 if(!current_event)
146 void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
147 #ifdef BOOST_MSVC
148 #pragma warning(push)
149 #pragma warning(disable:4311)
150 #pragma warning(disable:4312)
151 #endif
152 void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
153 #ifdef BOOST_MSVC
154 #pragma warning(pop)
155 #endif
156 if(old_event!=0)
158 win32::CloseHandle(new_event);
159 return old_event;
161 else
163 return new_event;
166 return current_event;
174 #define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
176 #include <boost/config/abi_suffix.hpp>
178 #endif