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