File indexing completed on 2025-01-18 09:38:33
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 #if defined(BOOST_HAS_PRAGMA_ONCE)
0023 # pragma once
0024 #endif
0025
0026 #include <boost/interprocess/detail/config_begin.hpp>
0027 #include <boost/interprocess/detail/workaround.hpp>
0028 #include <boost/interprocess/sync/scoped_lock.hpp>
0029 #include <boost/interprocess/sync/interprocess_mutex.hpp>
0030 #include <boost/interprocess/sync/interprocess_condition.hpp>
0031 #include <climits>
0032
0033
0034
0035
0036
0037 namespace boost {
0038 namespace interprocess {
0039
0040
0041
0042 class interprocess_sharable_mutex
0043 {
0044
0045 interprocess_sharable_mutex(const interprocess_sharable_mutex &);
0046 interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &);
0047
0048 friend class interprocess_condition;
0049 public:
0050
0051
0052
0053 interprocess_sharable_mutex();
0054
0055
0056
0057 ~interprocess_sharable_mutex();
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 void lock();
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 bool try_lock();
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 template<class TimePoint>
0099 bool timed_lock(const TimePoint &abs_time);
0100
0101
0102
0103 template<class TimePoint> bool try_lock_until(const TimePoint &abs_time)
0104 { return this->timed_lock(abs_time); }
0105
0106
0107
0108 template<class Duration> bool try_lock_for(const Duration &dur)
0109 { return this->timed_lock(ipcdetail::duration_to_ustime(dur)); }
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 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0189 private:
0190 typedef scoped_lock<interprocess_mutex> scoped_lock_t;
0191
0192
0193
0194 struct control_word_t
0195 {
0196 unsigned exclusive_in : 1;
0197 unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1;
0198 } m_ctrl;
0199
0200 interprocess_mutex m_mut;
0201 interprocess_condition m_first_gate;
0202 interprocess_condition m_second_gate;
0203
0204 private:
0205
0206 struct exclusive_rollback
0207 {
0208 exclusive_rollback(control_word_t &ctrl
0209 ,interprocess_condition &first_gate)
0210 : mp_ctrl(&ctrl), m_first_gate(first_gate)
0211 {}
0212
0213 void release()
0214 { mp_ctrl = 0; }
0215
0216 ~exclusive_rollback()
0217 {
0218 if(mp_ctrl){
0219 mp_ctrl->exclusive_in = 0;
0220 m_first_gate.notify_all();
0221 }
0222 }
0223 control_word_t *mp_ctrl;
0224 interprocess_condition &m_first_gate;
0225 };
0226
0227 template<int Dummy>
0228 struct base_constants_t
0229 {
0230 static const unsigned max_readers
0231 = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1));
0232 };
0233 typedef base_constants_t<0> constants;
0234 #endif
0235 };
0236
0237 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0238
0239 template <int Dummy>
0240 const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers;
0241
0242 inline interprocess_sharable_mutex::interprocess_sharable_mutex()
0243 {
0244 this->m_ctrl.exclusive_in = 0;
0245 this->m_ctrl.num_shared = 0;
0246 }
0247
0248 inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
0249 {}
0250
0251 inline void interprocess_sharable_mutex::lock()
0252 {
0253 scoped_lock_t lck(m_mut);
0254
0255
0256
0257 while (this->m_ctrl.exclusive_in){
0258 this->m_first_gate.wait(lck);
0259 }
0260
0261
0262 this->m_ctrl.exclusive_in = 1;
0263
0264
0265 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0266
0267
0268 while (this->m_ctrl.num_shared){
0269 this->m_second_gate.wait(lck);
0270 }
0271 rollback.release();
0272 }
0273
0274 inline bool interprocess_sharable_mutex::try_lock()
0275 {
0276 scoped_lock_t lck(m_mut, try_to_lock);
0277
0278
0279
0280 if(!lck.owns()
0281 || this->m_ctrl.exclusive_in
0282 || this->m_ctrl.num_shared){
0283 return false;
0284 }
0285 this->m_ctrl.exclusive_in = 1;
0286 return true;
0287 }
0288
0289 template<class TimePoint>
0290 inline bool interprocess_sharable_mutex::timed_lock
0291 (const TimePoint &abs_time)
0292 {
0293 scoped_lock_t lck(m_mut, abs_time);
0294 if(!lck.owns()) return false;
0295
0296
0297
0298 while (this->m_ctrl.exclusive_in){
0299
0300
0301 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0302 if(this->m_ctrl.exclusive_in){
0303 return false;
0304 }
0305 break;
0306 }
0307 }
0308
0309
0310 this->m_ctrl.exclusive_in = 1;
0311
0312
0313 exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
0314
0315
0316 while (this->m_ctrl.num_shared){
0317
0318
0319 if(!this->m_second_gate.timed_wait(lck, abs_time)){
0320 if(this->m_ctrl.num_shared){
0321 return false;
0322 }
0323 break;
0324 }
0325 }
0326 rollback.release();
0327 return true;
0328 }
0329
0330 inline void interprocess_sharable_mutex::unlock()
0331 {
0332 scoped_lock_t lck(m_mut);
0333 this->m_ctrl.exclusive_in = 0;
0334 this->m_first_gate.notify_all();
0335 }
0336
0337
0338
0339 inline void interprocess_sharable_mutex::lock_sharable()
0340 {
0341 scoped_lock_t lck(m_mut);
0342
0343
0344
0345
0346 while(this->m_ctrl.exclusive_in
0347 || this->m_ctrl.num_shared == constants::max_readers){
0348 this->m_first_gate.wait(lck);
0349 }
0350
0351
0352 ++this->m_ctrl.num_shared;
0353 }
0354
0355 inline bool interprocess_sharable_mutex::try_lock_sharable()
0356 {
0357 scoped_lock_t lck(m_mut, try_to_lock);
0358
0359
0360
0361
0362 if(!lck.owns()
0363 || this->m_ctrl.exclusive_in
0364 || this->m_ctrl.num_shared == constants::max_readers){
0365 return false;
0366 }
0367
0368
0369 ++this->m_ctrl.num_shared;
0370 return true;
0371 }
0372
0373 template<class TimePoint>
0374 inline bool interprocess_sharable_mutex::timed_lock_sharable
0375 (const TimePoint &abs_time)
0376 {
0377 scoped_lock_t lck(m_mut, abs_time);
0378 if(!lck.owns()) return false;
0379
0380
0381
0382
0383 while (this->m_ctrl.exclusive_in
0384 || this->m_ctrl.num_shared == constants::max_readers){
0385
0386
0387 if(!this->m_first_gate.timed_wait(lck, abs_time)){
0388 if(this->m_ctrl.exclusive_in
0389 || this->m_ctrl.num_shared == constants::max_readers){
0390 return false;
0391 }
0392 break;
0393 }
0394 }
0395
0396
0397 ++this->m_ctrl.num_shared;
0398 return true;
0399 }
0400
0401 inline void interprocess_sharable_mutex::unlock_sharable()
0402 {
0403 scoped_lock_t lck(m_mut);
0404
0405 --this->m_ctrl.num_shared;
0406 if (this->m_ctrl.num_shared == 0){
0407 this->m_second_gate.notify_one();
0408 }
0409
0410
0411 else if(this->m_ctrl.num_shared == (constants::max_readers-1)){
0412 this->m_first_gate.notify_all();
0413 }
0414 }
0415
0416 #endif
0417
0418 }
0419 }
0420
0421 #include <boost/interprocess/detail/config_end.hpp>
0422
0423 #endif