1 #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
2 #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
4 // (C) Copyright 2006-8 Anthony Williams
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 #include <boost/assert.hpp>
11 #include <boost/detail/interlocked.hpp>
12 #include <boost/thread/win32/thread_primitives.hpp>
13 #include <boost/static_assert.hpp>
15 #include <boost/utility.hpp>
16 #include <boost/thread/thread_time.hpp>
18 #include <boost/config/abi_prefix.hpp>
23 private boost::noncopyable
28 unsigned shared_count
:11,
33 exclusive_waiting_blocked
:1;
35 friend bool operator==(state_data
const& lhs
,state_data
const& rhs
)
37 return *reinterpret_cast<unsigned const*>(&lhs
)==*reinterpret_cast<unsigned const*>(&rhs
);
43 T
interlocked_compare_exchange(T
* target
,T new_value
,T comparand
)
45 BOOST_STATIC_ASSERT(sizeof(T
)==sizeof(long));
46 long const res
=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target
),
47 *reinterpret_cast<long*>(&new_value
),
48 *reinterpret_cast<long*>(&comparand
));
49 return *reinterpret_cast<T
const*>(&res
);
53 detail::win32::handle semaphores
[2];
54 detail::win32::handle
&unlock_sem
;
55 detail::win32::handle
&exclusive_sem
;
56 detail::win32::handle upgrade_sem
;
58 void release_waiters(state_data old_state
)
60 if(old_state
.exclusive_waiting
)
62 BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem
,1,0)!=0);
65 if(old_state
.shared_waiting
|| old_state
.exclusive_waiting
)
67 BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem
,old_state
.shared_waiting
+ (old_state
.exclusive_waiting
?1:0),0)!=0);
74 unlock_sem(semaphores
[0]),
75 exclusive_sem(semaphores
[1])
77 unlock_sem
=detail::win32::create_anonymous_semaphore(0,LONG_MAX
);
78 exclusive_sem
=detail::win32::create_anonymous_semaphore(0,LONG_MAX
);
79 upgrade_sem
=detail::win32::create_anonymous_semaphore(0,LONG_MAX
);
80 state_data state_
={0};
86 detail::win32::CloseHandle(upgrade_sem
);
87 detail::win32::CloseHandle(unlock_sem
);
88 detail::win32::CloseHandle(exclusive_sem
);
91 bool try_lock_shared()
93 state_data old_state
=state
;
96 state_data new_state
=old_state
;
97 if(!new_state
.exclusive
&& !new_state
.exclusive_waiting_blocked
)
99 ++new_state
.shared_count
;
102 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
103 if(current_state
==old_state
)
107 old_state
=current_state
;
109 return !(old_state
.exclusive
| old_state
.exclusive_waiting_blocked
);
114 BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
117 template<typename TimeDuration
>
118 bool timed_lock_shared(TimeDuration
const & relative_time
)
120 return timed_lock_shared(get_system_time()+relative_time
);
123 bool timed_lock_shared(boost::system_time
const& wait_until
)
127 state_data old_state
=state
;
130 state_data new_state
=old_state
;
131 if(new_state
.exclusive
|| new_state
.exclusive_waiting_blocked
)
133 ++new_state
.shared_waiting
;
137 ++new_state
.shared_count
;
140 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
141 if(current_state
==old_state
)
145 old_state
=current_state
;
148 if(!(old_state
.exclusive
| old_state
.exclusive_waiting_blocked
))
153 unsigned long const res
=detail::win32::WaitForSingleObject(unlock_sem
,::boost::detail::get_milliseconds_until(wait_until
));
154 if(res
==detail::win32::timeout
)
158 state_data new_state
=old_state
;
159 if(new_state
.exclusive
|| new_state
.exclusive_waiting_blocked
)
161 if(new_state
.shared_waiting
)
163 --new_state
.shared_waiting
;
168 ++new_state
.shared_count
;
171 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
172 if(current_state
==old_state
)
176 old_state
=current_state
;
179 if(!(old_state
.exclusive
| old_state
.exclusive_waiting_blocked
))
186 BOOST_ASSERT(res
==0);
192 state_data old_state
=state
;
195 state_data new_state
=old_state
;
196 bool const last_reader
=!--new_state
.shared_count
;
200 if(new_state
.upgrade
)
202 new_state
.upgrade
=false;
203 new_state
.exclusive
=true;
207 if(new_state
.exclusive_waiting
)
209 --new_state
.exclusive_waiting
;
210 new_state
.exclusive_waiting_blocked
=false;
212 new_state
.shared_waiting
=0;
216 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
217 if(current_state
==old_state
)
221 if(old_state
.upgrade
)
223 BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem
,1,0)!=0);
227 release_waiters(old_state
);
232 old_state
=current_state
;
238 BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
241 template<typename TimeDuration
>
242 bool timed_lock(TimeDuration
const & relative_time
)
244 return timed_lock(get_system_time()+relative_time
);
249 state_data old_state
=state
;
252 state_data new_state
=old_state
;
253 if(new_state
.shared_count
|| new_state
.exclusive
)
259 new_state
.exclusive
=true;
262 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
263 if(current_state
==old_state
)
267 old_state
=current_state
;
273 bool timed_lock(boost::system_time
const& wait_until
)
277 state_data old_state
=state
;
281 state_data new_state
=old_state
;
282 if(new_state
.shared_count
|| new_state
.exclusive
)
284 ++new_state
.exclusive_waiting
;
285 new_state
.exclusive_waiting_blocked
=true;
289 new_state
.exclusive
=true;
292 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
293 if(current_state
==old_state
)
297 old_state
=current_state
;
300 if(!old_state
.shared_count
&& !old_state
.exclusive
)
304 unsigned long const wait_res
=detail::win32::WaitForMultipleObjects(2,semaphores
,true,::boost::detail::get_milliseconds_until(wait_until
));
305 if(wait_res
==detail::win32::timeout
)
309 state_data new_state
=old_state
;
310 if(new_state
.shared_count
|| new_state
.exclusive
)
312 if(new_state
.exclusive_waiting
)
314 if(!--new_state
.exclusive_waiting
)
316 new_state
.exclusive_waiting_blocked
=false;
322 new_state
.exclusive
=true;
325 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
326 if(current_state
==old_state
)
330 old_state
=current_state
;
332 if(!old_state
.shared_count
&& !old_state
.exclusive
)
338 BOOST_ASSERT(wait_res
<2);
344 state_data old_state
=state
;
347 state_data new_state
=old_state
;
348 new_state
.exclusive
=false;
349 if(new_state
.exclusive_waiting
)
351 --new_state
.exclusive_waiting
;
352 new_state
.exclusive_waiting_blocked
=false;
354 new_state
.shared_waiting
=0;
356 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
357 if(current_state
==old_state
)
361 old_state
=current_state
;
363 release_waiters(old_state
);
370 state_data old_state
=state
;
373 state_data new_state
=old_state
;
374 if(new_state
.exclusive
|| new_state
.exclusive_waiting_blocked
|| new_state
.upgrade
)
376 ++new_state
.shared_waiting
;
380 ++new_state
.shared_count
;
381 new_state
.upgrade
=true;
384 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
385 if(current_state
==old_state
)
389 old_state
=current_state
;
392 if(!(old_state
.exclusive
|| old_state
.exclusive_waiting_blocked
|| old_state
.upgrade
))
397 BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem
,detail::win32::infinite
));
401 bool try_lock_upgrade()
403 state_data old_state
=state
;
406 state_data new_state
=old_state
;
407 if(new_state
.exclusive
|| new_state
.exclusive_waiting_blocked
|| new_state
.upgrade
)
413 ++new_state
.shared_count
;
414 new_state
.upgrade
=true;
417 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
418 if(current_state
==old_state
)
422 old_state
=current_state
;
427 void unlock_upgrade()
429 state_data old_state
=state
;
432 state_data new_state
=old_state
;
433 new_state
.upgrade
=false;
434 bool const last_reader
=!--new_state
.shared_count
;
438 if(new_state
.exclusive_waiting
)
440 --new_state
.exclusive_waiting
;
441 new_state
.exclusive_waiting_blocked
=false;
443 new_state
.shared_waiting
=0;
446 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
447 if(current_state
==old_state
)
451 release_waiters(old_state
);
455 old_state
=current_state
;
459 void unlock_upgrade_and_lock()
461 state_data old_state
=state
;
464 state_data new_state
=old_state
;
465 bool const last_reader
=!--new_state
.shared_count
;
469 new_state
.upgrade
=false;
470 new_state
.exclusive
=true;
473 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
474 if(current_state
==old_state
)
478 BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem
,detail::win32::infinite
));
482 old_state
=current_state
;
486 void unlock_and_lock_upgrade()
488 state_data old_state
=state
;
491 state_data new_state
=old_state
;
492 new_state
.exclusive
=false;
493 new_state
.upgrade
=true;
494 ++new_state
.shared_count
;
495 if(new_state
.exclusive_waiting
)
497 --new_state
.exclusive_waiting
;
498 new_state
.exclusive_waiting_blocked
=false;
500 new_state
.shared_waiting
=0;
502 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
503 if(current_state
==old_state
)
507 old_state
=current_state
;
509 release_waiters(old_state
);
512 void unlock_and_lock_shared()
514 state_data old_state
=state
;
517 state_data new_state
=old_state
;
518 new_state
.exclusive
=false;
519 ++new_state
.shared_count
;
520 if(new_state
.exclusive_waiting
)
522 --new_state
.exclusive_waiting
;
523 new_state
.exclusive_waiting_blocked
=false;
525 new_state
.shared_waiting
=0;
527 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
528 if(current_state
==old_state
)
532 old_state
=current_state
;
534 release_waiters(old_state
);
537 void unlock_upgrade_and_lock_shared()
539 state_data old_state
=state
;
542 state_data new_state
=old_state
;
543 new_state
.upgrade
=false;
544 if(new_state
.exclusive_waiting
)
546 --new_state
.exclusive_waiting
;
547 new_state
.exclusive_waiting_blocked
=false;
549 new_state
.shared_waiting
=0;
551 state_data
const current_state
=interlocked_compare_exchange(&state
,new_state
,old_state
);
552 if(current_state
==old_state
)
556 old_state
=current_state
;
558 release_waiters(old_state
);
564 #include <boost/config/abi_suffix.hpp>