Browse code

Adding IPC detail on windows

Steffen Neumann authored on 18/01/2022 08:33:38
Showing 4 changed files

1 1
new file mode 100755
... ...
@@ -0,0 +1,99 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+//
3
+// (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
4
+// Software License, Version 1.0. (See accompanying file
5
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+//
7
+// See http://www.boost.org/libs/interprocess for documentation.
8
+//
9
+//////////////////////////////////////////////////////////////////////////////
10
+
11
+#ifndef BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
12
+#define BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
13
+
14
+#ifndef BOOST_CONFIG_HPP
15
+#  include <boost/config.hpp>
16
+#endif
17
+#
18
+#if defined(BOOST_HAS_PRAGMA_ONCE)
19
+#  pragma once
20
+#endif
21
+
22
+#include <boost/interprocess/detail/config_begin.hpp>
23
+#include <boost/interprocess/detail/workaround.hpp>
24
+
25
+#include <boost/interprocess/sync/spin/wait.hpp>
26
+
27
+namespace boost {
28
+namespace interprocess {
29
+namespace ipcdetail {
30
+
31
+template<class MutexType>
32
+bool try_based_timed_lock(MutexType &m, const boost::posix_time::ptime &abs_time)
33
+{
34
+   //Same as lock()
35
+   if(abs_time.is_pos_infinity()){
36
+      m.lock();
37
+      return true;
38
+   }
39
+   //Always try to lock to achieve POSIX guarantees:
40
+   // "Under no circumstance shall the function fail with a timeout if the mutex
41
+   //  can be locked immediately. The validity of the abs_timeout parameter need not
42
+   //  be checked if the mutex can be locked immediately."
43
+   else if(m.try_lock()){
44
+      return true;
45
+   }
46
+   else{
47
+      spin_wait swait;
48
+      while(microsec_clock::universal_time() < abs_time){
49
+         if(m.try_lock()){
50
+            return true;
51
+         }
52
+         swait.yield();
53
+      }
54
+      return false;
55
+   }
56
+}
57
+
58
+template<class MutexType>
59
+void try_based_lock(MutexType &m)
60
+{
61
+   if(!m.try_lock()){
62
+      spin_wait swait;
63
+      do{
64
+         if(m.try_lock()){
65
+            break;
66
+         }
67
+         else{
68
+            swait.yield();
69
+         }
70
+      }
71
+      while(1);
72
+   }
73
+}
74
+
75
+template<class MutexType>
76
+void timeout_when_locking_aware_lock(MutexType &m)
77
+{
78
+   #ifdef BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING
79
+      boost::posix_time::ptime wait_time
80
+         = microsec_clock::universal_time()
81
+         + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS);
82
+      if (!m.timed_lock(wait_time))
83
+      {
84
+         throw interprocess_exception(timeout_when_locking_error
85
+                                     , "Interprocess mutex timeout when locking. Possible deadlock: "
86
+                                       "owner died without unlocking?");
87
+      }
88
+   #else
89
+      m.lock();
90
+   #endif
91
+}
92
+
93
+}  //namespace ipcdetail
94
+}  //namespace interprocess
95
+}  //namespace boost
96
+
97
+#include <boost/interprocess/detail/config_end.hpp>
98
+
99
+#endif   //BOOST_INTERPROCESS_SYNC_DETAIL_COMMON_ALGORITHMS_HPP
0 100
new file mode 100755
... ...
@@ -0,0 +1,395 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+//
3
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4
+// Software License, Version 1.0. (See accompanying file
5
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+//
7
+// See http://www.boost.org/libs/interprocess for documentation.
8
+//
9
+//////////////////////////////////////////////////////////////////////////////
10
+
11
+#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
12
+#define BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
13
+
14
+#ifndef BOOST_CONFIG_HPP
15
+#  include <boost/config.hpp>
16
+#endif
17
+#
18
+#if defined(BOOST_HAS_PRAGMA_ONCE)
19
+#  pragma once
20
+#endif
21
+
22
+#include <boost/interprocess/detail/config_begin.hpp>
23
+#include <boost/interprocess/detail/workaround.hpp>
24
+#include <boost/interprocess/sync/scoped_lock.hpp>
25
+#include <boost/interprocess/sync/detail/locks.hpp>
26
+#include <limits>
27
+
28
+namespace boost {
29
+namespace interprocess {
30
+namespace ipcdetail {
31
+
32
+////////////////////////////////////////////////////////////////////////
33
+////////////////////////////////////////////////////////////////////////
34
+////////////////////////////////////////////////////////////////////////
35
+//
36
+// Condition variable algorithm taken from pthreads-win32 discussion.
37
+//
38
+// The algorithm was developed by Alexander Terekhov in colaboration with
39
+// Louis Thomas.
40
+//
41
+//     Algorithm 8a / IMPL_SEM,UNBLOCK_STRATEGY == UNBLOCK_ALL
42
+//
43
+// semBlockLock - bin.semaphore
44
+// semBlockQueue - semaphore
45
+// mtxExternal - mutex or CS
46
+// mtxUnblockLock - mutex or CS
47
+// nWaitersGone - int
48
+// nWaitersBlocked - int
49
+// nWaitersToUnblock - int
50
+//
51
+// wait( timeout ) {
52
+//
53
+//   [auto: register int result          ]     // error checking omitted
54
+//   [auto: register int nSignalsWasLeft ]
55
+//   [auto: register int nWaitersWasGone ]
56
+//
57
+//   sem_wait( semBlockLock );
58
+//   nWaitersBlocked++;
59
+//   sem_post( semBlockLock );
60
+//
61
+//   unlock( mtxExternal );
62
+//   bTimedOut = sem_wait( semBlockQueue,timeout );
63
+//
64
+//   lock( mtxUnblockLock );
65
+//   if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
66
+//     if ( bTimedOut ) {                       // timeout (or canceled)
67
+//       if ( 0 != nWaitersBlocked ) {
68
+//         nWaitersBlocked--;
69
+//       }
70
+//       else {
71
+//         nWaitersGone++;                     // count spurious wakeups.
72
+//       }
73
+//     }
74
+//     if ( 0 == --nWaitersToUnblock ) {
75
+//       if ( 0 != nWaitersBlocked ) {
76
+//         sem_post( semBlockLock );           // open the gate.
77
+//         nSignalsWasLeft = 0;                // do not open the gate
78
+//                                             // below again.
79
+//       }
80
+//       else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
81
+//         nWaitersGone = 0;
82
+//       }
83
+//     }
84
+//   }
85
+//   else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
86
+//                                             // spurious semaphore :-)
87
+//     sem_wait( semBlockLock );
88
+//     nWaitersBlocked -= nWaitersGone;     // something is going on here
89
+//                                          //  - test of timeouts? :-)
90
+//     sem_post( semBlockLock );
91
+//     nWaitersGone = 0;
92
+//   }
93
+//   unlock( mtxUnblockLock );
94
+//
95
+//   if ( 1 == nSignalsWasLeft ) {
96
+//     if ( 0 != nWaitersWasGone ) {
97
+//       // sem_adjust( semBlockQueue,-nWaitersWasGone );
98
+//       while ( nWaitersWasGone-- ) {
99
+//         sem_wait( semBlockQueue );       // better now than spurious later
100
+//       }
101
+//     } sem_post( semBlockLock );          // open the gate
102
+//   }
103
+//
104
+//   lock( mtxExternal );
105
+//
106
+//   return ( bTimedOut ) ? ETIMEOUT : 0;
107
+// }
108
+//
109
+// signal(bAll) {
110
+//
111
+//   [auto: register int result         ]
112
+//   [auto: register int nSignalsToIssue]
113
+//
114
+//   lock( mtxUnblockLock );
115
+//
116
+//   if ( 0 != nWaitersToUnblock ) {        // the gate is closed!!!
117
+//     if ( 0 == nWaitersBlocked ) {        // NO-OP
118
+//       return unlock( mtxUnblockLock );
119
+//     }
120
+//     if (bAll) {
121
+//       nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
122
+//       nWaitersBlocked = 0;
123
+//     }
124
+//     else {
125
+//       nSignalsToIssue = 1;
126
+//       nWaitersToUnblock++;
127
+//       nWaitersBlocked--;
128
+//     }
129
+//   }
130
+//   else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
131
+//     sem_wait( semBlockLock );                  // close the gate
132
+//     if ( 0 != nWaitersGone ) {
133
+//       nWaitersBlocked -= nWaitersGone;
134
+//       nWaitersGone = 0;
135
+//     }
136
+//     if (bAll) {
137
+//       nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
138
+//       nWaitersBlocked = 0;
139
+//     }
140
+//     else {
141
+//       nSignalsToIssue = nWaitersToUnblock = 1;
142
+//       nWaitersBlocked--;
143
+//     }
144
+//   }
145
+//   else { // NO-OP
146
+//     return unlock( mtxUnblockLock );
147
+//   }
148
+//
149
+//   unlock( mtxUnblockLock );
150
+//   sem_post( semBlockQueue,nSignalsToIssue );
151
+//   return result;
152
+// }
153
+////////////////////////////////////////////////////////////////////////
154
+////////////////////////////////////////////////////////////////////////
155
+////////////////////////////////////////////////////////////////////////
156
+
157
+
158
+// Required interface for ConditionMembers
159
+// class ConditionMembers
160
+// {
161
+//    typedef implementation_defined semaphore_type;
162
+//    typedef implementation_defined mutex_type;
163
+//    typedef implementation_defined integer_type;
164
+//
165
+//    integer_type    &get_nwaiters_blocked()
166
+//    integer_type    &get_nwaiters_gone()
167
+//    integer_type    &get_nwaiters_to_unblock()
168
+//    semaphore_type  &get_sem_block_queue()
169
+//    semaphore_type  &get_sem_block_lock()
170
+//    mutex_type      &get_mtx_unblock_lock()
171
+// };
172
+//
173
+// Must be initialized as following
174
+//
175
+//    get_nwaiters_blocked() == 0
176
+//    get_nwaiters_gone() == 0
177
+//    get_nwaiters_to_unblock() == 0
178
+//    get_sem_block_queue() == initial count 0
179
+//    get_sem_block_lock() == initial count 1
180
+//    get_mtx_unblock_lock() (unlocked)
181
+//
182
+template<class ConditionMembers>
183
+class condition_algorithm_8a
184
+{
185
+   private:
186
+   condition_algorithm_8a();
187
+   ~condition_algorithm_8a();
188
+   condition_algorithm_8a(const condition_algorithm_8a &);
189
+   condition_algorithm_8a &operator=(const condition_algorithm_8a &);
190
+
191
+   typedef typename ConditionMembers::semaphore_type  semaphore_type;
192
+   typedef typename ConditionMembers::mutex_type      mutex_type;
193
+   typedef typename ConditionMembers::integer_type    integer_type;
194
+
195
+   public:
196
+   template<class Lock>
197
+   static bool wait  ( ConditionMembers &data, Lock &lock
198
+                     , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
199
+   static void signal(ConditionMembers &data, bool broadcast);
200
+};
201
+
202
+template<class ConditionMembers>
203
+inline void condition_algorithm_8a<ConditionMembers>::signal(ConditionMembers &data, bool broadcast)
204
+{
205
+   integer_type nsignals_to_issue;
206
+
207
+   {
208
+      scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
209
+
210
+      if ( 0 != data.get_nwaiters_to_unblock() ) {        // the gate is closed!!!
211
+         if ( 0 == data.get_nwaiters_blocked() ) {        // NO-OP
212
+            //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
213
+            return;
214
+         }
215
+         if (broadcast) {
216
+            data.get_nwaiters_to_unblock() += nsignals_to_issue = data.get_nwaiters_blocked();
217
+            data.get_nwaiters_blocked() = 0;
218
+         }
219
+         else {
220
+            nsignals_to_issue = 1;
221
+            data.get_nwaiters_to_unblock()++;
222
+            data.get_nwaiters_blocked()--;
223
+         }
224
+      }
225
+      else if ( data.get_nwaiters_blocked() > data.get_nwaiters_gone() ) { // HARMLESS RACE CONDITION!
226
+         data.get_sem_block_lock().wait();                      // close the gate
227
+         if ( 0 != data.get_nwaiters_gone() ) {
228
+            data.get_nwaiters_blocked() -= data.get_nwaiters_gone();
229
+            data.get_nwaiters_gone() = 0;
230
+         }
231
+         if (broadcast) {
232
+            nsignals_to_issue = data.get_nwaiters_to_unblock() = data.get_nwaiters_blocked();
233
+            data.get_nwaiters_blocked() = 0;
234
+         }
235
+         else {
236
+            nsignals_to_issue = data.get_nwaiters_to_unblock() = 1;
237
+            data.get_nwaiters_blocked()--;
238
+         }
239
+      }
240
+      else { // NO-OP
241
+         //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
242
+         return;
243
+      }
244
+      //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
245
+   }
246
+   data.get_sem_block_queue().post(nsignals_to_issue);
247
+}
248
+
249
+template<class ConditionMembers>
250
+template<class Lock>
251
+inline bool condition_algorithm_8a<ConditionMembers>::wait
252
+   ( ConditionMembers &data
253
+   , Lock &lock
254
+   , bool tout_enabled
255
+   , const boost::posix_time::ptime &abs_time
256
+   )
257
+{
258
+   //Initialize to avoid warnings
259
+   integer_type nsignals_was_left = 0;
260
+   integer_type nwaiters_was_gone = 0;
261
+
262
+   data.get_sem_block_lock().wait();
263
+   ++data.get_nwaiters_blocked();
264
+   data.get_sem_block_lock().post();
265
+
266
+   //Unlock external lock and program for relock
267
+   lock_inverter<Lock> inverted_lock(lock);
268
+   scoped_lock<lock_inverter<Lock> >   external_unlock(inverted_lock);
269
+
270
+   bool bTimedOut = tout_enabled
271
+      ? !data.get_sem_block_queue().timed_wait(abs_time)
272
+      : (data.get_sem_block_queue().wait(), false);
273
+
274
+   {
275
+      scoped_lock<mutex_type> locker(data.get_mtx_unblock_lock());
276
+      if ( 0 != (nsignals_was_left = data.get_nwaiters_to_unblock()) ) {
277
+         if ( bTimedOut ) {                       // timeout (or canceled)
278
+            if ( 0 != data.get_nwaiters_blocked() ) {
279
+               data.get_nwaiters_blocked()--;
280
+            }
281
+            else {
282
+               data.get_nwaiters_gone()++;                     // count spurious wakeups.
283
+            }
284
+         }
285
+         if ( 0 == --data.get_nwaiters_to_unblock() ) {
286
+            if ( 0 != data.get_nwaiters_blocked() ) {
287
+               data.get_sem_block_lock().post();          // open the gate.
288
+               nsignals_was_left = 0;          // do not open the gate below again.
289
+            }
290
+            else if ( 0 != (nwaiters_was_gone = data.get_nwaiters_gone()) ) {
291
+               data.get_nwaiters_gone() = 0;
292
+            }
293
+         }
294
+      }
295
+      else if ( (std::numeric_limits<integer_type>::max)()/2
296
+                == ++data.get_nwaiters_gone() ) { // timeout/canceled or spurious semaphore :-)
297
+         data.get_sem_block_lock().wait();
298
+         data.get_nwaiters_blocked() -= data.get_nwaiters_gone();       // something is going on here - test of timeouts? :-)
299
+         data.get_sem_block_lock().post();
300
+         data.get_nwaiters_gone() = 0;
301
+      }
302
+      //locker's destructor triggers data.get_mtx_unblock_lock().unlock()
303
+   }
304
+
305
+   if ( 1 == nsignals_was_left ) {
306
+      if ( 0 != nwaiters_was_gone ) {
307
+         // sem_adjust( data.get_sem_block_queue(),-nwaiters_was_gone );
308
+         while ( nwaiters_was_gone-- ) {
309
+            data.get_sem_block_queue().wait();       // better now than spurious later
310
+         }
311
+      }
312
+      data.get_sem_block_lock().post(); // open the gate
313
+   }
314
+
315
+   //lock.lock(); called from unlocker destructor
316
+
317
+   return ( bTimedOut ) ? false : true;
318
+}
319
+
320
+
321
+template<class ConditionMembers>
322
+class condition_8a_wrapper
323
+{
324
+   //Non-copyable
325
+   condition_8a_wrapper(const condition_8a_wrapper &);
326
+   condition_8a_wrapper &operator=(const condition_8a_wrapper &);
327
+
328
+   ConditionMembers m_data;
329
+   typedef ipcdetail::condition_algorithm_8a<ConditionMembers> algo_type;
330
+
331
+   public:
332
+
333
+   condition_8a_wrapper(){}
334
+
335
+   //Compiler-generated destructor is OK
336
+   //~condition_8a_wrapper(){}
337
+
338
+   ConditionMembers & get_members()
339
+   {  return m_data; }
340
+
341
+   const ConditionMembers & get_members() const
342
+   {  return m_data; }
343
+
344
+   void notify_one()
345
+   {  algo_type::signal(m_data, false);  }
346
+
347
+   void notify_all()
348
+   {  algo_type::signal(m_data, true);  }
349
+
350
+   template <typename L>
351
+   void wait(L& lock)
352
+   {
353
+      if (!lock)
354
+         throw lock_exception();
355
+      algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
356
+   }
357
+
358
+   template <typename L, typename Pr>
359
+   void wait(L& lock, Pr pred)
360
+   {
361
+      if (!lock)
362
+         throw lock_exception();
363
+
364
+      while (!pred())
365
+         algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
366
+   }
367
+
368
+   template <typename L>
369
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
370
+   {
371
+      if (!lock)
372
+         throw lock_exception();
373
+      return algo_type::wait(m_data, lock, true, abs_time);
374
+   }
375
+
376
+   template <typename L, typename Pr>
377
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
378
+   {
379
+      if (!lock)
380
+            throw lock_exception();
381
+      while (!pred()){
382
+         if (!algo_type::wait(m_data, lock, true, abs_time))
383
+            return pred();
384
+      }
385
+      return true;
386
+   }
387
+};
388
+
389
+}  //namespace ipcdetail
390
+}  //namespace interprocess
391
+}  //namespace boost
392
+
393
+#include <boost/interprocess/detail/config_end.hpp>
394
+
395
+#endif   //BOOST_INTERPROCESS_DETAIL_CONDITION_ALGORITHM_8A_HPP
0 396
new file mode 100755
... ...
@@ -0,0 +1,224 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+//
3
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
4
+// Software License, Version 1.0. (See accompanying file
5
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+//
7
+// See http://www.boost.org/libs/interprocess for documentation.
8
+//
9
+//////////////////////////////////////////////////////////////////////////////
10
+
11
+#ifndef BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
12
+#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
13
+
14
+#ifndef BOOST_CONFIG_HPP
15
+#  include <boost/config.hpp>
16
+#endif
17
+#
18
+#if defined(BOOST_HAS_PRAGMA_ONCE)
19
+#  pragma once
20
+#endif
21
+
22
+#include <boost/interprocess/detail/config_begin.hpp>
23
+#include <boost/interprocess/detail/workaround.hpp>
24
+#include <boost/interprocess/sync/scoped_lock.hpp>
25
+#include <boost/interprocess/sync/detail/locks.hpp>
26
+#include <limits>
27
+
28
+namespace boost {
29
+namespace interprocess {
30
+namespace ipcdetail {
31
+
32
+////////////////////////////////////////////////////////////////////////
33
+////////////////////////////////////////////////////////////////////////
34
+////////////////////////////////////////////////////////////////////////
35
+//
36
+// Condition variable 'any' (able to use any type of external mutex)
37
+//
38
+// The code is based on Howard E. Hinnant's ISO C++ N2406 paper.
39
+// Many thanks to Howard for his support and comments.
40
+////////////////////////////////////////////////////////////////////////
41
+////////////////////////////////////////////////////////////////////////
42
+////////////////////////////////////////////////////////////////////////
43
+
44
+// Required interface for ConditionAnyMembers
45
+// class ConditionAnyMembers
46
+// {
47
+//    typedef implementation_defined mutex_type;
48
+//    typedef implementation_defined condvar_type;
49
+//
50
+//    condvar     &get_condvar()
51
+//    mutex_type  &get_mutex()
52
+// };
53
+//
54
+// Must be initialized as following
55
+//
56
+//    get_condvar()  [no threads blocked]
57
+//    get_mutex()    [unlocked]
58
+
59
+template<class ConditionAnyMembers>
60
+class condition_any_algorithm
61
+{
62
+   private:
63
+   condition_any_algorithm();
64
+   ~condition_any_algorithm();
65
+   condition_any_algorithm(const condition_any_algorithm &);
66
+   condition_any_algorithm &operator=(const condition_any_algorithm &);
67
+
68
+   typedef typename ConditionAnyMembers::mutex_type      mutex_type;
69
+   typedef typename ConditionAnyMembers::condvar_type    condvar_type;
70
+
71
+   template <class Lock>
72
+   static void do_wait(ConditionAnyMembers &data, Lock& lock);
73
+
74
+   template <class Lock>
75
+   static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time);
76
+
77
+   public:
78
+   template<class Lock>
79
+   static bool wait  ( ConditionAnyMembers &data, Lock &mut
80
+                     , bool timeout_enabled, const boost::posix_time::ptime &abs_time);
81
+   static void signal( ConditionAnyMembers &data, bool broadcast);
82
+};
83
+
84
+template<class ConditionAnyMembers>
85
+void condition_any_algorithm<ConditionAnyMembers>::signal(ConditionAnyMembers &data, bool broadcast)
86
+{
87
+   scoped_lock<mutex_type> internal_lock(data.get_mutex());
88
+   if(broadcast){
89
+      data.get_condvar().notify_all();
90
+   }
91
+   else{
92
+      data.get_condvar().notify_one();
93
+   }
94
+}
95
+
96
+template<class ConditionAnyMembers>
97
+template<class Lock>
98
+bool condition_any_algorithm<ConditionAnyMembers>::wait
99
+   ( ConditionAnyMembers &data
100
+   , Lock &lock
101
+   , bool tout_enabled
102
+   , const boost::posix_time::ptime &abs_time)
103
+{
104
+   if(tout_enabled){
105
+      return condition_any_algorithm::do_timed_wait(data, lock, abs_time);
106
+   }
107
+   else{
108
+      condition_any_algorithm::do_wait(data, lock);
109
+      return true;
110
+   }
111
+}
112
+
113
+template<class ConditionAnyMembers>
114
+template <class Lock>
115
+void condition_any_algorithm<ConditionAnyMembers>::do_wait
116
+   (ConditionAnyMembers &data, Lock& lock)
117
+{
118
+   //lock internal before unlocking external to avoid race with a notifier
119
+   scoped_lock<mutex_type> internal_lock(data.get_mutex());
120
+   {
121
+      lock_inverter<Lock> inverted_lock(lock);
122
+      scoped_lock<lock_inverter<Lock> >   external_unlock(inverted_lock);
123
+      {  //unlock internal first to avoid deadlock with near simultaneous waits
124
+         scoped_lock<mutex_type>     internal_unlock;
125
+         internal_lock.swap(internal_unlock);
126
+         data.get_condvar().wait(internal_unlock);
127
+      }
128
+   }
129
+}
130
+
131
+template<class ConditionAnyMembers>
132
+template <class Lock>
133
+bool condition_any_algorithm<ConditionAnyMembers>::do_timed_wait
134
+   (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time)
135
+{
136
+   //lock internal before unlocking external to avoid race with a notifier
137
+   scoped_lock<mutex_type> internal_lock(data.get_mutex());
138
+   {
139
+      //Unlock external lock and program for relock
140
+      lock_inverter<Lock> inverted_lock(lock);
141
+      scoped_lock<lock_inverter<Lock> >   external_unlock(inverted_lock);
142
+      {  //unlock internal first to avoid deadlock with near simultaneous waits
143
+         scoped_lock<mutex_type> internal_unlock;
144
+         internal_lock.swap(internal_unlock);
145
+         return data.get_condvar().timed_wait(internal_unlock, abs_time);
146
+      }
147
+   }
148
+}
149
+
150
+
151
+template<class ConditionAnyMembers>
152
+class condition_any_wrapper
153
+{
154
+   //Non-copyable
155
+   condition_any_wrapper(const condition_any_wrapper &);
156
+   condition_any_wrapper &operator=(const condition_any_wrapper &);
157
+
158
+   ConditionAnyMembers m_data;
159
+   typedef ipcdetail::condition_any_algorithm<ConditionAnyMembers> algo_type;
160
+
161
+   public:
162
+
163
+   condition_any_wrapper(){}
164
+
165
+   ~condition_any_wrapper(){}
166
+
167
+   ConditionAnyMembers & get_members()
168
+   {  return m_data; }
169
+
170
+   const ConditionAnyMembers & get_members() const
171
+   {  return m_data; }
172
+
173
+   void notify_one()
174
+   {  algo_type::signal(m_data, false);  }
175
+
176
+   void notify_all()
177
+   {  algo_type::signal(m_data, true);  }
178
+
179
+   template <typename L>
180
+   void wait(L& lock)
181
+   {
182
+      if (!lock)
183
+         throw lock_exception();
184
+      algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
185
+   }
186
+
187
+   template <typename L, typename Pr>
188
+   void wait(L& lock, Pr pred)
189
+   {
190
+      if (!lock)
191
+         throw lock_exception();
192
+
193
+      while (!pred())
194
+         algo_type::wait(m_data, lock, false, boost::posix_time::ptime());
195
+   }
196
+
197
+   template <typename L>
198
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
199
+   {
200
+      if (!lock)
201
+         throw lock_exception();
202
+      return algo_type::wait(m_data, lock, true, abs_time);
203
+   }
204
+
205
+   template <typename L, typename Pr>
206
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
207
+   {
208
+      if (!lock)
209
+            throw lock_exception();
210
+      while (!pred()){
211
+         if (!algo_type::wait(m_data, lock, true, abs_time))
212
+            return pred();
213
+      }
214
+      return true;
215
+   }
216
+};
217
+
218
+}  //namespace ipcdetail
219
+}  //namespace interprocess
220
+}  //namespace boost
221
+
222
+#include <boost/interprocess/detail/config_end.hpp>
223
+
224
+#endif   //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP
0 225
new file mode 100755
... ...
@@ -0,0 +1,111 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+//
3
+// (C) Copyright Ion Gaztanaga 2012-2012. Distributed under the Boost
4
+// Software License, Version 1.0. (See accompanying file
5
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
+//
7
+// See http://www.boost.org/libs/interprocess for documentation.
8
+//
9
+//////////////////////////////////////////////////////////////////////////////
10
+
11
+#ifndef BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
12
+#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP
13
+
14
+#ifndef BOOST_CONFIG_HPP
15
+#  include <boost/config.hpp>
16
+#endif
17
+#
18
+#if defined(BOOST_HAS_PRAGMA_ONCE)
19
+#  pragma once
20
+#endif
21
+
22
+#include <boost/interprocess/detail/config_begin.hpp>
23
+#include <boost/interprocess/detail/workaround.hpp>
24
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
25
+
26
+namespace boost {
27
+namespace interprocess {
28
+namespace ipcdetail {
29
+
30
+template<class Lock>
31
+class internal_mutex_lock
32
+{
33
+   typedef void (internal_mutex_lock::*unspecified_bool_type)();
34
+   public:
35
+
36
+   typedef typename Lock::mutex_type::internal_mutex_type  mutex_type;
37
+
38
+
39
+   BOOST_INTERPROCESS_FORCEINLINE internal_mutex_lock(Lock &l)
40
+      : l_(l)
41
+   {}
42
+
43
+   BOOST_INTERPROCESS_FORCEINLINE mutex_type* mutex() const
44
+   {  return l_ ? &l_.mutex()->internal_mutex() : 0;  }
45
+
46
+   BOOST_INTERPROCESS_FORCEINLINE void lock()    { l_.lock(); }
47
+
48
+   BOOST_INTERPROCESS_FORCEINLINE void unlock()  { l_.unlock(); }
49
+
50
+   BOOST_INTERPROCESS_FORCEINLINE operator unspecified_bool_type() const
51
+   {  return l_ ? &internal_mutex_lock::lock : 0;  }
52
+
53
+   private:
54
+   Lock &l_;
55
+};
56
+
57
+template <class Lock>
58
+class lock_inverter
59
+{
60
+   Lock &l_;
61
+   public:
62
+   BOOST_INTERPROCESS_FORCEINLINE lock_inverter(Lock &l)
63
+      :  l_(l)
64
+   {}
65
+
66
+   BOOST_INTERPROCESS_FORCEINLINE void lock()    {   l_.unlock();   }
67
+
68
+   BOOST_INTERPROCESS_FORCEINLINE void unlock()  {   l_.lock();     }
69
+};
70
+
71
+template <class Lock>
72
+class lock_to_sharable
73
+{
74
+   Lock &l_;
75
+
76
+   public:
77
+   BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_sharable(Lock &l)
78
+      :  l_(l)
79
+   {}
80
+
81
+   BOOST_INTERPROCESS_FORCEINLINE void lock()    {  l_.lock_sharable();     }
82
+
83
+   BOOST_INTERPROCESS_FORCEINLINE bool try_lock(){  return l_.try_lock_sharable(); }
84
+
85
+   BOOST_INTERPROCESS_FORCEINLINE void unlock()  {  l_.unlock_sharable();   }
86
+};
87
+
88
+template <class Lock>
89
+class lock_to_wait
90
+{
91
+   Lock &l_;
92
+
93
+   public:
94
+   BOOST_INTERPROCESS_FORCEINLINE explicit lock_to_wait(Lock &l)
95
+      :  l_(l)
96
+   {}
97
+   BOOST_INTERPROCESS_FORCEINLINE void lock()     {  l_.wait();     }
98
+
99
+   BOOST_INTERPROCESS_FORCEINLINE bool try_lock() {  return l_.try_wait(); }
100
+
101
+   BOOST_INTERPROCESS_FORCEINLINE bool timed_lock(const boost::posix_time::ptime &abs_time)
102
+      {  return l_.timed_wait(abs_time);   }
103
+};
104
+
105
+}  //namespace ipcdetail
106
+}  //namespace interprocess
107
+}  //namespace boost
108
+
109
+#include <boost/interprocess/detail/config_end.hpp>
110
+
111
+#endif   //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP