File indexing completed on 2025-07-11 08:13:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
0014 #define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
0015
0016 #ifndef BOOST_CONFIG_HPP
0017 # include <boost/config.hpp>
0018 #endif
0019 #
0020 #if defined(BOOST_HAS_PRAGMA_ONCE)
0021 # pragma once
0022 #endif
0023
0024 #include <boost/interprocess/detail/config_begin.hpp>
0025 #include <boost/interprocess/detail/workaround.hpp>
0026 #include <boost/interprocess/sync/scoped_lock.hpp>
0027 #include <boost/interprocess/timed_utils.hpp>
0028 #include <boost/interprocess/sync/interprocess_mutex.hpp>
0029 #include <boost/interprocess/sync/interprocess_condition.hpp>
0030 #include <climits>
0031
0032
0033
0034
0035
0036 namespace boost {
0037 namespace interprocess {
0038
0039
0040
0041 class interprocess_upgradable_mutex
0042 {
0043
0044 interprocess_upgradable_mutex(const interprocess_upgradable_mutex &);
0045 interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &);
0046
0047 friend class interprocess_condition;
0048 public:
0049
0050
0051
0052 interprocess_upgradable_mutex();
0053
0054
0055
0056 ~interprocess_upgradable_mutex();
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 void lock();
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 bool try_lock();
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 template<class TimePoint>
0098 bool timed_lock(const TimePoint &abs_time);
0099
0100
0101
0102 template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
0103 { return this->timed_lock(abs_time); }
0104
0105
0106
0107 template<class Duration> bool try_lock_for(const Duration &dur)
0108 { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
0109
0110
0111
0112
0113
0114 void unlock();
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 void lock_sharable();
0129
0130
0131
0132 void lock_shared()
0133 { this->lock_sharable(); }
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 bool try_lock_sharable();
0148
0149
0150
0151 bool try_lock_shared()
0152 { return this->try_lock_sharable(); }
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 template<class TimePoint>
0166 bool timed_lock_sharable(const TimePoint &abs_time);
0167
0168
0169
0170 template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
0171 { return this->timed_lock_sharable(abs_time); }
0172
0173
0174
0175 template<class Duration> bool try_lock_shared_for(const Duration &dur)
0176 { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
0177
0178
0179
0180
0181 void unlock_sharable();
0182
0183
0184
0185 void unlock_shared()
0186 { this->unlock_sharable(); }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 void lock_upgradable();
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 bool try_lock_upgradable();
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227 template<class TimePoint>
0228 bool timed_lock_upgradable(const TimePoint &abs_time);
0229
0230
0231
0232
0233 void unlock_upgradable();
0234
0235
0236
0237
0238
0239
0240
0241 void unlock_and_lock_upgradable();
0242
0243
0244
0245
0246
0247 void unlock_and_lock_sharable();
0248
0249
0250
0251
0252
0253 void unlock_upgradable_and_lock_sharable();
0254
0255
0256
0257
0258
0259
0260
0261
0262 void unlock_upgradable_and_lock();
0263
0264
0265
0266
0267
0268
0269
0270 bool try_unlock_upgradable_and_lock();
0271
0272
0273
0274
0275
0276
0277
0278
0279 template<class TimePoint>
0280 bool timed_unlock_upgradable_and_lock(const TimePoint &abs_time);
0281
0282
0283
0284
0285
0286
0287
0288 bool try_unlock_sharable_and_lock();
0289
0290
0291
0292
0293
0294
0295
0296 bool try_unlock_sharable_and_lock_upgradable();
0297
0298 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0299 private:
0300 typedef scoped_lock<interprocess_mutex> scoped_lock_t;
0301
0302
0303
0304 struct control_word_t
0305 {
0306 unsigned exclusive_in : 1;
0307 unsigned upgradable_in : 1;
0308 unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2;
0309 } m_ctrl;
0310
0311 interprocess_mutex m_mut;
0312 interprocess_condition m_first_gate;
0313 interprocess_condition m_second_gate;
0314
0315 private:
0316
0317 struct exclusive_rollback
0318 {
0319 exclusive_rollback(control_word_t &ctrl
0320 ,interprocess_condition &first_gate)
0321 : mp_ctrl(&ctrl), m_first_gate(first_gate)
0322 {}
0323
0324 void release()
0325 { mp_ctrl = 0; }
0326
0327 ~exclusive_rollback()
0328 {
0329 if(mp_ctrl){
0330 mp_ctrl->exclusive_in = 0;
0331 m_first_gate.notify_all();
0332 }
0333 }
0334 control_word_t *mp_ctrl;
0335 interprocess_condition &m_first_gate;
0336 };
0337
0338 struct upgradable_to_exclusive_rollback
0339 {
0340 upgradable_to_exclusive_rollback(control_word_t &ctrl)
0341 : mp_ctrl(&ctrl)
0342 {}
0343
0344 void release()
0345 { mp_ctrl = 0; }
0346
0347 ~upgradable_to_exclusive_rollback()
0348 {
0349 if(mp_ctrl){
0350
0351 mp_ctrl->upgradable_in = 1;
0352 ++mp_ctrl->num_upr_shar;
0353
0354 mp_ctrl->exclusive_in = 0;
0355 }
0356 }
0357 control_word_t *mp_ctrl;
0358 };
0359
0360 template<int Dummy>
0361 struct base_constants_t
0362 {
0363 static const unsigned max_readers
0364 = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
0365 };
0366 typedef base_constants_t<0> constants;
0367 #endif
0368 };
0369
0370 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0371
0372 template <int Dummy>
0373 const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
0374
0375 inline interprocess_upgradable_mutex::interprocess_upgradable_mutex()
0376 {
0377 this->m_ctrl.exclusive_in = 0;
0378 this->m_ctrl.upgradable_in = 0;
0379 this->m_ctrl.num_upr_shar = 0;
0380 }
0381
0382 inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
0383 {}
0384
0385 inline void interprocess_upgradable_mutex::lock()
0386 {
0387 scoped_lock_t lck(m_mut);
0388
0389
0390
0391 while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
0392 this->m_first_gate.wait(lck);
0393 }
0394
0395
0396 this->m_ctrl.exclusive_in = 1;
0397
0398
0399 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0400
0401
0402 while (this->m_ctrl.num_upr_shar){
0403 this->m_second_gate.wait(lck);
0404 }
0405 rollback.release();
0406 }
0407
0408 inline bool interprocess_upgradable_mutex::try_lock()
0409 {
0410 scoped_lock_t lck(m_mut, try_to_lock);
0411
0412
0413
0414 if(!lck.owns()
0415 || this->m_ctrl.exclusive_in
0416 || this->m_ctrl.num_upr_shar){
0417 return false;
0418 }
0419 this->m_ctrl.exclusive_in = 1;
0420 return true;
0421 }
0422
0423 template<class TimePoint>
0424 bool interprocess_upgradable_mutex::timed_lock(const TimePoint &abs_time)
0425 {
0426
0427
0428 scoped_lock_t lck(m_mut, abs_time);
0429 if(!lck.owns()) return false;
0430
0431
0432
0433 while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
0434 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0435 if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
0436 return false;
0437 }
0438 break;
0439 }
0440 }
0441
0442
0443 this->m_ctrl.exclusive_in = 1;
0444
0445
0446 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0447
0448
0449 while (this->m_ctrl.num_upr_shar){
0450 if(!this->m_second_gate.timed_wait(lck, abs_time)){
0451 if(this->m_ctrl.num_upr_shar){
0452 return false;
0453 }
0454 break;
0455 }
0456 }
0457 rollback.release();
0458 return true;
0459 }
0460
0461 inline void interprocess_upgradable_mutex::unlock()
0462 {
0463 scoped_lock_t lck(m_mut);
0464 this->m_ctrl.exclusive_in = 0;
0465 this->m_first_gate.notify_all();
0466 }
0467
0468
0469
0470 inline void interprocess_upgradable_mutex::lock_upgradable()
0471 {
0472 scoped_lock_t lck(m_mut);
0473
0474
0475
0476
0477 while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in
0478 || this->m_ctrl.num_upr_shar == constants::max_readers){
0479 this->m_first_gate.wait(lck);
0480 }
0481
0482
0483
0484 this->m_ctrl.upgradable_in = 1;
0485 ++this->m_ctrl.num_upr_shar;
0486 }
0487
0488 inline bool interprocess_upgradable_mutex::try_lock_upgradable()
0489 {
0490 scoped_lock_t lck(m_mut, try_to_lock);
0491
0492
0493
0494
0495 if(!lck.owns()
0496 || this->m_ctrl.exclusive_in
0497 || this->m_ctrl.upgradable_in
0498 || this->m_ctrl.num_upr_shar == constants::max_readers){
0499 return false;
0500 }
0501
0502
0503
0504 this->m_ctrl.upgradable_in = 1;
0505 ++this->m_ctrl.num_upr_shar;
0506 return true;
0507 }
0508
0509 template<class TimePoint>
0510 bool interprocess_upgradable_mutex::timed_lock_upgradable(const TimePoint &abs_time)
0511 {
0512
0513
0514 scoped_lock_t lck(m_mut, abs_time);
0515 if(!lck.owns()) return false;
0516
0517
0518
0519
0520 while(this->m_ctrl.exclusive_in
0521 || this->m_ctrl.upgradable_in
0522 || this->m_ctrl.num_upr_shar == constants::max_readers){
0523 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0524 if((this->m_ctrl.exclusive_in
0525 || this->m_ctrl.upgradable_in
0526 || this->m_ctrl.num_upr_shar == constants::max_readers)){
0527 return false;
0528 }
0529 break;
0530 }
0531 }
0532
0533
0534
0535 this->m_ctrl.upgradable_in = 1;
0536 ++this->m_ctrl.num_upr_shar;
0537 return true;
0538 }
0539
0540 inline void interprocess_upgradable_mutex::unlock_upgradable()
0541 {
0542 scoped_lock_t lck(m_mut);
0543
0544
0545 this->m_ctrl.upgradable_in = 0;
0546 --this->m_ctrl.num_upr_shar;
0547 this->m_first_gate.notify_all();
0548 }
0549
0550
0551
0552 inline void interprocess_upgradable_mutex::lock_sharable()
0553 {
0554 scoped_lock_t lck(m_mut);
0555
0556
0557
0558
0559 while(this->m_ctrl.exclusive_in
0560 || this->m_ctrl.num_upr_shar == constants::max_readers){
0561 this->m_first_gate.wait(lck);
0562 }
0563
0564
0565 ++this->m_ctrl.num_upr_shar;
0566 }
0567
0568 inline bool interprocess_upgradable_mutex::try_lock_sharable()
0569 {
0570 scoped_lock_t lck(m_mut, try_to_lock);
0571
0572
0573
0574
0575 if(!lck.owns()
0576 || this->m_ctrl.exclusive_in
0577 || this->m_ctrl.num_upr_shar == constants::max_readers){
0578 return false;
0579 }
0580
0581
0582 ++this->m_ctrl.num_upr_shar;
0583 return true;
0584 }
0585
0586 template<class TimePoint>
0587 inline bool interprocess_upgradable_mutex::timed_lock_sharable(const TimePoint &abs_time)
0588 {
0589
0590
0591 scoped_lock_t lck(m_mut, abs_time);
0592 if(!lck.owns()) return false;
0593
0594
0595
0596
0597 while (this->m_ctrl.exclusive_in
0598 || this->m_ctrl.num_upr_shar == constants::max_readers){
0599 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0600 if(this->m_ctrl.exclusive_in
0601 || this->m_ctrl.num_upr_shar == constants::max_readers){
0602 return false;
0603 }
0604 break;
0605 }
0606 }
0607
0608
0609 ++this->m_ctrl.num_upr_shar;
0610 return true;
0611 }
0612
0613 inline void interprocess_upgradable_mutex::unlock_sharable()
0614 {
0615 scoped_lock_t lck(m_mut);
0616
0617 --this->m_ctrl.num_upr_shar;
0618 if (this->m_ctrl.num_upr_shar == 0){
0619 this->m_second_gate.notify_one();
0620 }
0621
0622
0623 else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){
0624 this->m_first_gate.notify_all();
0625 }
0626 }
0627
0628
0629
0630 inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable()
0631 {
0632 scoped_lock_t lck(m_mut);
0633
0634 this->m_ctrl.exclusive_in = 0;
0635
0636 this->m_ctrl.upgradable_in = 1;
0637
0638 this->m_ctrl.num_upr_shar = 1;
0639
0640 m_first_gate.notify_all();
0641 }
0642
0643 inline void interprocess_upgradable_mutex::unlock_and_lock_sharable()
0644 {
0645 scoped_lock_t lck(m_mut);
0646
0647 this->m_ctrl.exclusive_in = 0;
0648
0649 this->m_ctrl.num_upr_shar = 1;
0650
0651 m_first_gate.notify_all();
0652 }
0653
0654 inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable()
0655 {
0656 scoped_lock_t lck(m_mut);
0657
0658 this->m_ctrl.upgradable_in = 0;
0659
0660 m_first_gate.notify_all();
0661 }
0662
0663
0664
0665 inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock()
0666 {
0667 scoped_lock_t lck(m_mut);
0668
0669
0670 this->m_ctrl.upgradable_in = 0;
0671 --this->m_ctrl.num_upr_shar;
0672
0673 this->m_ctrl.exclusive_in = 1;
0674
0675
0676 upgradable_to_exclusive_rollback rollback(m_ctrl);
0677
0678 while (this->m_ctrl.num_upr_shar){
0679 this->m_second_gate.wait(lck);
0680 }
0681 rollback.release();
0682 }
0683
0684 inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock()
0685 {
0686 scoped_lock_t lck(m_mut, try_to_lock);
0687
0688 if(!lck.owns()
0689 || this->m_ctrl.num_upr_shar != 1){
0690 return false;
0691 }
0692
0693 this->m_ctrl.upgradable_in = 0;
0694 --this->m_ctrl.num_upr_shar;
0695 this->m_ctrl.exclusive_in = 1;
0696 return true;
0697 }
0698
0699 template<class TimePoint>
0700 bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock(const TimePoint &abs_time)
0701 {
0702
0703
0704 scoped_lock_t lck(m_mut, abs_time);
0705 if(!lck.owns()) return false;
0706
0707
0708
0709 this->m_ctrl.upgradable_in = 0;
0710 --this->m_ctrl.num_upr_shar;
0711
0712 this->m_ctrl.exclusive_in = 1;
0713
0714
0715 upgradable_to_exclusive_rollback rollback(m_ctrl);
0716
0717 while (this->m_ctrl.num_upr_shar){
0718 if(!this->m_second_gate.timed_wait(lck, abs_time)){
0719 if(this->m_ctrl.num_upr_shar){
0720 return false;
0721 }
0722 break;
0723 }
0724 }
0725 rollback.release();
0726 return true;
0727 }
0728
0729 inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock()
0730 {
0731 scoped_lock_t lck(m_mut, try_to_lock);
0732
0733
0734
0735 if(!lck.owns()
0736 || this->m_ctrl.exclusive_in
0737 || this->m_ctrl.upgradable_in
0738 || this->m_ctrl.num_upr_shar != 1){
0739 return false;
0740 }
0741 this->m_ctrl.exclusive_in = 1;
0742 this->m_ctrl.num_upr_shar = 0;
0743 return true;
0744 }
0745
0746 inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable()
0747 {
0748 scoped_lock_t lck(m_mut, try_to_lock);
0749
0750
0751
0752 if(!lck.owns()
0753 || this->m_ctrl.exclusive_in
0754 || this->m_ctrl.upgradable_in){
0755 return false;
0756 }
0757
0758
0759 this->m_ctrl.upgradable_in = 1;
0760 return true;
0761 }
0762
0763 #endif
0764
0765 }
0766 }
0767
0768
0769 #include <boost/interprocess/detail/config_end.hpp>
0770
0771 #endif