00001 #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
00002 #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <boost/assert.hpp>
00016 #include <boost/detail/interlocked.hpp>
00017 #include <boost/thread/win32/thread_primitives.hpp>
00018 #include <boost/static_assert.hpp>
00019 #include <limits.h>
00020 #include <boost/utility.hpp>
00021 #include <boost/thread/thread_time.hpp>
00022
00023 #include <boost/config/abi_prefix.hpp>
00024
00025 namespace boost
00026 {
00027 class modified_shared_mutex:
00028 private boost::noncopyable
00029 {
00030 private:
00031 struct state_data
00032 {
00033 unsigned shared_count:11,
00034 shared_waiting:11,
00035 exclusive:1,
00036 upgrade:1,
00037 exclusive_waiting:7,
00038 exclusive_waiting_blocked:1;
00039
00040 friend bool operator==(state_data const& lhs,state_data const& rhs)
00041 {
00042 return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
00043 }
00044 };
00045
00046
00047 template<typename T>
00048 T interlocked_compare_exchange(T* target,T new_value,T comparand)
00049 {
00050 BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
00051 long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
00052 *reinterpret_cast<long*>(&new_value),
00053 *reinterpret_cast<long*>(&comparand));
00054 return *reinterpret_cast<T const*>(&res);
00055 }
00056
00057 state_data state;
00058 detail::win32::handle semaphores[2];
00059 detail::win32::handle &unlock_sem;
00060 detail::win32::handle &exclusive_sem;
00061 detail::win32::handle upgrade_sem;
00062
00063 void release_waiters(state_data old_state)
00064 {
00065 if(old_state.exclusive_waiting)
00066 {
00067 BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
00068 }
00069
00070 if(old_state.shared_waiting || old_state.exclusive_waiting)
00071 {
00072 BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
00073 }
00074 }
00075
00076
00077 public:
00078 modified_shared_mutex():
00079 unlock_sem(semaphores[0]),
00080 exclusive_sem(semaphores[1])
00081 {
00082 unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
00083 exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
00084 upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
00085 state_data state_={0};
00086 state=state_;
00087 }
00088
00089 ~modified_shared_mutex()
00090 {
00091 detail::win32::CloseHandle(upgrade_sem);
00092 detail::win32::CloseHandle(unlock_sem);
00093 detail::win32::CloseHandle(exclusive_sem);
00094 }
00095
00096 bool try_lock_shared()
00097 {
00098 state_data old_state=state;
00099 for(;;)
00100 {
00101 state_data new_state=old_state;
00102 if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
00103 {
00104 ++new_state.shared_count;
00105 }
00106
00107 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00108 if(current_state==old_state)
00109 {
00110 break;
00111 }
00112 old_state=current_state;
00113 }
00114 return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
00115 }
00116
00117 void lock_shared()
00118 {
00119 BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
00120 }
00121
00122 template<typename TimeDuration>
00123 bool timed_lock_shared(TimeDuration const & relative_time)
00124 {
00125 return timed_lock_shared(get_system_time()+relative_time);
00126 }
00127
00128 bool timed_lock_shared(boost::system_time const& wait_until)
00129 {
00130 for(;;)
00131 {
00132 state_data old_state=state;
00133 for(;;)
00134 {
00135 state_data new_state=old_state;
00136 if(new_state.exclusive || new_state.exclusive_waiting_blocked)
00137 {
00138 ++new_state.shared_waiting;
00139 }
00140 else
00141 {
00142 ++new_state.shared_count;
00143 }
00144
00145 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00146 if(current_state==old_state)
00147 {
00148 break;
00149 }
00150 old_state=current_state;
00151 }
00152
00153 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
00154 {
00155 return true;
00156 }
00157
00158 unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
00159 if(res==detail::win32::timeout)
00160 {
00161 for(;;)
00162 {
00163 state_data new_state=old_state;
00164 if(new_state.exclusive || new_state.exclusive_waiting_blocked)
00165 {
00166 if(new_state.shared_waiting)
00167 {
00168 --new_state.shared_waiting;
00169 }
00170 }
00171 else
00172 {
00173 ++new_state.shared_count;
00174 }
00175
00176 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00177 if(current_state==old_state)
00178 {
00179 break;
00180 }
00181 old_state=current_state;
00182 }
00183
00184 if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
00185 {
00186 return true;
00187 }
00188 return false;
00189 }
00190
00191 BOOST_ASSERT(res==0);
00192 }
00193 }
00194
00195 void unlock_shared()
00196 {
00197 state_data old_state=state;
00198 for(;;)
00199 {
00200 state_data new_state=old_state;
00201 bool const last_reader=!--new_state.shared_count;
00202
00203 if(last_reader)
00204 {
00205 if(new_state.upgrade)
00206 {
00207 new_state.upgrade=false;
00208 new_state.exclusive=true;
00209 }
00210 else
00211 {
00212 if(new_state.exclusive_waiting)
00213 {
00214 --new_state.exclusive_waiting;
00215 new_state.exclusive_waiting_blocked=false;
00216 }
00217 new_state.shared_waiting=0;
00218 }
00219 }
00220
00221 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00222 if(current_state==old_state)
00223 {
00224 if(last_reader)
00225 {
00226 if(old_state.upgrade)
00227 {
00228 BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
00229 }
00230 else
00231 {
00232 release_waiters(old_state);
00233 }
00234 }
00235 break;
00236 }
00237 old_state=current_state;
00238 }
00239 }
00240
00241 void lock()
00242 {
00243 BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
00244 }
00245
00246 template<typename TimeDuration>
00247 bool timed_lock(TimeDuration const & relative_time)
00248 {
00249 return timed_lock(get_system_time()+relative_time);
00250 }
00251
00252 bool try_lock()
00253 {
00254 state_data old_state=state;
00255 for(;;)
00256 {
00257 state_data new_state=old_state;
00258 if(new_state.shared_count || new_state.exclusive)
00259 {
00260 return false;
00261 }
00262 else
00263 {
00264 new_state.exclusive=true;
00265 }
00266
00267 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00268 if(current_state==old_state)
00269 {
00270 break;
00271 }
00272 old_state=current_state;
00273 }
00274 return true;
00275 }
00276
00277
00278 bool timed_lock(boost::system_time const& wait_until)
00279 {
00280 for(;;)
00281 {
00282 state_data old_state=state;
00283
00284 for(;;)
00285 {
00286 state_data new_state=old_state;
00287 if(new_state.shared_count || new_state.exclusive)
00288 {
00289 if( new_state.exclusive_waiting == 127 )
00290 break;
00291 ++new_state.exclusive_waiting;
00292 new_state.exclusive_waiting_blocked=true;
00293 }
00294 else
00295 {
00296 new_state.exclusive=true;
00297 }
00298
00299 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00300 if(current_state==old_state)
00301 {
00302 break;
00303 }
00304 old_state=current_state;
00305 }
00306
00307 if(!old_state.shared_count && !old_state.exclusive)
00308 {
00309 return true;
00310 }
00311 unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
00312 if(wait_res==detail::win32::timeout)
00313 {
00314 for(;;)
00315 {
00316 state_data new_state=old_state;
00317 if(new_state.shared_count || new_state.exclusive)
00318 {
00319 if(new_state.exclusive_waiting)
00320 {
00321 if(!--new_state.exclusive_waiting)
00322 {
00323 new_state.exclusive_waiting_blocked=false;
00324 }
00325 }
00326 }
00327 else
00328 {
00329 new_state.exclusive=true;
00330 }
00331
00332 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00333 if(current_state==old_state)
00334 {
00335 break;
00336 }
00337 old_state=current_state;
00338 }
00339 if(!old_state.shared_count && !old_state.exclusive)
00340 {
00341 return true;
00342 }
00343 return false;
00344 }
00345 BOOST_ASSERT(wait_res<2);
00346 }
00347 }
00348
00349 void unlock()
00350 {
00351 state_data old_state=state;
00352 for(;;)
00353 {
00354 state_data new_state=old_state;
00355 new_state.exclusive=false;
00356 if(new_state.exclusive_waiting)
00357 {
00358 --new_state.exclusive_waiting;
00359 new_state.exclusive_waiting_blocked=false;
00360 }
00361 new_state.shared_waiting=0;
00362
00363 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00364 if(current_state==old_state)
00365 {
00366 break;
00367 }
00368 old_state=current_state;
00369 }
00370 release_waiters(old_state);
00371 }
00372
00373 void lock_upgrade()
00374 {
00375 for(;;)
00376 {
00377 state_data old_state=state;
00378 for(;;)
00379 {
00380 state_data new_state=old_state;
00381 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
00382 {
00383 ++new_state.shared_waiting;
00384 }
00385 else
00386 {
00387 ++new_state.shared_count;
00388 new_state.upgrade=true;
00389 }
00390
00391 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00392 if(current_state==old_state)
00393 {
00394 break;
00395 }
00396 old_state=current_state;
00397 }
00398
00399 if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
00400 {
00401 return;
00402 }
00403
00404 BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
00405 }
00406 }
00407
00408 bool try_lock_upgrade()
00409 {
00410 state_data old_state=state;
00411 for(;;)
00412 {
00413 state_data new_state=old_state;
00414 if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
00415 {
00416 return false;
00417 }
00418 else
00419 {
00420 ++new_state.shared_count;
00421 new_state.upgrade=true;
00422 }
00423
00424 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00425 if(current_state==old_state)
00426 {
00427 break;
00428 }
00429 old_state=current_state;
00430 }
00431 return true;
00432 }
00433
00434 void unlock_upgrade()
00435 {
00436 state_data old_state=state;
00437 for(;;)
00438 {
00439 state_data new_state=old_state;
00440 new_state.upgrade=false;
00441 bool const last_reader=!--new_state.shared_count;
00442
00443 if(last_reader)
00444 {
00445 if(new_state.exclusive_waiting)
00446 {
00447 --new_state.exclusive_waiting;
00448 new_state.exclusive_waiting_blocked=false;
00449 }
00450 new_state.shared_waiting=0;
00451 }
00452
00453 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00454 if(current_state==old_state)
00455 {
00456 if(last_reader)
00457 {
00458 release_waiters(old_state);
00459 }
00460 break;
00461 }
00462 old_state=current_state;
00463 }
00464 }
00465
00466 void unlock_upgrade_and_lock()
00467 {
00468 state_data old_state=state;
00469 for(;;)
00470 {
00471 state_data new_state=old_state;
00472 bool const last_reader=!--new_state.shared_count;
00473
00474 if(last_reader)
00475 {
00476 new_state.upgrade=false;
00477 new_state.exclusive=true;
00478 }
00479
00480 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00481 if(current_state==old_state)
00482 {
00483 if(!last_reader)
00484 {
00485 BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
00486 }
00487 break;
00488 }
00489 old_state=current_state;
00490 }
00491 }
00492
00493 void unlock_and_lock_upgrade()
00494 {
00495 state_data old_state=state;
00496 for(;;)
00497 {
00498 state_data new_state=old_state;
00499 new_state.exclusive=false;
00500 new_state.upgrade=true;
00501 ++new_state.shared_count;
00502 if(new_state.exclusive_waiting)
00503 {
00504 --new_state.exclusive_waiting;
00505 new_state.exclusive_waiting_blocked=false;
00506 }
00507 new_state.shared_waiting=0;
00508
00509 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00510 if(current_state==old_state)
00511 {
00512 break;
00513 }
00514 old_state=current_state;
00515 }
00516 release_waiters(old_state);
00517 }
00518
00519 void unlock_and_lock_shared()
00520 {
00521 state_data old_state=state;
00522 for(;;)
00523 {
00524 state_data new_state=old_state;
00525 new_state.exclusive=false;
00526 ++new_state.shared_count;
00527 if(new_state.exclusive_waiting)
00528 {
00529 --new_state.exclusive_waiting;
00530 new_state.exclusive_waiting_blocked=false;
00531 }
00532 new_state.shared_waiting=0;
00533
00534 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00535 if(current_state==old_state)
00536 {
00537 break;
00538 }
00539 old_state=current_state;
00540 }
00541 release_waiters(old_state);
00542 }
00543
00544 void unlock_upgrade_and_lock_shared()
00545 {
00546 state_data old_state=state;
00547 for(;;)
00548 {
00549 state_data new_state=old_state;
00550 new_state.upgrade=false;
00551 if(new_state.exclusive_waiting)
00552 {
00553 --new_state.exclusive_waiting;
00554 new_state.exclusive_waiting_blocked=false;
00555 }
00556 new_state.shared_waiting=0;
00557
00558 state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
00559 if(current_state==old_state)
00560 {
00561 break;
00562 }
00563 old_state=current_state;
00564 }
00565 release_waiters(old_state);
00566 }
00567
00568 };
00569 }
00570
00571 #include <boost/config/abi_suffix.hpp>
00572
00573 #endif