File indexing completed on 2025-02-22 10:29:21
0001 #ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
0002 #define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/assert.hpp>
0012 #include <boost/bind/bind.hpp>
0013 #include <boost/static_assert.hpp>
0014 #include <boost/thread/mutex.hpp>
0015 #include <boost/thread/condition_variable.hpp>
0016 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0017 #include <boost/thread/detail/thread_interruption.hpp>
0018 #endif
0019 #ifdef BOOST_THREAD_USES_CHRONO
0020 #include <boost/chrono/system_clocks.hpp>
0021 #include <boost/chrono/ceil.hpp>
0022 #endif
0023 #include <boost/thread/detail/delete.hpp>
0024
0025 #include <boost/config/abi_prefix.hpp>
0026
0027 namespace boost
0028 {
0029 class shared_mutex
0030 {
0031 private:
0032 class state_data
0033 {
0034 public:
0035 state_data () :
0036 shared_count(0),
0037 exclusive(false),
0038 upgrade(false),
0039 exclusive_waiting_blocked(false)
0040 {}
0041
0042 void assert_free() const
0043 {
0044 BOOST_ASSERT( ! exclusive );
0045 BOOST_ASSERT( ! upgrade );
0046 BOOST_ASSERT( shared_count==0 );
0047 }
0048
0049 void assert_locked() const
0050 {
0051 BOOST_ASSERT( exclusive );
0052 BOOST_ASSERT( shared_count==0 );
0053 BOOST_ASSERT( ! upgrade );
0054 }
0055
0056 void assert_lock_shared () const
0057 {
0058 BOOST_ASSERT( ! exclusive );
0059 BOOST_ASSERT( shared_count>0 );
0060
0061
0062
0063 }
0064
0065 void assert_lock_upgraded () const
0066 {
0067 BOOST_ASSERT( ! exclusive );
0068 BOOST_ASSERT( upgrade );
0069 BOOST_ASSERT( shared_count>0 );
0070 }
0071
0072 void assert_lock_not_upgraded () const
0073 {
0074 BOOST_ASSERT( ! upgrade );
0075 }
0076
0077 bool can_lock () const
0078 {
0079 return ! (shared_count || exclusive);
0080 }
0081
0082 void lock ()
0083 {
0084 exclusive = true;
0085 }
0086
0087 void unlock ()
0088 {
0089 exclusive = false;
0090 exclusive_waiting_blocked = false;
0091 }
0092
0093 bool can_lock_shared () const
0094 {
0095 return ! (exclusive || exclusive_waiting_blocked);
0096 }
0097
0098 bool no_shared () const
0099 {
0100 return shared_count==0;
0101 }
0102
0103 bool one_shared () const
0104 {
0105 return shared_count==1;
0106 }
0107
0108 void lock_shared ()
0109 {
0110 ++shared_count;
0111 }
0112
0113
0114 void unlock_shared ()
0115 {
0116 --shared_count;
0117 }
0118
0119 void lock_upgrade ()
0120 {
0121 ++shared_count;
0122 upgrade=true;
0123 }
0124 bool can_lock_upgrade () const
0125 {
0126 return ! (exclusive || exclusive_waiting_blocked || upgrade);
0127 }
0128
0129 void unlock_upgrade ()
0130 {
0131 upgrade=false;
0132 --shared_count;
0133 }
0134
0135
0136 unsigned shared_count;
0137 bool exclusive;
0138 bool upgrade;
0139 bool exclusive_waiting_blocked;
0140 };
0141
0142
0143
0144 state_data state;
0145 boost::mutex state_change;
0146 boost::condition_variable shared_cond;
0147 boost::condition_variable exclusive_cond;
0148 boost::condition_variable upgrade_cond;
0149
0150 void release_waiters()
0151 {
0152 exclusive_cond.notify_one();
0153 shared_cond.notify_all();
0154 }
0155
0156 public:
0157
0158 BOOST_THREAD_NO_COPYABLE(shared_mutex)
0159
0160 shared_mutex()
0161 {
0162 }
0163
0164 ~shared_mutex()
0165 {
0166 }
0167
0168 void lock_shared()
0169 {
0170 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0171 boost::this_thread::disable_interruption do_not_disturb;
0172 #endif
0173 boost::unique_lock<boost::mutex> lk(state_change);
0174 shared_cond.wait(lk, boost::bind(&state_data::can_lock_shared, boost::ref(state)));
0175 state.lock_shared();
0176 }
0177
0178 bool try_lock_shared()
0179 {
0180 boost::unique_lock<boost::mutex> lk(state_change);
0181
0182 if(!state.can_lock_shared())
0183 {
0184 return false;
0185 }
0186 state.lock_shared();
0187 return true;
0188 }
0189
0190 #if defined BOOST_THREAD_USES_DATETIME
0191 bool timed_lock_shared(system_time const& timeout)
0192 {
0193 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0194 boost::this_thread::disable_interruption do_not_disturb;
0195 #endif
0196 boost::unique_lock<boost::mutex> lk(state_change);
0197 if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0198 {
0199 return false;
0200 }
0201 state.lock_shared();
0202 return true;
0203 }
0204
0205 template<typename TimeDuration>
0206 bool timed_lock_shared(TimeDuration const & relative_time)
0207 {
0208 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0209 boost::this_thread::disable_interruption do_not_disturb;
0210 #endif
0211 boost::unique_lock<boost::mutex> lk(state_change);
0212 if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0213 {
0214 return false;
0215 }
0216 state.lock_shared();
0217 return true;
0218 }
0219 #endif
0220 #ifdef BOOST_THREAD_USES_CHRONO
0221 template <class Rep, class Period>
0222 bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
0223 {
0224 return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
0225 }
0226 template <class Clock, class Duration>
0227 bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
0228 {
0229 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0230 boost::this_thread::disable_interruption do_not_disturb;
0231 #endif
0232 boost::unique_lock<boost::mutex> lk(state_change);
0233 if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_shared, boost::ref(state))))
0234 {
0235 return false;
0236 }
0237 state.lock_shared();
0238 return true;
0239 }
0240 #endif
0241 void unlock_shared()
0242 {
0243 boost::unique_lock<boost::mutex> lk(state_change);
0244 state.assert_lock_shared();
0245 state.unlock_shared();
0246 if (state.no_shared())
0247 {
0248 if (state.upgrade)
0249 {
0250
0251
0252 state.upgrade=false;
0253 state.exclusive=true;
0254
0255 upgrade_cond.notify_one();
0256 }
0257 else
0258 {
0259 state.exclusive_waiting_blocked=false;
0260
0261 }
0262 release_waiters();
0263 }
0264 }
0265
0266 void lock()
0267 {
0268 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0269 boost::this_thread::disable_interruption do_not_disturb;
0270 #endif
0271 boost::unique_lock<boost::mutex> lk(state_change);
0272 state.exclusive_waiting_blocked=true;
0273 exclusive_cond.wait(lk, boost::bind(&state_data::can_lock, boost::ref(state)));
0274 state.exclusive=true;
0275 }
0276
0277 #if defined BOOST_THREAD_USES_DATETIME
0278 bool timed_lock(system_time const& timeout)
0279 {
0280 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0281 boost::this_thread::disable_interruption do_not_disturb;
0282 #endif
0283 boost::unique_lock<boost::mutex> lk(state_change);
0284 state.exclusive_waiting_blocked=true;
0285 if(!exclusive_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock, boost::ref(state))))
0286 {
0287 state.exclusive_waiting_blocked=false;
0288 release_waiters();
0289 return false;
0290 }
0291 state.exclusive=true;
0292 return true;
0293 }
0294
0295 template<typename TimeDuration>
0296 bool timed_lock(TimeDuration const & relative_time)
0297 {
0298 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0299 boost::this_thread::disable_interruption do_not_disturb;
0300 #endif
0301 boost::unique_lock<boost::mutex> lk(state_change);
0302 state.exclusive_waiting_blocked=true;
0303 if(!exclusive_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock, boost::ref(state))))
0304 {
0305 state.exclusive_waiting_blocked=false;
0306 release_waiters();
0307 return false;
0308 }
0309 state.exclusive=true;
0310 return true;
0311 }
0312 #endif
0313 #ifdef BOOST_THREAD_USES_CHRONO
0314 template <class Rep, class Period>
0315 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
0316 {
0317 return try_lock_until(chrono::steady_clock::now() + rel_time);
0318 }
0319 template <class Clock, class Duration>
0320 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
0321 {
0322 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0323 boost::this_thread::disable_interruption do_not_disturb;
0324 #endif
0325 boost::unique_lock<boost::mutex> lk(state_change);
0326 state.exclusive_waiting_blocked=true;
0327 if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock, boost::ref(state))))
0328 {
0329 state.exclusive_waiting_blocked=false;
0330 release_waiters();
0331 return false;
0332 }
0333 state.exclusive=true;
0334 return true;
0335 }
0336 #endif
0337
0338 bool try_lock()
0339 {
0340 boost::unique_lock<boost::mutex> lk(state_change);
0341 if(!state.can_lock())
0342 {
0343 return false;
0344 }
0345 state.exclusive=true;
0346 return true;
0347 }
0348
0349 void unlock()
0350 {
0351 boost::unique_lock<boost::mutex> lk(state_change);
0352 state.assert_locked();
0353 state.exclusive=false;
0354 state.exclusive_waiting_blocked=false;
0355 state.assert_free();
0356 release_waiters();
0357 }
0358
0359 void lock_upgrade()
0360 {
0361 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0362 boost::this_thread::disable_interruption do_not_disturb;
0363 #endif
0364 boost::unique_lock<boost::mutex> lk(state_change);
0365 shared_cond.wait(lk, boost::bind(&state_data::can_lock_upgrade, boost::ref(state)));
0366 state.lock_shared();
0367 state.upgrade=true;
0368 }
0369
0370 #if defined BOOST_THREAD_USES_DATETIME
0371 bool timed_lock_upgrade(system_time const& timeout)
0372 {
0373 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0374 boost::this_thread::disable_interruption do_not_disturb;
0375 #endif
0376 boost::unique_lock<boost::mutex> lk(state_change);
0377 if(!shared_cond.timed_wait(lk, timeout, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0378 {
0379 return false;
0380 }
0381 state.lock_shared();
0382 state.upgrade=true;
0383 return true;
0384 }
0385
0386 template<typename TimeDuration>
0387 bool timed_lock_upgrade(TimeDuration const & relative_time)
0388 {
0389 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0390 boost::this_thread::disable_interruption do_not_disturb;
0391 #endif
0392 boost::unique_lock<boost::mutex> lk(state_change);
0393 if(!shared_cond.timed_wait(lk, relative_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0394 {
0395 return false;
0396 }
0397 state.lock_shared();
0398 state.upgrade=true;
0399 return true;
0400 }
0401 #endif
0402 #ifdef BOOST_THREAD_USES_CHRONO
0403 template <class Rep, class Period>
0404 bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time)
0405 {
0406 return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
0407 }
0408 template <class Clock, class Duration>
0409 bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
0410 {
0411 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0412 boost::this_thread::disable_interruption do_not_disturb;
0413 #endif
0414 boost::unique_lock<boost::mutex> lk(state_change);
0415 if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0416 {
0417 return false;
0418 }
0419 state.lock_shared();
0420 state.upgrade=true;
0421 return true;
0422 }
0423 #endif
0424 bool try_lock_upgrade()
0425 {
0426 boost::unique_lock<boost::mutex> lk(state_change);
0427 if(!state.can_lock_upgrade())
0428 {
0429 return false;
0430 }
0431 state.lock_shared();
0432 state.upgrade=true;
0433 state.assert_lock_upgraded();
0434 return true;
0435 }
0436
0437 void unlock_upgrade()
0438 {
0439 boost::unique_lock<boost::mutex> lk(state_change);
0440
0441 state.unlock_upgrade();
0442 if(state.no_shared())
0443 {
0444 state.exclusive_waiting_blocked=false;
0445 release_waiters();
0446 } else {
0447 shared_cond.notify_all();
0448 }
0449 }
0450
0451
0452 void unlock_upgrade_and_lock()
0453 {
0454 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0455 boost::this_thread::disable_interruption do_not_disturb;
0456 #endif
0457 boost::unique_lock<boost::mutex> lk(state_change);
0458 state.assert_lock_upgraded();
0459 state.unlock_shared();
0460 upgrade_cond.wait(lk, boost::bind(&state_data::no_shared, boost::ref(state)));
0461 state.upgrade=false;
0462 state.exclusive=true;
0463 state.assert_locked();
0464 }
0465
0466 void unlock_and_lock_upgrade()
0467 {
0468 boost::unique_lock<boost::mutex> lk(state_change);
0469 state.assert_locked();
0470 state.exclusive=false;
0471 state.upgrade=true;
0472 state.lock_shared();
0473 state.exclusive_waiting_blocked=false;
0474 state.assert_lock_upgraded();
0475 release_waiters();
0476 }
0477
0478 bool try_unlock_upgrade_and_lock()
0479 {
0480 boost::unique_lock<boost::mutex> lk(state_change);
0481 state.assert_lock_upgraded();
0482 if( !state.exclusive
0483 && !state.exclusive_waiting_blocked
0484 && state.upgrade
0485 && state.shared_count==1)
0486 {
0487 state.shared_count=0;
0488 state.exclusive=true;
0489 state.upgrade=false;
0490 state.assert_locked();
0491 return true;
0492 }
0493 return false;
0494 }
0495 #ifdef BOOST_THREAD_USES_CHRONO
0496 template <class Rep, class Period>
0497 bool
0498 try_unlock_upgrade_and_lock_for(
0499 const chrono::duration<Rep, Period>& rel_time)
0500 {
0501 return try_unlock_upgrade_and_lock_until(
0502 chrono::steady_clock::now() + rel_time);
0503 }
0504 template <class Clock, class Duration>
0505 bool
0506 try_unlock_upgrade_and_lock_until(
0507 const chrono::time_point<Clock, Duration>& abs_time)
0508 {
0509 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0510 boost::this_thread::disable_interruption do_not_disturb;
0511 #endif
0512 boost::unique_lock<boost::mutex> lk(state_change);
0513 state.assert_lock_upgraded();
0514 if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
0515 {
0516 return false;
0517 }
0518 state.upgrade=false;
0519 state.exclusive=true;
0520 state.exclusive_waiting_blocked=false;
0521 state.shared_count=0;
0522 return true;
0523 }
0524 #endif
0525
0526
0527 void unlock_and_lock_shared()
0528 {
0529 boost::unique_lock<boost::mutex> lk(state_change);
0530 state.assert_locked();
0531 state.exclusive=false;
0532 state.lock_shared();
0533 state.exclusive_waiting_blocked=false;
0534 release_waiters();
0535 }
0536
0537 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0538 bool try_unlock_shared_and_lock()
0539 {
0540 boost::unique_lock<boost::mutex> lk(state_change);
0541 state.assert_lock_shared();
0542 if( !state.exclusive
0543 && !state.exclusive_waiting_blocked
0544 && !state.upgrade
0545 && state.shared_count==1)
0546 {
0547 state.shared_count=0;
0548 state.exclusive=true;
0549 return true;
0550 }
0551 return false;
0552 }
0553 #ifdef BOOST_THREAD_USES_CHRONO
0554 template <class Rep, class Period>
0555 bool
0556 try_unlock_shared_and_lock_for(
0557 const chrono::duration<Rep, Period>& rel_time)
0558 {
0559 return try_unlock_shared_and_lock_until(
0560 chrono::steady_clock::now() + rel_time);
0561 }
0562 template <class Clock, class Duration>
0563 bool
0564 try_unlock_shared_and_lock_until(
0565 const chrono::time_point<Clock, Duration>& abs_time)
0566 {
0567 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0568 boost::this_thread::disable_interruption do_not_disturb;
0569 #endif
0570 boost::unique_lock<boost::mutex> lk(state_change);
0571 state.assert_lock_shared();
0572 if(!shared_cond.wait_until(lk, abs_time, boost::bind(&state_data::one_shared, boost::ref(state))))
0573 {
0574 return false;
0575 }
0576 state.upgrade=false;
0577 state.exclusive=true;
0578 state.exclusive_waiting_blocked=false;
0579 state.shared_count=0;
0580 return true;
0581 }
0582 #endif
0583 #endif
0584
0585
0586 void unlock_upgrade_and_lock_shared()
0587 {
0588 boost::unique_lock<boost::mutex> lk(state_change);
0589 state.assert_lock_upgraded();
0590 state.upgrade=false;
0591 state.exclusive_waiting_blocked=false;
0592 release_waiters();
0593 }
0594
0595 #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
0596 bool try_unlock_shared_and_lock_upgrade()
0597 {
0598 boost::unique_lock<boost::mutex> lk(state_change);
0599 state.assert_lock_shared();
0600 if(state.can_lock_upgrade())
0601 {
0602 state.upgrade=true;
0603 return true;
0604 }
0605 return false;
0606 }
0607 #ifdef BOOST_THREAD_USES_CHRONO
0608 template <class Rep, class Period>
0609 bool
0610 try_unlock_shared_and_lock_upgrade_for(
0611 const chrono::duration<Rep, Period>& rel_time)
0612 {
0613 return try_unlock_shared_and_lock_upgrade_until(
0614 chrono::steady_clock::now() + rel_time);
0615 }
0616 template <class Clock, class Duration>
0617 bool
0618 try_unlock_shared_and_lock_upgrade_until(
0619 const chrono::time_point<Clock, Duration>& abs_time)
0620 {
0621 #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
0622 boost::this_thread::disable_interruption do_not_disturb;
0623 #endif
0624 boost::unique_lock<boost::mutex> lk(state_change);
0625 state.assert_lock_shared();
0626 if(!exclusive_cond.wait_until(lk, abs_time, boost::bind(&state_data::can_lock_upgrade, boost::ref(state))))
0627 {
0628 return false;
0629 }
0630 state.upgrade=true;
0631 return true;
0632 }
0633 #endif
0634 #endif
0635 };
0636
0637 typedef shared_mutex upgrade_mutex;
0638 }
0639
0640 #include <boost/config/abi_suffix.hpp>
0641
0642 #endif