File indexing completed on 2025-12-16 09:53:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
0012 #define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024 #include <boost/interprocess/sync/scoped_lock.hpp>
0025 #include <boost/interprocess/sync/detail/locks.hpp>
0026 #include <limits>
0027
0028 namespace boost {
0029 namespace interprocess {
0030 namespace ipcdetail {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 template<class ConditionMembers>
0183 class condition_algorithm_8a
0184 {
0185 private:
0186 condition_algorithm_8a();
0187 ~condition_algorithm_8a();
0188 condition_algorithm_8a(const condition_algorithm_8a &);
0189 condition_algorithm_8a &operator=(const condition_algorithm_8a &);
0190
0191 typedef typename ConditionMembers::semaphore_type semaphore_type;
0192 typedef typename ConditionMembers::mutex_type mutex_type;
0193 typedef typename ConditionMembers::integer_type integer_type;
0194
0195 public:
0196 template<bool TimeoutEnabled, class Lock, class TimePoint>
0197 static bool wait ( ConditionMembers &data, Lock &lock, const TimePoint &abs_time)
0198 {
0199
0200 integer_type nsignals_was_left = 0;
0201 integer_type nwaiters_was_gone = 0;
0202
0203 data.get_sem_block_lock().wait();
0204 ++data.get_nwaiters_blocked();
0205 data.get_sem_block_lock().post();
0206
0207
0208 lock_inverter<Lock> inverted_lock(lock);
0209 scoped_lock<lock_inverter<Lock> > external_unlock(inverted_lock);
0210
0211 bool bTimedOut = !do_sem_timed_wait(data.get_sem_block_queue(), abs_time, bool_<TimeoutEnabled>());
0212
0213 {
0214 scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
0215 if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
0216 if ( bTimedOut ) {
0217 if ( 0 != data.get_nwaiters_blocked() ) {
0218 data.get_nwaiters_blocked()--;
0219 }
0220 else {
0221 data.get_nwaiters_gone()++;
0222 }
0223 }
0224 if ( 0 == --data.get_nwaiters_to_unblock() ) {
0225 if ( 0 != data.get_nwaiters_blocked() ) {
0226 data.get_sem_block_lock().post();
0227 nsignals_was_left = 0;
0228 }
0229 else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
0230 data.get_nwaiters_gone() = 0;
0231 }
0232 }
0233 }
0234 else if ( (std::numeric_limits<integer_type>::max)()/2
0235 == ++data.get_nwaiters_gone() ) {
0236 data.get_sem_block_lock().wait();
0237 data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
0238 data.get_sem_block_lock().post();
0239 data.get_nwaiters_gone() = 0;
0240 }
0241
0242 }
0243
0244 if ( 1 == nsignals_was_left ) {
0245 if ( 0 != nwaiters_was_gone ) {
0246
0247 while ( nwaiters_was_gone-- ) {
0248 data.get_sem_block_queue().wait();
0249 }
0250 }
0251 data.get_sem_block_lock().post();
0252 }
0253
0254
0255
0256 return ( bTimedOut ) ? false : true;
0257 }
0258
0259 static void signal(ConditionMembers &data, bool broadcast)
0260 {
0261 integer_type nsignals_to_issue;
0262
0263 {
0264 scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
0265
0266 if ( 0 != data.get_nwaiters_to_unblock() ) {
0267 if ( 0 == data.get_nwaiters_blocked() ) {
0268
0269 return;
0270 }
0271 if (broadcast) {
0272 data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
0273 data.get_nwaiters_blocked() = 0;
0274 }
0275 else {
0276 nsignals_to_issue = 1;
0277 data.get_nwaiters_to_unblock()++;
0278 data.get_nwaiters_blocked()--;
0279 }
0280 }
0281 else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) {
0282 data.get_sem_block_lock().wait();
0283 if ( 0 != data.get_nwaiters_gone() ) {
0284 data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
0285 data.get_nwaiters_gone() = 0;
0286 }
0287 if (broadcast) {
0288 nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
0289 data.get_nwaiters_blocked() = 0;
0290 }
0291 else {
0292 nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
0293 data.get_nwaiters_blocked()--;
0294 }
0295 }
0296 else {
0297
0298 return;
0299 }
0300
0301 }
0302 data.get_sem_block_queue().post(nsignals_to_issue);
0303 }
0304
0305 private:
0306 template<class TimePoint>
0307 static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &abs_time, bool_<true>)
0308 { return sem.timed_wait(abs_time); }
0309
0310 template<class TimePoint>
0311 static bool do_sem_timed_wait(semaphore_type &sem, const TimePoint &, bool_<false>)
0312 { sem.wait(); return true; }
0313 };
0314
0315 template<class ConditionMembers>
0316 class condition_8a_wrapper
0317 {
0318
0319 condition_8a_wrapper(const condition_8a_wrapper &);
0320 condition_8a_wrapper &operator=(const condition_8a_wrapper &);
0321
0322 ConditionMembers m_data;
0323 typedef condition_algorithm_8a<ConditionMembers> algo_type;
0324
0325 public:
0326
0327 condition_8a_wrapper(){}
0328
0329
0330
0331
0332 ConditionMembers & get_members()
0333 { return m_data; }
0334
0335 const ConditionMembers & get_members() const
0336 { return m_data; }
0337
0338 void notify_one()
0339 { algo_type::signal(m_data, false); }
0340
0341 void notify_all()
0342 { algo_type::signal(m_data, true); }
0343
0344 template <typename L>
0345 void wait(L& lock)
0346 {
0347 if (!lock)
0348 throw lock_exception();
0349 algo_type::template wait<false>(m_data, lock, 0);
0350 }
0351
0352 template <typename L, typename Pr>
0353 void wait(L& lock, Pr pred)
0354 {
0355 if (!lock)
0356 throw lock_exception();
0357
0358 while (!pred())
0359 algo_type::template wait<false>(m_data, lock, 0);
0360 }
0361
0362 template <typename L, class TimePoint>
0363 bool timed_wait(L& lock, const TimePoint &abs_time)
0364 {
0365 if (!lock)
0366 throw lock_exception();
0367 return algo_type::template wait<true>(m_data, lock, abs_time);
0368 }
0369
0370 template <typename L, class TimePoint, typename Pr>
0371 bool timed_wait(L& lock, const TimePoint &abs_time, Pr pred)
0372 {
0373 if (!lock)
0374 throw lock_exception();
0375 while (!pred()){
0376 if (!algo_type::template wait<true>(m_data, lock, abs_time))
0377 return pred();
0378 }
0379 return true;
0380 }
0381 };
0382
0383 }
0384 }
0385 }
0386
0387 #include <boost/interprocess/detail/config_end.hpp>
0388
0389 #endif