]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/boost/boost/thread/win32/basic_timed_mutex.hpp
Add subset of boost library headers needed for compilation on PowerPC
[eurobot/public.git] / src / boost / boost / thread / win32 / basic_timed_mutex.hpp
1 #ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
2 #define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
3
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)
11
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>
18
19 #include <boost/config/abi_prefix.hpp>
20
21 namespace boost
22 {
23     namespace detail
24     {
25         struct basic_timed_mutex
26         {
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;
33
34             void initialize()
35             {
36                 active_count=0;
37                 event=0;
38             }
39
40             void destroy()
41             {
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)
51                 {
52                     win32::CloseHandle(old_event);
53                 }
54             }
55
56
57             bool try_lock()
58             {
59                 return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
60             }
61
62             void lock()
63             {
64                 if(try_lock())
65                 {
66                     return;
67                 }
68                 long old_count=active_count;
69                 mark_waiting_and_try_lock(old_count);
70
71                 if(old_count&lock_flag_value)
72                 {
73                     bool lock_acquired=false;
74                     void* const sem=get_event();
75
76                     do
77                     {
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);
82                     }
83                     while(!lock_acquired);
84                 }
85             }
86             void mark_waiting_and_try_lock(long& old_count)
87             {
88                 for(;;)
89                 {
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)
93                     {
94                         break;
95                     }
96                     old_count=current;
97                 }
98             }
99
100             void clear_waiting_and_try_lock(long& old_count)
101             {
102                 old_count&=~lock_flag_value;
103                 old_count|=event_set_flag_value;
104                 for(;;)
105                 {
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)
109                     {
110                         break;
111                     }
112                     old_count=current;
113                 }
114             }
115
116
117             bool timed_lock(::boost::system_time const& wait_until)
118             {
119                 if(try_lock())
120                 {
121                     return true;
122                 }
123                 long old_count=active_count;
124                 mark_waiting_and_try_lock(old_count);
125
126                 if(old_count&lock_flag_value)
127                 {
128                     bool lock_acquired=false;
129                     void* const sem=get_event();
130
131                     do
132                     {
133                         if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
134                         {
135                             BOOST_INTERLOCKED_DECREMENT(&active_count);
136                             return false;
137                         }
138                         clear_waiting_and_try_lock(old_count);
139                         lock_acquired=!(old_count&lock_flag_value);
140                     }
141                     while(!lock_acquired);
142                 }
143                 return true;
144             }
145
146             template<typename Duration>
147             bool timed_lock(Duration const& timeout)
148             {
149                 return timed_lock(get_system_time()+timeout);
150             }
151
152             bool timed_lock(boost::xtime const& timeout)
153             {
154                 return timed_lock(system_time(timeout));
155             }
156
157             void unlock()
158             {
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))
162                 {
163                     if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
164                     {
165                         win32::SetEvent(get_event());
166                     }
167                 }
168             }
169
170         private:
171             void* get_event()
172             {
173                 void* current_event=::boost::detail::interlocked_read_acquire(&event);
174
175                 if(!current_event)
176                 {
177                     void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
178 #ifdef BOOST_MSVC
179 #pragma warning(push)
180 #pragma warning(disable:4311)
181 #pragma warning(disable:4312)
182 #endif
183                     void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
184 #ifdef BOOST_MSVC
185 #pragma warning(pop)
186 #endif
187                     if(old_event!=0)
188                     {
189                         win32::CloseHandle(new_event);
190                         return old_event;
191                     }
192                     else
193                     {
194                         return new_event;
195                     }
196                 }
197                 return current_event;
198             }
199
200         };
201
202     }
203 }
204
205 #define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
206
207 #include <boost/config/abi_suffix.hpp>
208
209 #endif