File indexing completed on 2026-04-02 07:50:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
0016 #define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
0017
0018 #ifndef BOOST_CONFIG_HPP
0019 # include <boost/config.hpp>
0020 #endif
0021 0022 ">#
0023 #if defined(BOOST_HAS_PRAGMA_ONCE)
0024 # pragma once
0025 #endif
0026
0027 #include <boost/interprocess/detail/config_begin.hpp>
0028 #include <boost/interprocess/detail/workaround.hpp>
0029 #include <boost/interprocess/sync/scoped_lock.hpp>
0030 #include <boost/interprocess/timed_utils.hpp>
0031 #include <boost/interprocess/sync/interprocess_mutex.hpp>
0032 #include <boost/interprocess/sync/interprocess_condition.hpp>
0033 #include <climits>
0034
0035
0036
0037
0038
0039 namespace boost {
0040 namespace interprocess {
0041
0042
0043
0044 class interprocess_sharable_mutex
0045 {
0046
0047 interprocess_sharable_mutex(const interprocess_sharable_mutex &);
0048 interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &);
0049
0050 friend class interprocess_condition;
0051 public:
0052
0053
0054
0055 interprocess_sharable_mutex();
0056
0057
0058
0059 ~interprocess_sharable_mutex();
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073 void lock();
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 bool try_lock();
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100 template<class TimePoint>
0101 bool timed_lock(const TimePoint &abs_time);
0102
0103
0104
0105 template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
0106 { return this->timed_lock(abs_time); }
0107
0108
0109
0110 template<class Duration> bool try_lock_for(const Duration &dur)
0111 { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
0112
0113
0114
0115
0116 void unlock();
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 void lock_sharable();
0131
0132
0133
0134 void lock_shared()
0135 { this->lock_sharable(); }
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 bool try_lock_sharable();
0150
0151
0152
0153 bool try_lock_shared()
0154 { return this->try_lock_sharable(); }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 template<class TimePoint>
0168 bool timed_lock_sharable(const TimePoint &abs_time);
0169
0170
0171
0172 template<class TimePoint> bool try_lock_shared_until(const TimePoint &abs_time)
0173 { return this->timed_lock_sharable(abs_time); }
0174
0175
0176
0177 template<class Duration> bool try_lock_shared_for(const Duration &dur)
0178 { return this->timed_lock_sharable(ipcdetail::duration_to_ustime(dur)); }
0179
0180
0181
0182
0183 void unlock_sharable();
0184
0185
0186
0187 void unlock_shared()
0188 { this->unlock_sharable(); }
0189
0190 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0191 private:
0192 typedef scoped_lock<interprocess_mutex> scoped_lock_t;
0193
0194
0195
0196 struct control_word_t
0197 {
0198 unsigned exclusive_in : 1;
0199 unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1;
0200 } m_ctrl;
0201
0202 interprocess_mutex m_mut;
0203 interprocess_condition m_first_gate;
0204 interprocess_condition m_second_gate;
0205
0206 private:
0207
0208 struct exclusive_rollback
0209 {
0210 exclusive_rollback(control_word_t &ctrl
0211 ,interprocess_condition &first_gate)
0212 : mp_ctrl(&ctrl), m_first_gate(first_gate)
0213 {}
0214
0215 void release()
0216 { mp_ctrl = 0; }
0217
0218 ~exclusive_rollback()
0219 {
0220 if(mp_ctrl){
0221 mp_ctrl->exclusive_in = 0;
0222 m_first_gate.notify_all();
0223 }
0224 }
0225 control_word_t *mp_ctrl;
0226 interprocess_condition &m_first_gate;
0227 };
0228
0229 template<int Dummy>
0230 struct base_constants_t
0231 {
0232 static const unsigned max_readers
0233 = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1));
0234 };
0235 typedef base_constants_t<0> constants;
0236 #endif
0237 };
0238
0239 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0240
0241 template <int Dummy>
0242 const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers;
0243
0244 inline interprocess_sharable_mutex::interprocess_sharable_mutex()
0245 {
0246 this->m_ctrl.exclusive_in = 0;
0247 this->m_ctrl.num_shared = 0;
0248 }
0249
0250 inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
0251 {}
0252
0253 inline void interprocess_sharable_mutex::lock()
0254 {
0255 scoped_lock_t lck(m_mut);
0256
0257
0258
0259 while (this->m_ctrl.exclusive_in){
0260 this->m_first_gate.wait(lck);
0261 }
0262
0263
0264 this->m_ctrl.exclusive_in = 1;
0265
0266
0267 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0268
0269
0270 while (this->m_ctrl.num_shared){
0271 this->m_second_gate.wait(lck);
0272 }
0273 rollback.release();
0274 }
0275
0276 inline bool interprocess_sharable_mutex::try_lock()
0277 {
0278 scoped_lock_t lck(m_mut, try_to_lock);
0279
0280
0281
0282 if(!lck.owns()
0283 || this->m_ctrl.exclusive_in
0284 || this->m_ctrl.num_shared){
0285 return false;
0286 }
0287 this->m_ctrl.exclusive_in = 1;
0288 return true;
0289 }
0290
0291 template<class TimePoint>
0292 inline bool interprocess_sharable_mutex::timed_lock
0293 (const TimePoint &abs_time)
0294 {
0295 scoped_lock_t lck(m_mut, abs_time);
0296 if(!lck.owns()) return false;
0297
0298
0299
0300 while (this->m_ctrl.exclusive_in){
0301
0302
0303 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0304 if(this->m_ctrl.exclusive_in){
0305 return false;
0306 }
0307 break;
0308 }
0309 }
0310
0311
0312 this->m_ctrl.exclusive_in = 1;
0313
0314
0315 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0316
0317
0318 while (this->m_ctrl.num_shared){
0319
0320
0321 if(!this->m_second_gate.timed_wait(lck, abs_time)){
0322 if(this->m_ctrl.num_shared){
0323 return false;
0324 }
0325 break;
0326 }
0327 }
0328 rollback.release();
0329 return true;
0330 }
0331
0332 inline void interprocess_sharable_mutex::unlock()
0333 {
0334 scoped_lock_t lck(m_mut);
0335 this->m_ctrl.exclusive_in = 0;
0336 this->m_first_gate.notify_all();
0337 }
0338
0339
0340
0341 inline void interprocess_sharable_mutex::lock_sharable()
0342 {
0343 scoped_lock_t lck(m_mut);
0344
0345
0346
0347
0348 while(this->m_ctrl.exclusive_in
0349 || this->m_ctrl.num_shared == constants::max_readers){
0350 this->m_first_gate.wait(lck);
0351 }
0352
0353
0354 ++this->m_ctrl.num_shared;
0355 }
0356
0357 inline bool interprocess_sharable_mutex::try_lock_sharable()
0358 {
0359 scoped_lock_t lck(m_mut, try_to_lock);
0360
0361
0362
0363
0364 if(!lck.owns()
0365 || this->m_ctrl.exclusive_in
0366 || this->m_ctrl.num_shared == constants::max_readers){
0367 return false;
0368 }
0369
0370
0371 ++this->m_ctrl.num_shared;
0372 return true;
0373 }
0374
0375 template<class TimePoint>
0376 inline bool interprocess_sharable_mutex::timed_lock_sharable
0377 (const TimePoint &abs_time)
0378 {
0379 scoped_lock_t lck(m_mut, abs_time);
0380 if(!lck.owns()) return false;
0381
0382
0383
0384
0385 while (this->m_ctrl.exclusive_in
0386 || this->m_ctrl.num_shared == constants::max_readers){
0387
0388
0389 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0390 if(this->m_ctrl.exclusive_in
0391 || this->m_ctrl.num_shared == constants::max_readers){
0392 return false;
0393 }
0394 break;
0395 }
0396 }
0397
0398
0399 ++this->m_ctrl.num_shared;
0400 return true;
0401 }
0402
0403 inline void interprocess_sharable_mutex::unlock_sharable()
0404 {
0405 scoped_lock_t lck(m_mut);
0406
0407 --this->m_ctrl.num_shared;
0408 if (this->m_ctrl.num_shared == 0){
0409 this->m_second_gate.notify_one();
0410 }
0411
0412
0413 else if(this->m_ctrl.num_shared == (constants::max_readers-1)){
0414 this->m_first_gate.notify_all();
0415 }
0416 }
0417
0418 #endif
0419
0420 }
0421 }
0422
0423 #include <boost/interprocess/detail/config_end.hpp>
0424
0425 #endif