Browse code

Add more headers

Steffen Neumann authored on 18/01/2022 09:43:12
Showing21 changed files

1 1
new file mode 100755
... ...
@@ -0,0 +1,284 @@
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_FILE_LOCK_HPP
12
+#define BOOST_INTERPROCESS_FILE_LOCK_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/exceptions.hpp>
25
+#include <boost/interprocess/detail/os_file_functions.hpp>
26
+#include <boost/interprocess/detail/os_thread_functions.hpp>
27
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
28
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
29
+#include <boost/interprocess/sync/detail/locks.hpp>
30
+#include <boost/move/utility_core.hpp>
31
+
32
+//!\file
33
+//!Describes a class that wraps file locking capabilities.
34
+
35
+namespace boost {
36
+namespace interprocess {
37
+
38
+
39
+//!A file lock, is a mutual exclusion utility similar to a mutex using a
40
+//!file. A file lock has sharable and exclusive locking capabilities and
41
+//!can be used with scoped_lock and sharable_lock classes.
42
+//!A file lock can't guarantee synchronization between threads of the same
43
+//!process so just use file locks to synchronize threads from different processes.
44
+class file_lock
45
+{
46
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
47
+   //Non-copyable
48
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock)
49
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
50
+
51
+   public:
52
+   //!Constructs an empty file mapping.
53
+   //!Does not throw
54
+   file_lock() BOOST_NOEXCEPT
55
+      :  m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
56
+   {}
57
+
58
+   //!Opens a file lock. Throws interprocess_exception if the file does not
59
+   //!exist or there are no operating system resources.
60
+   file_lock(const char *name);
61
+
62
+   #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
63
+   //!Opens a file lock. Throws interprocess_exception if the file does not
64
+   //!exist or there are no operating system resources.
65
+   //! 
66
+   //!Note: This function is only available on operating systems with
67
+   //!      native wchar_t APIs (e.g. Windows).
68
+   file_lock(const wchar_t *name);
69
+   #endif
70
+
71
+   //!Moves the ownership of "moved"'s file mapping object to *this.
72
+   //!After the call, "moved" does not represent any file mapping object.
73
+   //!Does not throw
74
+   file_lock(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT
75
+      :  m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
76
+   {  this->swap(moved);   }
77
+
78
+   //!Moves the ownership of "moved"'s file mapping to *this.
79
+   //!After the call, "moved" does not represent any file mapping.
80
+   //!Does not throw
81
+   file_lock &operator=(BOOST_RV_REF(file_lock) moved) BOOST_NOEXCEPT
82
+   {
83
+      file_lock tmp(boost::move(moved));
84
+      this->swap(tmp);
85
+      return *this;
86
+   }
87
+
88
+   //!Closes a file lock. Does not throw.
89
+   ~file_lock();
90
+
91
+   //!Swaps two file_locks.
92
+   //!Does not throw.
93
+   void swap(file_lock &other) BOOST_NOEXCEPT
94
+   {
95
+      file_handle_t tmp = m_file_hnd;
96
+      m_file_hnd = other.m_file_hnd;
97
+      other.m_file_hnd = tmp;
98
+   }
99
+
100
+   //Exclusive locking
101
+
102
+   //!Requires: The calling thread does not own the mutex.
103
+   //!
104
+   //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
105
+   //!   and if another thread has exclusive, or sharable ownership of
106
+   //!   the mutex, it waits until it can obtain the ownership.
107
+   //!Throws: interprocess_exception on error.
108
+   //!
109
+   //!Note: A program may deadlock if the thread that has ownership calls 
110
+   //!   this function. If the implementation can detect the deadlock,
111
+   //!   an exception could be thrown.
112
+   void lock();
113
+
114
+   //!Requires: The calling thread does not own the mutex.
115
+   //!
116
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
117
+   //!   without waiting. If no other thread has exclusive, or sharable
118
+   //!   ownership of the mutex this succeeds.
119
+   //!Returns: If it can acquire exclusive ownership immediately returns true.
120
+   //!   If it has to wait, returns false.
121
+   //!Throws: interprocess_exception on error.
122
+   //! 
123
+   //!Note: A program may deadlock if the thread that has ownership calls 
124
+   //!   this function. If the implementation can detect the deadlock,
125
+   //!   an exception could be thrown.
126
+   bool try_lock();
127
+
128
+   //!Requires: The calling thread does not own the mutex.
129
+   //!
130
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
131
+   //!   waiting if necessary until no other thread has exclusive, or sharable
132
+   //!   ownership of the mutex or abs_time is reached.
133
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
134
+   //!Throws: interprocess_exception on error.
135
+   //! 
136
+   //!Note: A program may deadlock if the thread that has ownership calls 
137
+   //!   this function. If the implementation can detect the deadlock,
138
+   //!   an exception could be thrown.
139
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
140
+
141
+   //!Precondition: The thread must have exclusive ownership of the mutex.
142
+   //!Effects: The calling thread releases the exclusive ownership of the mutex.
143
+   //!Throws: An exception derived from interprocess_exception on error.
144
+   void unlock();
145
+
146
+   //Sharable locking
147
+
148
+   //!Requires: The calling thread does not own the mutex.
149
+   //!
150
+   //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
151
+   //!   and if another thread has exclusive ownership of the mutex, waits until
152
+   //!   it can obtain the ownership.
153
+   //!Throws: interprocess_exception on error.
154
+   //!
155
+   //!Note: A program may deadlock if the thread that owns a mutex object calls 
156
+   //!   this function. If the implementation can detect the deadlock,
157
+   //!   an exception could be thrown.
158
+   void lock_sharable();
159
+
160
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
161
+   //!   without waiting. If no other thread has exclusive ownership of the
162
+   //!   mutex this succeeds.
163
+   //!Returns: If it can acquire sharable ownership immediately returns true. If it
164
+   //!   has to wait, returns false.
165
+   //!Throws: interprocess_exception on error.
166
+   bool try_lock_sharable();
167
+
168
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
169
+   //!   waiting if necessary until no other thread has exclusive ownership of
170
+   //!   the mutex or abs_time is reached.
171
+   //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
172
+   //!Throws: interprocess_exception on error.
173
+   bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
174
+
175
+   //!Precondition: The thread must have sharable ownership of the mutex.
176
+   //!Effects: The calling thread releases the sharable ownership of the mutex.
177
+   //!Throws: An exception derived from interprocess_exception on error.
178
+   void unlock_sharable();
179
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
180
+   private:
181
+   file_handle_t m_file_hnd;
182
+
183
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
184
+};
185
+
186
+inline file_lock::file_lock(const char *name)
187
+{
188
+   m_file_hnd = ipcdetail::open_existing_file(name, read_write);
189
+
190
+   if(m_file_hnd == ipcdetail::invalid_file()){
191
+      error_info err(system_error_code());
192
+      throw interprocess_exception(err);
193
+   }
194
+}
195
+
196
+#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
197
+
198
+inline file_lock::file_lock(const wchar_t *name)
199
+{
200
+   m_file_hnd = ipcdetail::open_existing_file(name, read_write);
201
+
202
+   if(m_file_hnd == ipcdetail::invalid_file()){
203
+      error_info err(system_error_code());
204
+      throw interprocess_exception(err);
205
+   }
206
+}
207
+
208
+#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
209
+
210
+inline file_lock::~file_lock()
211
+{
212
+   if(m_file_hnd != ipcdetail::invalid_file()){
213
+      ipcdetail::close_file(m_file_hnd);
214
+      m_file_hnd = ipcdetail::invalid_file();
215
+   }
216
+}
217
+
218
+inline void file_lock::lock()
219
+{
220
+   if(!ipcdetail::acquire_file_lock(m_file_hnd)){
221
+      error_info err(system_error_code());
222
+      throw interprocess_exception(err);
223
+   }
224
+}
225
+
226
+inline bool file_lock::try_lock()
227
+{
228
+   bool result;
229
+   if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){
230
+      error_info err(system_error_code());
231
+      throw interprocess_exception(err);
232
+   }
233
+   return result;
234
+}
235
+
236
+inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
237
+{  return ipcdetail::try_based_timed_lock(*this, abs_time);   }
238
+
239
+inline void file_lock::unlock()
240
+{
241
+   if(!ipcdetail::release_file_lock(m_file_hnd)){
242
+      error_info err(system_error_code());
243
+      throw interprocess_exception(err);
244
+   }
245
+}
246
+
247
+inline void file_lock::lock_sharable()
248
+{
249
+   if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){
250
+      error_info err(system_error_code());
251
+      throw interprocess_exception(err);
252
+   }
253
+}
254
+
255
+inline bool file_lock::try_lock_sharable()
256
+{
257
+   bool result;
258
+   if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){
259
+      error_info err(system_error_code());
260
+      throw interprocess_exception(err);
261
+   }
262
+   return result;
263
+}
264
+
265
+inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
266
+{
267
+   ipcdetail::lock_to_sharable<file_lock> lsh(*this);
268
+   return ipcdetail::try_based_timed_lock(lsh, abs_time);
269
+}
270
+
271
+inline void file_lock::unlock_sharable()
272
+{
273
+   if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){
274
+      error_info err(system_error_code());
275
+      throw interprocess_exception(err);
276
+   }
277
+}
278
+
279
+}  //namespace interprocess {
280
+}  //namespace boost {
281
+
282
+#include <boost/interprocess/detail/config_end.hpp>
283
+
284
+#endif   //BOOST_INTERPROCESS_FILE_LOCK_HPP
0 285
new file mode 100755
... ...
@@ -0,0 +1,160 @@
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_CONDITION_HPP
12
+#define BOOST_INTERPROCESS_CONDITION_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
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
23
+
24
+#include <boost/interprocess/detail/config_begin.hpp>
25
+#include <boost/interprocess/detail/workaround.hpp>
26
+
27
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
28
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
29
+#include <boost/interprocess/sync/detail/locks.hpp>
30
+#include <boost/interprocess/exceptions.hpp>
31
+#include <boost/limits.hpp>
32
+#include <boost/assert.hpp>
33
+
34
+#if   !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
35
+   #include <boost/interprocess/sync/posix/condition.hpp>
36
+   #define BOOST_INTERPROCESS_CONDITION_USE_POSIX
37
+//Experimental...
38
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
39
+   #include <boost/interprocess/sync/windows/condition.hpp>
40
+   #define BOOST_INTERPROCESS_CONDITION_USE_WINAPI
41
+#else
42
+   //spin_condition is used
43
+   #include <boost/interprocess/sync/spin/condition.hpp>
44
+#endif
45
+
46
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
47
+
48
+//!\file
49
+//!Describes process-shared variables interprocess_condition class
50
+
51
+namespace boost {
52
+
53
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
54
+
55
+namespace posix_time
56
+{  class ptime;   }
57
+
58
+#endif   //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
59
+
60
+namespace interprocess {
61
+
62
+class named_condition;
63
+
64
+//!This class is a condition variable that can be placed in shared memory or
65
+//!memory mapped files.
66
+//!Destroys the object of type std::condition_variable_any
67
+//!
68
+//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all
69
+//!threads have been only notified. It is required that they have exited their respective wait
70
+//!functions.
71
+class interprocess_condition
72
+{
73
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
74
+   //Non-copyable
75
+   interprocess_condition(const interprocess_condition &);
76
+   interprocess_condition &operator=(const interprocess_condition &);
77
+   friend class named_condition;
78
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
79
+
80
+   public:
81
+   //!Constructs a interprocess_condition. On error throws interprocess_exception.
82
+   interprocess_condition()
83
+   {}
84
+
85
+   //!Destroys *this
86
+   //!liberating system resources.
87
+   ~interprocess_condition()
88
+   {}
89
+
90
+   //!If there is a thread waiting on *this, change that
91
+   //!thread's state to ready. Otherwise there is no effect.
92
+   void notify_one()
93
+   {  m_condition.notify_one();  }
94
+
95
+   //!Change the state of all threads waiting on *this to ready.
96
+   //!If there are no waiting threads, notify_all() has no effect.
97
+   void notify_all()
98
+   {  m_condition.notify_all();  }
99
+
100
+   //!Releases the lock on the interprocess_mutex object associated with lock, blocks
101
+   //!the current thread of execution until readied by a call to
102
+   //!this->notify_one() or this->notify_all(), and then reacquires the lock.
103
+   template <typename L>
104
+   void wait(L& lock)
105
+   {
106
+      ipcdetail::internal_mutex_lock<L> internal_lock(lock);
107
+      m_condition.wait(internal_lock);
108
+   }
109
+
110
+   //!The same as:
111
+   //!while (!pred()) wait(lock)
112
+   template <typename L, typename Pr>
113
+   void wait(L& lock, Pr pred)
114
+   {
115
+      ipcdetail::internal_mutex_lock<L> internal_lock(lock);
116
+      m_condition.wait(internal_lock, pred);
117
+   }
118
+
119
+   //!Releases the lock on the interprocess_mutex object associated with lock, blocks
120
+   //!the current thread of execution until readied by a call to
121
+   //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
122
+   //!and then reacquires the lock.
123
+   //!Returns: false if time abs_time is reached, otherwise true.
124
+   template <typename L>
125
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
126
+   {
127
+      ipcdetail::internal_mutex_lock<L> internal_lock(lock);
128
+      return m_condition.timed_wait(internal_lock, abs_time);
129
+   }
130
+
131
+   //!The same as:   while (!pred()) {
132
+   //!                  if (!timed_wait(lock, abs_time)) return pred();
133
+   //!               } return true;
134
+   template <typename L, typename Pr>
135
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
136
+   {
137
+      ipcdetail::internal_mutex_lock<L> internal_lock(lock);
138
+      return m_condition.timed_wait(internal_lock, abs_time, pred);
139
+   }
140
+
141
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
142
+
143
+   private:
144
+   #if defined(BOOST_INTERPROCESS_CONDITION_USE_POSIX)
145
+      ipcdetail::posix_condition m_condition;
146
+   #elif defined(BOOST_INTERPROCESS_CONDITION_USE_WINAPI)
147
+      ipcdetail::winapi_condition m_condition;
148
+   #else
149
+      ipcdetail::spin_condition m_condition;
150
+   #endif
151
+
152
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
153
+};
154
+
155
+}  //namespace interprocess
156
+}  // namespace boost
157
+
158
+#include <boost/interprocess/detail/config_end.hpp>
159
+
160
+#endif // BOOST_INTERPROCESS_CONDITION_HPP
0 161
new file mode 100755
... ...
@@ -0,0 +1,137 @@
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_CONDITION_ANY_HPP
12
+#define BOOST_INTERPROCESS_CONDITION_ANY_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
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
23
+
24
+#include <boost/interprocess/detail/config_begin.hpp>
25
+#include <boost/interprocess/detail/workaround.hpp>
26
+
27
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
28
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
29
+#include <boost/interprocess/sync/interprocess_condition.hpp>
30
+#include <boost/interprocess/exceptions.hpp>
31
+#include <boost/interprocess/sync/detail/condition_any_algorithm.hpp>
32
+
33
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
34
+
35
+//!\file
36
+//!Describes process-shared variables interprocess_condition_any class
37
+
38
+namespace boost {
39
+
40
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
41
+
42
+namespace posix_time
43
+{  class ptime;   }
44
+
45
+#endif   //#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
46
+
47
+namespace interprocess {
48
+
49
+//!This class is a condition variable that can be placed in shared memory or
50
+//!memory mapped files.
51
+//!
52
+//!The interprocess_condition_any class is a generalization of interprocess_condition.
53
+//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex
54
+//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable
55
+//!requirements (lock()/unlock() member functions).
56
+//!
57
+//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all
58
+//!threads have been only notified. It is required that they have exited their respective wait
59
+//!functions.
60
+class interprocess_condition_any
61
+{
62
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
63
+   //Non-copyable
64
+   interprocess_condition_any(const interprocess_condition_any &);
65
+   interprocess_condition_any &operator=(const interprocess_condition_any &);
66
+
67
+   class members
68
+   {
69
+      public:
70
+      typedef interprocess_condition   condvar_type;
71
+      typedef interprocess_mutex       mutex_type;
72
+
73
+      condvar_type &get_condvar() {  return m_cond;  }
74
+      mutex_type   &get_mutex()   {  return m_mut; }
75
+
76
+      private:
77
+      condvar_type   m_cond;
78
+      mutex_type     m_mut;
79
+   };
80
+
81
+   ipcdetail::condition_any_wrapper<members>   m_cond;
82
+
83
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
84
+   public:
85
+   //!Constructs a interprocess_condition_any. On error throws interprocess_exception.
86
+   interprocess_condition_any(){}
87
+
88
+   //!Destroys *this
89
+   //!liberating system resources.
90
+   ~interprocess_condition_any(){}
91
+
92
+   //!If there is a thread waiting on *this, change that
93
+   //!thread's state to ready. Otherwise there is no effect.
94
+   void notify_one()
95
+   {  m_cond.notify_one();  }
96
+
97
+   //!Change the state of all threads waiting on *this to ready.
98
+   //!If there are no waiting threads, notify_all() has no effect.
99
+   void notify_all()
100
+   {  m_cond.notify_all();  }
101
+
102
+   //!Releases the lock on the interprocess_mutex object associated with lock, blocks
103
+   //!the current thread of execution until readied by a call to
104
+   //!this->notify_one() or this->notify_all(), and then reacquires the lock.
105
+   template <typename L>
106
+   void wait(L& lock)
107
+   {  m_cond.wait(lock);  }
108
+
109
+   //!The same as:
110
+   //!while (!pred()) wait(lock)
111
+   template <typename L, typename Pr>
112
+   void wait(L& lock, Pr pred)
113
+   {  m_cond.wait(lock, pred);  }
114
+
115
+   //!Releases the lock on the interprocess_mutex object associated with lock, blocks
116
+   //!the current thread of execution until readied by a call to
117
+   //!this->notify_one() or this->notify_all(), or until time abs_time is reached,
118
+   //!and then reacquires the lock.
119
+   //!Returns: false if time abs_time is reached, otherwise true.
120
+   template <typename L>
121
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time)
122
+   {  return m_cond.timed_wait(lock, abs_time);  }
123
+
124
+   //!The same as:   while (!pred()) {
125
+   //!                  if (!timed_wait(lock, abs_time)) return pred();
126
+   //!               } return true;
127
+   template <typename L, typename Pr>
128
+   bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred)
129
+   {  return m_cond.timed_wait(lock, abs_time, pred);  }
130
+};
131
+
132
+}  //namespace interprocess
133
+}  // namespace boost
134
+
135
+#include <boost/interprocess/detail/config_end.hpp>
136
+
137
+#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP
0 138
new file mode 100755
... ...
@@ -0,0 +1,186 @@
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
+// Parts of the pthread code come from Boost Threads code.
12
+//
13
+//////////////////////////////////////////////////////////////////////////////
14
+
15
+#ifndef BOOST_INTERPROCESS_MUTEX_HPP
16
+#define BOOST_INTERPROCESS_MUTEX_HPP
17
+
18
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
19
+
20
+#ifndef BOOST_CONFIG_HPP
21
+#  include <boost/config.hpp>
22
+#endif
23
+#
24
+#if defined(BOOST_HAS_PRAGMA_ONCE)
25
+#  pragma once
26
+#endif
27
+
28
+#include <boost/interprocess/detail/config_begin.hpp>
29
+#include <boost/interprocess/exceptions.hpp>
30
+#include <boost/interprocess/detail/workaround.hpp>
31
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
32
+#include <boost/assert.hpp>
33
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
34
+
35
+#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)
36
+   #include <boost/interprocess/sync/posix/mutex.hpp>
37
+   #define BOOST_INTERPROCESS_MUTEX_USE_POSIX
38
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
39
+   //Experimental...
40
+   #define BOOST_INTERPROCESS_MUTEX_USE_WINAPI
41
+   #include <boost/interprocess/sync/windows/mutex.hpp>
42
+#else
43
+   //spin_mutex is used
44
+   #include <boost/interprocess/sync/spin/mutex.hpp>
45
+   namespace boost {
46
+   namespace interprocess {
47
+   namespace ipcdetail{
48
+   namespace robust_emulation_helpers {
49
+
50
+   template<class T>
51
+   class mutex_traits;
52
+
53
+   }}}}
54
+#endif
55
+
56
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
57
+
58
+//!\file
59
+//!Describes a mutex class that can be placed in memory shared by
60
+//!several processes.
61
+
62
+namespace boost {
63
+namespace interprocess {
64
+
65
+class interprocess_condition;
66
+
67
+//!Wraps a interprocess_mutex that can be placed in shared memory and can be
68
+//!shared between processes. Allows timed lock tries
69
+class interprocess_mutex
70
+{
71
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
72
+   //Non-copyable
73
+   interprocess_mutex(const interprocess_mutex &);
74
+   interprocess_mutex &operator=(const interprocess_mutex &);
75
+   friend class interprocess_condition;
76
+
77
+   public:
78
+   #if defined(BOOST_INTERPROCESS_MUTEX_USE_POSIX)
79
+      typedef ipcdetail::posix_mutex internal_mutex_type;
80
+   #elif defined(BOOST_INTERPROCESS_MUTEX_USE_WINAPI)
81
+      typedef ipcdetail::winapi_mutex internal_mutex_type;
82
+   #else
83
+      typedef ipcdetail::spin_mutex internal_mutex_type;
84
+      private:
85
+      friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_mutex>;
86
+      void take_ownership(){ m_mutex.take_ownership(); }
87
+      public:
88
+   #endif
89
+
90
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
91
+   public:
92
+
93
+   //!Constructor.
94
+   //!Throws interprocess_exception on error.
95
+   interprocess_mutex();
96
+
97
+   //!Destructor. If any process uses the mutex after the destructor is called
98
+   //!the result is undefined. Does not throw.
99
+   ~interprocess_mutex();
100
+
101
+   //!Requires: The calling thread does not own the mutex.
102
+   //!
103
+   //!Effects: The calling thread tries to obtain ownership of the mutex, and
104
+   //!   if another thread has ownership of the mutex, it waits until it can
105
+   //!   obtain the ownership. If a thread takes ownership of the mutex the
106
+   //!   mutex must be unlocked by the same mutex.
107
+   //!Throws: interprocess_exception on error.
108
+   //! 
109
+   //!Note: A program may deadlock if the thread that has ownership calls 
110
+   //!   this function. If the implementation can detect the deadlock,
111
+   //!   an exception could be thrown.
112
+   void lock();
113
+
114
+   //!Requires: The calling thread does not own the mutex.
115
+   //!
116
+   //!Effects: The calling thread tries to obtain ownership of the mutex, and
117
+   //!   if another thread has ownership of the mutex returns immediately.
118
+   //!Returns: If the thread acquires ownership of the mutex, returns true, if
119
+   //!   the another thread has ownership of the mutex, returns false.
120
+   //!Throws: interprocess_exception on error.
121
+   //! 
122
+   //!Note: A program may deadlock if the thread that has ownership calls 
123
+   //!   this function. If the implementation can detect the deadlock,
124
+   //!   an exception could be thrown.
125
+   bool try_lock();
126
+
127
+   //!Requires: The calling thread does not own the mutex.
128
+   //!
129
+   //!Effects: The calling thread will try to obtain exclusive ownership of the
130
+   //!   mutex if it can do so in until the specified time is reached. If the
131
+   //!   mutex supports recursive locking, the mutex must be unlocked the same
132
+   //!   number of times it is locked.
133
+   //!Returns: If the thread acquires ownership of the mutex, returns true, if
134
+   //!   the timeout expires returns false.
135
+   //!Throws: interprocess_exception on error.
136
+   //! 
137
+   //!Note: A program may deadlock if the thread that has ownership calls 
138
+   //!   this function. If the implementation can detect the deadlock,
139
+   //!   an exception could be thrown.
140
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
141
+
142
+   //!Effects: The calling thread releases the exclusive ownership of the mutex.
143
+   //!Throws: interprocess_exception on error.
144
+   void unlock();
145
+
146
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
147
+   internal_mutex_type &internal_mutex()
148
+   {  return m_mutex;   }
149
+
150
+   const internal_mutex_type &internal_mutex() const
151
+   {  return m_mutex;   }
152
+
153
+   private:
154
+   internal_mutex_type m_mutex;
155
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
156
+};
157
+
158
+}  //namespace interprocess {
159
+}  //namespace boost {
160
+
161
+
162
+namespace boost {
163
+namespace interprocess {
164
+
165
+inline interprocess_mutex::interprocess_mutex(){}
166
+
167
+inline interprocess_mutex::~interprocess_mutex(){}
168
+
169
+inline void interprocess_mutex::lock()
170
+{  ipcdetail::timeout_when_locking_aware_lock(m_mutex);  }
171
+
172
+inline bool interprocess_mutex::try_lock()
173
+{ return m_mutex.try_lock(); }
174
+
175
+inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
176
+{ return m_mutex.timed_lock(abs_time); }
177
+
178
+inline void interprocess_mutex::unlock()
179
+{ m_mutex.unlock(); }
180
+
181
+}  //namespace interprocess {
182
+}  //namespace boost {
183
+
184
+#include <boost/interprocess/detail/config_end.hpp>
185
+
186
+#endif   //BOOST_INTERPROCESS_MUTEX_HPP
0 187
new file mode 100755
... ...
@@ -0,0 +1,172 @@
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
+// Parts of the pthread code come from Boost Threads code:
12
+//
13
+//////////////////////////////////////////////////////////////////////////////
14
+//
15
+// Copyright (C) 2001-2003
16
+// William E. Kempf
17
+//
18
+// Permission to use, copy, modify, distribute and sell this software
19
+// and its documentation for any purpose is hereby granted without fee,
20
+// provided that the above copyright notice appear in all copies and
21
+// that both that copyright notice and this permission notice appear
22
+// in supporting documentation.  William E. Kempf makes no representations
23
+// about the suitability of this software for any purpose.
24
+// It is provided "as is" without express or implied warranty.
25
+//////////////////////////////////////////////////////////////////////////////
26
+
27
+#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
28
+#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
29
+
30
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
31
+
32
+#ifndef BOOST_CONFIG_HPP
33
+#  include <boost/config.hpp>
34
+#endif
35
+#
36
+#if defined(BOOST_HAS_PRAGMA_ONCE)
37
+#  pragma once
38
+#endif
39
+
40
+#include <boost/interprocess/detail/config_begin.hpp>
41
+#include <boost/interprocess/detail/workaround.hpp>
42
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
43
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
44
+#include <boost/assert.hpp>
45
+
46
+#if   !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
47
+       defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) && \
48
+       defined (BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES)
49
+   //Experimental...
50
+   #include <boost/interprocess/sync/posix/recursive_mutex.hpp>
51
+   #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX
52
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
53
+   #include <boost/interprocess/sync/windows/recursive_mutex.hpp>
54
+   #define BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI
55
+#else
56
+   //spin_recursive_mutex is used
57
+   #include <boost/interprocess/sync/spin/recursive_mutex.hpp>
58
+   namespace boost {
59
+   namespace interprocess {
60
+   namespace ipcdetail{
61
+   namespace robust_emulation_helpers {
62
+
63
+   template<class T>
64
+   class mutex_traits;
65
+
66
+   }}}}
67
+#endif
68
+
69
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
70
+
71
+//!\file
72
+//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes
73
+
74
+namespace boost {
75
+namespace interprocess {
76
+
77
+//!Wraps a interprocess_mutex that can be placed in shared memory and can be
78
+//!shared between processes. Allows several locking calls by the same
79
+//!process. Allows timed lock tries
80
+class interprocess_recursive_mutex
81
+{
82
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
83
+   //Non-copyable
84
+   interprocess_recursive_mutex(const interprocess_recursive_mutex &);
85
+   interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &);
86
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
87
+   public:
88
+   //!Constructor.
89
+   //!Throws interprocess_exception on error.
90
+   interprocess_recursive_mutex();
91
+
92
+   //!Destructor. If any process uses the mutex after the destructor is called
93
+   //!the result is undefined. Does not throw.
94
+  ~interprocess_recursive_mutex();
95
+
96
+   //!Effects: The calling thread tries to obtain ownership of the mutex, and
97
+   //!   if another thread has ownership of the mutex, it waits until it can
98
+   //!   obtain the ownership. If a thread takes ownership of the mutex the
99
+   //!   mutex must be unlocked by the same mutex. The mutex must be unlocked
100
+   //!   the same number of times it is locked.
101
+   //!Throws: interprocess_exception on error.
102
+   //! 
103
+   //!Note: A program shall not deadlock if the thread that has ownership calls 
104
+   //!   this function. 
105
+   void lock();
106
+
107
+   //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex
108
+   //!is already locked, returns true when success. The mutex must be unlocked
109
+   //!the same number of times it is locked.
110
+   //!Throws: interprocess_exception if a severe error is found
111
+   //! 
112
+   //!Note: A program shall not deadlock if the thread that has ownership calls 
113
+   //!   this function. 
114
+   bool try_lock();
115
+
116
+   //!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before
117
+   //!abs_time time, returns false. The mutex must be unlocked
118
+   //!   the same number of times it is locked.
119
+   //!Throws: interprocess_exception if a severe error is found
120
+   //! 
121
+   //!Note: A program shall not deadlock if the thread that has ownership calls 
122
+   //!   this function. 
123
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
124
+
125
+   //!Effects: The calling thread releases the exclusive ownership of the mutex.
126
+   //!   If the mutex supports recursive locking, the mutex must be unlocked the
127
+   //!   same number of times it is locked.
128
+   //!Throws: interprocess_exception on error.
129
+   void unlock();
130
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
131
+   private:
132
+
133
+   #if defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_POSIX)
134
+      ipcdetail::posix_recursive_mutex mutex;
135
+   #elif defined(BOOST_INTERPROCESS_RECURSIVE_MUTEX_USE_WINAPI)
136
+      ipcdetail::winapi_recursive_mutex mutex;
137
+   #else
138
+      void take_ownership(){ mutex.take_ownership(); }
139
+      friend class ipcdetail::robust_emulation_helpers::mutex_traits<interprocess_recursive_mutex>;
140
+      ipcdetail::spin_recursive_mutex mutex;
141
+   #endif
142
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
143
+};
144
+
145
+}  //namespace interprocess {
146
+}  //namespace boost {
147
+
148
+namespace boost {
149
+namespace interprocess {
150
+
151
+inline interprocess_recursive_mutex::interprocess_recursive_mutex(){}
152
+
153
+inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
154
+
155
+inline void interprocess_recursive_mutex::lock()
156
+{  ipcdetail::timeout_when_locking_aware_lock(mutex);  }
157
+
158
+inline bool interprocess_recursive_mutex::try_lock()
159
+{ return mutex.try_lock(); }
160
+
161
+inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
162
+{ return mutex.timed_lock(abs_time); }
163
+
164
+inline void interprocess_recursive_mutex::unlock()
165
+{ mutex.unlock(); }
166
+
167
+}  //namespace interprocess {
168
+}  //namespace boost {
169
+
170
+#include <boost/interprocess/detail/config_end.hpp>
171
+
172
+#endif   //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP
0 173
new file mode 100755
... ...
@@ -0,0 +1,142 @@
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_SEMAPHORE_HPP
12
+#define BOOST_INTERPROCESS_SEMAPHORE_HPP
13
+
14
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
15
+
16
+#ifndef BOOST_CONFIG_HPP
17
+#  include <boost/config.hpp>
18
+#endif
19
+#
20
+#if defined(BOOST_HAS_PRAGMA_ONCE)
21
+#  pragma once
22
+#endif
23
+
24
+#include <boost/interprocess/detail/config_begin.hpp>
25
+#include <boost/interprocess/detail/workaround.hpp>
26
+
27
+#include <boost/interprocess/creation_tags.hpp>
28
+#include <boost/interprocess/exceptions.hpp>
29
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
30
+#include <boost/interprocess/sync/detail/locks.hpp>
31
+#include <boost/interprocess/sync/detail/common_algorithms.hpp>
32
+
33
+#if   !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && \
34
+       defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED)    && \
35
+       defined(BOOST_INTERPROCESS_POSIX_UNNAMED_SEMAPHORES)
36
+   #include <boost/interprocess/sync/posix/semaphore.hpp>
37
+   #define BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX
38
+#elif !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS)
39
+   //Experimental...
40
+   #include <boost/interprocess/sync/windows/semaphore.hpp>
41
+   #define BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI
42
+#else
43
+   //spin_semaphore is used
44
+   #include <boost/interprocess/sync/spin/semaphore.hpp>
45
+#endif
46
+
47
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
48
+
49
+//!\file
50
+//!Describes a interprocess_semaphore class for inter-process synchronization
51
+
52
+namespace boost {
53
+namespace interprocess {
54
+
55
+//!Wraps a interprocess_semaphore that can be placed in shared memory and can be
56
+//!shared between processes. Allows timed lock tries
57
+class interprocess_semaphore
58
+{
59
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
60
+   //Non-copyable
61
+   interprocess_semaphore(const interprocess_semaphore &);
62
+   interprocess_semaphore &operator=(const interprocess_semaphore &);
63
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
64
+   public:
65
+   //!Creates a interprocess_semaphore with the given initial count.
66
+   //!interprocess_exception if there is an error.*/
67
+   interprocess_semaphore(unsigned int initialCount);
68
+
69
+   //!Destroys the interprocess_semaphore.
70
+   //!Does not throw
71
+   ~interprocess_semaphore();
72
+
73
+   //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting
74
+   //!for the interprocess_semaphore, then one of these processes will return successfully from
75
+   //!its wait function. If there is an error an interprocess_exception exception is thrown.
76
+   void post();
77
+
78
+   //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero,
79
+   //!then the calling process/thread blocks until it can decrement the counter.
80
+   //!If there is an error an interprocess_exception exception is thrown.
81
+   void wait();
82
+
83
+   //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero
84
+   //!and returns true. If the value is not greater than zero returns false.
85
+   //!If there is an error an interprocess_exception exception is thrown.
86
+   bool try_wait();
87
+
88
+   //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater
89
+   //!than zero and returns true. Otherwise, waits for the interprocess_semaphore
90
+   //!to the posted or the timeout expires. If the timeout expires, the
91
+   //!function returns false. If the interprocess_semaphore is posted the function
92
+   //!returns true. If there is an error throws sem_exception
93
+   bool timed_wait(const boost::posix_time::ptime &abs_time);
94
+
95
+   //!Returns the interprocess_semaphore count
96
+//   int get_count() const;
97
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
98
+   private:
99
+   #if defined(BOOST_INTERPROCESS_SEMAPHORE_USE_POSIX)
100
+      typedef ipcdetail::posix_semaphore internal_sem_t;
101
+   #elif defined(BOOST_INTERPROCESS_SEMAPHORE_USE_WINAPI)
102
+      typedef ipcdetail::winapi_semaphore internal_sem_t;
103
+   #else
104
+      typedef ipcdetail::spin_semaphore internal_sem_t;
105
+   #endif   //#if defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION)
106
+   internal_sem_t m_sem;
107
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
108
+};
109
+
110
+}  //namespace interprocess {
111
+}  //namespace boost {
112
+
113
+namespace boost {
114
+namespace interprocess {
115
+
116
+inline interprocess_semaphore::interprocess_semaphore(unsigned int initialCount)
117
+   : m_sem(initialCount)
118
+{}
119
+
120
+inline interprocess_semaphore::~interprocess_semaphore(){}
121
+
122
+inline void interprocess_semaphore::wait()
123
+{
124
+   ipcdetail::lock_to_wait<internal_sem_t> ltw(m_sem);
125
+   timeout_when_locking_aware_lock(ltw);
126
+}
127
+
128
+inline bool interprocess_semaphore::try_wait()
129
+{ return m_sem.try_wait(); }
130
+
131
+inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
132
+{ return m_sem.timed_wait(abs_time); }
133
+
134
+inline void interprocess_semaphore::post()
135
+{ m_sem.post(); }
136
+
137
+}  //namespace interprocess {
138
+}  //namespace boost {
139
+
140
+#include <boost/interprocess/detail/config_end.hpp>
141
+
142
+#endif   //BOOST_INTERPROCESS_SEMAPHORE_HPP
0 143
new file mode 100755
... ...
@@ -0,0 +1,385 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+//  Code based on Howard Hinnant's shared_mutex class
3
+//
4
+// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost
5
+// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt)
6
+//
7
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
8
+// Software License, Version 1.0. (See accompanying file
9
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10
+//
11
+// See http://www.boost.org/libs/interprocess for documentation.
12
+//
13
+//////////////////////////////////////////////////////////////////////////////
14
+
15
+#ifndef BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
16
+#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
17
+
18
+#ifndef BOOST_CONFIG_HPP
19
+#  include <boost/config.hpp>
20
+#endif
21
+#
22
+#if defined(BOOST_HAS_PRAGMA_ONCE)
23
+#  pragma once
24
+#endif
25
+
26
+#include <boost/interprocess/detail/config_begin.hpp>
27
+#include <boost/interprocess/detail/workaround.hpp>
28
+#include <boost/interprocess/sync/scoped_lock.hpp>
29
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
30
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
31
+#include <boost/interprocess/sync/interprocess_condition.hpp>
32
+#include <climits>
33
+
34
+
35
+//!\file
36
+//!Describes interprocess_sharable_mutex class
37
+
38
+namespace boost {
39
+namespace interprocess {
40
+
41
+//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be
42
+//!shared between processes. Allows timed lock tries
43
+class interprocess_sharable_mutex
44
+{
45
+   //Non-copyable
46
+   interprocess_sharable_mutex(const interprocess_sharable_mutex &);
47
+   interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &);
48
+
49
+   friend class interprocess_condition;
50
+   public:
51
+
52
+   //!Constructs the sharable lock.
53
+   //!Throws interprocess_exception on error.
54
+   interprocess_sharable_mutex();
55
+
56
+   //!Destroys the sharable lock.
57
+   //!Does not throw.
58
+   ~interprocess_sharable_mutex();
59
+
60
+   //Exclusive locking
61
+
62
+   //!Requires: The calling thread does not own the mutex.
63
+   //!
64
+   //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
65
+   //!   and if another thread has exclusive or sharable ownership of
66
+   //!   the mutex, it waits until it can obtain the ownership.
67
+   //!Throws: interprocess_exception on error.
68
+   //! 
69
+   //!Note: A program may deadlock if the thread that has ownership calls 
70
+   //!   this function. If the implementation can detect the deadlock,
71
+   //!   an exception could be thrown.
72
+   void lock();
73
+
74
+   //!Requires: The calling thread does not own the mutex.
75
+   //!
76
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
77
+   //!   without waiting. If no other thread has exclusive or sharable
78
+   //!   ownership of the mutex this succeeds.
79
+   //!Returns: If it can acquire exclusive ownership immediately returns true.
80
+   //!   If it has to wait, returns false.
81
+   //!Throws: interprocess_exception on error.
82
+   //! 
83
+   //!Note: A program may deadlock if the thread that has ownership calls 
84
+   //!   this function. If the implementation can detect the deadlock,
85
+   //!   an exception could be thrown.
86
+   bool try_lock();
87
+
88
+   //!Requires: The calling thread does not own the mutex.
89
+   //!
90
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
91
+   //!   waiting if necessary until no other thread has exclusive or sharable
92
+   //!   ownership of the mutex or abs_time is reached.
93
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
94
+   //!Throws: interprocess_exception on error.
95
+   //! 
96
+   //!Note: A program may deadlock if the thread that has ownership calls 
97
+   //!   this function. If the implementation can detect the deadlock,
98
+   //!   an exception could be thrown.
99
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
100
+
101
+   //!Precondition: The thread must have exclusive ownership of the mutex.
102
+   //!Effects: The calling thread releases the exclusive ownership of the mutex.
103
+   //!Throws: An exception derived from interprocess_exception on error.
104
+   void unlock();
105
+
106
+   //Sharable locking
107
+
108
+   //!Requires: The calling thread does not own the mutex.
109
+   //!
110
+   //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
111
+   //!   and if another thread has exclusive ownership of the mutex,
112
+   //!   waits until it can obtain the ownership.
113
+   //!Throws: interprocess_exception on error.
114
+   //! 
115
+   //!Note: A program may deadlock if the thread that has ownership calls 
116
+   //!   this function. If the implementation can detect the deadlock,
117
+   //!   an exception could be thrown.
118
+   void lock_sharable();
119
+
120
+   //!Requires: The calling thread does not own the mutex.
121
+   //!
122
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
123
+   //!   without waiting. If no other thread has exclusive ownership
124
+   //!   of the mutex this succeeds.
125
+   //!Returns: If it can acquire sharable ownership immediately returns true. If it
126
+   //!   has to wait, returns false.
127
+   //!Throws: interprocess_exception on error.
128
+   //! 
129
+   //!Note: A program may deadlock if the thread that has ownership calls 
130
+   //!   this function. If the implementation can detect the deadlock,
131
+   //!   an exception could be thrown.
132
+   bool try_lock_sharable();
133
+
134
+   //!Requires: The calling thread does not own the mutex.
135
+   //!
136
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
137
+   //!   waiting if necessary until no other thread has exclusive
138
+   //!   ownership of the mutex or abs_time is reached.
139
+   //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
140
+   //!Throws: interprocess_exception on error.
141
+   //! 
142
+   //!Note: A program may deadlock if the thread that has ownership calls 
143
+   //!   this function. If the implementation can detect the deadlock,
144
+   //!   an exception could be thrown.
145
+   bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
146
+
147
+   //!Precondition: The thread must have sharable ownership of the mutex.
148
+   //!Effects: The calling thread releases the sharable ownership of the mutex.
149
+   //!Throws: An exception derived from interprocess_exception on error.
150
+   void unlock_sharable();
151
+
152
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
153
+   private:
154
+   typedef scoped_lock<interprocess_mutex> scoped_lock_t;
155
+
156
+   //Pack all the control data in a word to be able
157
+   //to use atomic instructions in the future
158
+   struct control_word_t
159
+   {
160
+      unsigned exclusive_in   : 1;
161
+      unsigned num_shared     : sizeof(unsigned)*CHAR_BIT-1;
162
+   }                       m_ctrl;
163
+
164
+   interprocess_mutex      m_mut;
165
+   interprocess_condition  m_first_gate;
166
+   interprocess_condition  m_second_gate;
167
+
168
+   private:
169
+   //Rollback structures for exceptions or failure return values
170
+   struct exclusive_rollback
171
+   {
172
+      exclusive_rollback(control_word_t         &ctrl
173
+                        ,interprocess_condition &first_gate)
174
+         :  mp_ctrl(&ctrl), m_first_gate(first_gate)
175
+      {}
176
+
177
+      void release()
178
+      {  mp_ctrl = 0;   }
179
+
180
+      ~exclusive_rollback()
181
+      {
182
+         if(mp_ctrl){
183
+            mp_ctrl->exclusive_in = 0;
184
+            m_first_gate.notify_all();
185
+         }
186
+      }
187
+      control_word_t          *mp_ctrl;
188
+      interprocess_condition  &m_first_gate;
189
+   };
190
+
191
+   template<int Dummy>
192
+   struct base_constants_t
193
+   {
194
+      static const unsigned max_readers
195
+         = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1));
196
+   };
197
+   typedef base_constants_t<0> constants;
198
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
199
+};
200
+
201
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
202
+
203
+template <int Dummy>
204
+const unsigned interprocess_sharable_mutex::base_constants_t<Dummy>::max_readers;
205
+
206
+inline interprocess_sharable_mutex::interprocess_sharable_mutex()
207
+{
208
+   this->m_ctrl.exclusive_in  = 0;
209
+   this->m_ctrl.num_shared   = 0;
210
+}
211
+
212
+inline interprocess_sharable_mutex::~interprocess_sharable_mutex()
213
+{}
214
+
215
+inline void interprocess_sharable_mutex::lock()
216
+{
217
+   scoped_lock_t lck(m_mut);
218
+
219
+   //The exclusive lock must block in the first gate
220
+   //if an exclusive lock has been acquired
221
+   while (this->m_ctrl.exclusive_in){
222
+      this->m_first_gate.wait(lck);
223
+   }
224
+
225
+   //Mark that exclusive lock has been acquired
226
+   this->m_ctrl.exclusive_in = 1;
227
+
228
+   //Prepare rollback
229
+   exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
230
+
231
+   //Now wait until all readers are gone
232
+   while (this->m_ctrl.num_shared){
233
+      this->m_second_gate.wait(lck);
234
+   }
235
+   rollback.release();
236
+}
237
+
238
+inline bool interprocess_sharable_mutex::try_lock()
239
+{
240
+   scoped_lock_t lck(m_mut, try_to_lock);
241
+
242
+   //If we can't lock or any has there is any exclusive
243
+   //or sharable mark return false;
244
+   if(!lck.owns()
245
+      || this->m_ctrl.exclusive_in
246
+      || this->m_ctrl.num_shared){
247
+      return false;
248
+   }
249
+   this->m_ctrl.exclusive_in = 1;
250
+   return true;
251
+}
252
+
253
+inline bool interprocess_sharable_mutex::timed_lock
254
+   (const boost::posix_time::ptime &abs_time)
255
+{
256
+   scoped_lock_t lck(m_mut, abs_time);
257
+   if(!lck.owns())   return false;
258
+
259
+   //The exclusive lock must block in the first gate
260
+   //if an exclusive lock has been acquired
261
+   while (this->m_ctrl.exclusive_in){
262
+      //Mutexes and condvars handle just fine infinite abs_times
263
+      //so avoid checking it here
264
+      if(!this->m_first_gate.timed_wait(lck, abs_time)){
265
+         if(this->m_ctrl.exclusive_in){
266
+            return false;
267
+         }
268
+         break;
269
+      }
270
+   }
271
+
272
+   //Mark that exclusive lock has been acquired
273
+   this->m_ctrl.exclusive_in = 1;
274
+
275
+   //Prepare rollback
276
+   exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
277
+
278
+   //Now wait until all readers are gone
279
+   while (this->m_ctrl.num_shared){
280
+      //Mutexes and condvars handle just fine infinite abs_times
281
+      //so avoid checking it here
282
+      if(!this->m_second_gate.timed_wait(lck, abs_time)){
283
+         if(this->m_ctrl.num_shared){
284
+            return false;
285
+         }
286
+         break;
287
+      }
288
+   }
289
+   rollback.release();
290
+   return true;
291
+}
292
+
293
+inline void interprocess_sharable_mutex::unlock()
294
+{
295
+   scoped_lock_t lck(m_mut);
296
+   this->m_ctrl.exclusive_in = 0;
297
+   this->m_first_gate.notify_all();
298
+}
299
+
300
+//Sharable locking
301
+
302
+inline void interprocess_sharable_mutex::lock_sharable()
303
+{
304
+   scoped_lock_t lck(m_mut);
305
+
306
+   //The sharable lock must block in the first gate
307
+   //if an exclusive lock has been acquired
308
+   //or there are too many sharable locks
309
+   while(this->m_ctrl.exclusive_in
310
+        || this->m_ctrl.num_shared == constants::max_readers){
311
+      this->m_first_gate.wait(lck);
312
+   }
313
+
314
+   //Increment sharable count
315
+   ++this->m_ctrl.num_shared;
316
+}
317
+
318
+inline bool interprocess_sharable_mutex::try_lock_sharable()
319
+{
320
+   scoped_lock_t lck(m_mut, try_to_lock);
321
+
322
+   //The sharable lock must fail
323
+   //if an exclusive lock has been acquired
324
+   //or there are too many sharable locks
325
+   if(!lck.owns()
326
+      || this->m_ctrl.exclusive_in
327
+      || this->m_ctrl.num_shared == constants::max_readers){
328
+      return false;
329
+   }
330
+
331
+   //Increment sharable count
332
+   ++this->m_ctrl.num_shared;
333
+   return true;
334
+}
335
+
336
+inline bool interprocess_sharable_mutex::timed_lock_sharable
337
+   (const boost::posix_time::ptime &abs_time)
338
+{
339
+   scoped_lock_t lck(m_mut, abs_time);
340
+   if(!lck.owns())   return false;
341
+
342
+   //The sharable lock must block in the first gate
343
+   //if an exclusive lock has been acquired
344
+   //or there are too many sharable locks
345
+   while (this->m_ctrl.exclusive_in
346
+         || this->m_ctrl.num_shared == constants::max_readers){
347
+      //Mutexes and condvars handle just fine infinite abs_times
348
+      //so avoid checking it here
349
+      if(!this->m_first_gate.timed_wait(lck, abs_time)){
350
+         if(this->m_ctrl.exclusive_in
351
+               || this->m_ctrl.num_shared == constants::max_readers){
352
+            return false;
353
+         }
354
+         break;
355
+      }
356
+   }
357
+
358
+   //Increment sharable count
359
+   ++this->m_ctrl.num_shared;
360
+   return true;
361
+}
362
+
363
+inline void interprocess_sharable_mutex::unlock_sharable()
364
+{
365
+   scoped_lock_t lck(m_mut);
366
+   //Decrement sharable count
367
+   --this->m_ctrl.num_shared;
368
+   if (this->m_ctrl.num_shared == 0){
369
+      this->m_second_gate.notify_one();
370
+   }
371
+   //Check if there are blocked sharables because of
372
+   //there were too many sharables
373
+   else if(this->m_ctrl.num_shared == (constants::max_readers-1)){
374
+      this->m_first_gate.notify_all();
375
+   }
376
+}
377
+
378
+#endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
379
+
380
+}  //namespace interprocess {
381
+}  //namespace boost {
382
+
383
+#include <boost/interprocess/detail/config_end.hpp>
384
+
385
+#endif   //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP
0 386
new file mode 100755
... ...
@@ -0,0 +1,731 @@
1
+////////////////////////////////////////////////////////////////////////////////
2
+//
3
+//  Code based on Howard Hinnant's upgrade_mutex class
4
+//
5
+// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
6
+// Software License, Version 1.0. (See accompanying file
7
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
+//
9
+// See http://www.boost.org/libs/interprocess for documentation.
10
+//
11
+//////////////////////////////////////////////////////////////////////////////
12
+
13
+#ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
14
+#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP
15
+
16
+#ifndef BOOST_CONFIG_HPP
17
+#  include <boost/config.hpp>
18
+#endif
19
+#
20
+#if defined(BOOST_HAS_PRAGMA_ONCE)
21
+#  pragma once
22
+#endif
23
+
24
+#include <boost/interprocess/detail/config_begin.hpp>
25
+#include <boost/interprocess/detail/workaround.hpp>
26
+#include <boost/interprocess/sync/scoped_lock.hpp>
27
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
28
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
29
+#include <boost/interprocess/sync/interprocess_condition.hpp>
30
+#include <climits>
31
+
32
+
33
+//!\file
34
+//!Describes interprocess_upgradable_mutex class
35
+
36
+namespace boost {
37
+namespace interprocess {
38
+
39
+//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be
40
+//!shared between processes. Allows timed lock tries
41
+class interprocess_upgradable_mutex
42
+{
43
+   //Non-copyable
44
+   interprocess_upgradable_mutex(const interprocess_upgradable_mutex &);
45
+   interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &);
46
+
47
+   friend class interprocess_condition;
48
+   public:
49
+
50
+   //!Constructs the upgradable lock.
51
+   //!Throws interprocess_exception on error.
52
+   interprocess_upgradable_mutex();
53
+
54
+   //!Destroys the upgradable lock.
55
+   //!Does not throw.
56
+   ~interprocess_upgradable_mutex();
57
+
58
+   //Exclusive locking
59
+
60
+   //!Requires: The calling thread does not own the mutex.
61
+   //!
62
+   //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
63
+   //!   and if another thread has exclusive, sharable or upgradable ownership of
64
+   //!   the mutex, it waits until it can obtain the ownership.
65
+   //!Throws: interprocess_exception on error.
66
+   //! 
67
+   //!Note: A program may deadlock if the thread that has ownership calls 
68
+   //!   this function. If the implementation can detect the deadlock,
69
+   //!   an exception could be thrown.
70
+   void lock();
71
+
72
+   //!Requires: The calling thread does not own the mutex.
73
+   //!
74
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
75
+   //!   without waiting. If no other thread has exclusive, sharable or upgradable
76
+   //!   ownership of the mutex this succeeds.
77
+   //!Returns: If it can acquire exclusive ownership immediately returns true.
78
+   //!   If it has to wait, returns false.
79
+   //!Throws: interprocess_exception on error.
80
+   //! 
81
+   //!Note: A program may deadlock if the thread that has ownership calls 
82
+   //!   this function. If the implementation can detect the deadlock,
83
+   //!   an exception could be thrown.
84
+   bool try_lock();
85
+
86
+   //!Requires: The calling thread does not own the mutex.
87
+   //!
88
+   //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
89
+   //!   waiting if necessary until no other thread has exclusive, sharable or
90
+   //!   upgradable ownership of the mutex or abs_time is reached.
91
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
92
+   //!Throws: interprocess_exception on error.
93
+   //! 
94
+   //!Note: A program may deadlock if the thread that has ownership calls 
95
+   //!   this function. If the implementation can detect the deadlock,
96
+   //!   an exception could be thrown.
97
+   bool timed_lock(const boost::posix_time::ptime &abs_time);
98
+
99
+   //!Precondition: The thread must have exclusive ownership of the mutex.
100
+   //!Effects: The calling thread releases the exclusive ownership of the mutex.
101
+   //!Throws: An exception derived from interprocess_exception on error.
102
+   void unlock();
103
+
104
+   //Sharable locking
105
+
106
+   //!Requires: The calling thread does not own the mutex.
107
+   //!
108
+   //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
109
+   //!   and if another thread has exclusive ownership of the mutex,
110
+   //!   waits until it can obtain the ownership.
111
+   //!Throws: interprocess_exception on error.
112
+   //! 
113
+   //!Note: A program may deadlock if the thread that has ownership calls 
114
+   //!   this function. If the implementation can detect the deadlock,
115
+   //!   an exception could be thrown.
116
+   void lock_sharable();
117
+
118
+   //!Requires: The calling thread does not own the mutex.
119
+   //!
120
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
121
+   //!   without waiting. If no other thread has exclusive ownership
122
+   //!   of the mutex this succeeds.
123
+   //!Returns: If it can acquire sharable ownership immediately returns true. If it
124
+   //!   has to wait, returns false.
125
+   //!Throws: interprocess_exception on error.
126
+   //! 
127
+   //!Note: A program may deadlock if the thread that has ownership calls 
128
+   //!   this function. If the implementation can detect the deadlock,
129
+   //!   an exception could be thrown.
130
+   bool try_lock_sharable();
131
+
132
+   //!Requires: The calling thread does not own the mutex.
133
+   //!
134
+   //!Effects: The calling thread tries to acquire sharable ownership of the mutex
135
+   //!   waiting if necessary until no other thread has exclusive
136
+   //!   ownership of the mutex or abs_time is reached.
137
+   //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
138
+   //!Throws: interprocess_exception on error.
139
+   //! 
140
+   //!Note: A program may deadlock if the thread that has ownership calls 
141
+   //!   this function. If the implementation can detect the deadlock,
142
+   //!   an exception could be thrown.
143
+   bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
144
+
145
+   //!Precondition: The thread must have sharable ownership of the mutex.
146
+   //!Effects: The calling thread releases the sharable ownership of the mutex.
147
+   //!Throws: An exception derived from interprocess_exception on error.
148
+   void unlock_sharable();
149
+
150
+   //Upgradable locking
151
+
152
+   //!Requires: The calling thread does not own the mutex.
153
+   //!
154
+   //!Effects: The calling thread tries to obtain upgradable ownership of the mutex,
155
+   //!   and if another thread has exclusive or upgradable ownership of the mutex,
156
+   //!   waits until it can obtain the ownership.
157
+   //!Throws: interprocess_exception on error.
158
+   //!
159
+   //!Note: A program may deadlock if the thread that has ownership calls 
160
+   //!   this function. If the implementation can detect the deadlock,
161
+   //!   an exception could be thrown.
162
+   void lock_upgradable();
163
+
164
+   //!Requires: The calling thread does not own the mutex.
165
+   //!
166
+   //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
167
+   //!   without waiting. If no other thread has exclusive or upgradable ownership
168
+   //!   of the mutex this succeeds.
169
+   //!Returns: If it can acquire upgradable ownership immediately returns true.
170
+   //!   If it has to wait, returns false.
171
+   //!Throws: interprocess_exception on error.
172
+   //!
173
+   //!Note: A program may deadlock if the thread that has ownership calls 
174
+   //!   this function. If the implementation can detect the deadlock,
175
+   //!   an exception could be thrown.
176
+   bool try_lock_upgradable();
177
+
178
+   //!Requires: The calling thread does not own the mutex.
179
+   //!
180
+   //!Effects: The calling thread tries to acquire upgradable ownership of the mutex
181
+   //!   waiting if necessary until no other thread has exclusive or upgradable
182
+   //!   ownership of the mutex or abs_time is reached.
183
+   //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
184
+   //!Throws: interprocess_exception on error.
185
+   //!
186
+   //!Note: A program may deadlock if the thread that has ownership calls 
187
+   //!   this function. If the implementation can detect the deadlock,
188
+   //!   an exception could be thrown.
189
+   bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time);
190
+
191
+   //!Precondition: The thread must have upgradable ownership of the mutex.
192
+   //!Effects: The calling thread releases the upgradable ownership of the mutex.
193
+   //!Throws: An exception derived from interprocess_exception on error.
194
+   void unlock_upgradable();
195
+
196
+   //Demotions
197
+
198
+   //!Precondition: The thread must have exclusive ownership of the mutex.
199
+   //!Effects: The thread atomically releases exclusive ownership and acquires
200
+   //!   upgradable ownership. This operation is non-blocking.
201
+   //!Throws: An exception derived from interprocess_exception on error.
202
+   void unlock_and_lock_upgradable();
203
+
204
+   //!Precondition: The thread must have exclusive ownership of the mutex.
205
+   //!Effects: The thread atomically releases exclusive ownership and acquires
206
+   //!   sharable ownership. This operation is non-blocking.
207
+   //!Throws: An exception derived from interprocess_exception on error.
208
+   void unlock_and_lock_sharable();
209
+
210
+   //!Precondition: The thread must have upgradable ownership of the mutex.
211
+   //!Effects: The thread atomically releases upgradable ownership and acquires
212
+   //!   sharable ownership. This operation is non-blocking.
213
+   //!Throws: An exception derived from interprocess_exception on error.
214
+   void unlock_upgradable_and_lock_sharable();
215
+
216
+   //Promotions
217
+
218
+   //!Precondition: The thread must have upgradable ownership of the mutex.
219
+   //!Effects: The thread atomically releases upgradable ownership and acquires
220
+   //!   exclusive ownership. This operation will block until all threads with
221
+   //!   sharable ownership release their sharable lock.
222
+   //!Throws: An exception derived from interprocess_exception on error.
223
+   void unlock_upgradable_and_lock();
224
+
225
+   //!Precondition: The thread must have upgradable ownership of the mutex.
226
+   //!Effects: The thread atomically releases upgradable ownership and tries to
227
+   //!   acquire exclusive ownership. This operation will fail if there are threads
228
+   //!   with sharable ownership, but it will maintain upgradable ownership.
229
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
230
+   //!Throws: An exception derived from interprocess_exception on error.
231
+   bool try_unlock_upgradable_and_lock();
232
+
233
+   //!Precondition: The thread must have upgradable ownership of the mutex.
234
+   //!Effects: The thread atomically releases upgradable ownership and tries to acquire
235
+   //!   exclusive ownership, waiting if necessary until abs_time. This operation will
236
+   //!   fail if there are threads with sharable ownership or timeout reaches, but it
237
+   //!   will maintain upgradable ownership.
238
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
239
+   //!Throws: An exception derived from interprocess_exception on error. */
240
+   bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time);
241
+
242
+   //!Precondition: The thread must have sharable ownership of the mutex.
243
+   //!Effects: The thread atomically releases sharable ownership and tries to acquire
244
+   //!   exclusive ownership. This operation will fail if there are threads with sharable
245
+   //!   or upgradable ownership, but it will maintain sharable ownership.
246
+   //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
247
+   //!Throws: An exception derived from interprocess_exception on error.
248
+   bool try_unlock_sharable_and_lock();
249
+
250
+   //!Precondition: The thread must have sharable ownership of the mutex.
251
+   //!Effects: The thread atomically releases sharable ownership and tries to acquire
252
+   //!   upgradable ownership. This operation will fail if there are threads with sharable
253
+   //!   or upgradable ownership, but it will maintain sharable ownership.
254
+   //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false.
255
+   //!Throws: An exception derived from interprocess_exception on error.
256
+   bool try_unlock_sharable_and_lock_upgradable();
257
+
258
+   #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
259
+   private:
260
+   typedef scoped_lock<interprocess_mutex> scoped_lock_t;
261
+
262
+   //Pack all the control data in a word to be able
263
+   //to use atomic instructions in the future
264
+   struct control_word_t
265
+   {
266
+      unsigned exclusive_in         : 1;
267
+      unsigned upgradable_in        : 1;
268
+      unsigned num_upr_shar         : sizeof(unsigned)*CHAR_BIT-2;
269
+   }                       m_ctrl;
270
+
271
+   interprocess_mutex      m_mut;
272
+   interprocess_condition  m_first_gate;
273
+   interprocess_condition  m_second_gate;
274
+
275
+   private:
276
+   //Rollback structures for exceptions or failure return values
277
+   struct exclusive_rollback
278
+   {
279
+      exclusive_rollback(control_word_t         &ctrl
280
+                        ,interprocess_condition &first_gate)
281
+         :  mp_ctrl(&ctrl), m_first_gate(first_gate)
282
+      {}
283
+
284
+      void release()
285
+      {  mp_ctrl = 0;   }
286
+
287
+      ~exclusive_rollback()
288
+      {
289
+         if(mp_ctrl){
290
+            mp_ctrl->exclusive_in = 0;
291
+            m_first_gate.notify_all();
292
+         }
293
+      }
294
+      control_word_t          *mp_ctrl;
295
+      interprocess_condition  &m_first_gate;
296
+   };
297
+
298
+   struct upgradable_to_exclusive_rollback
299
+   {
300
+      upgradable_to_exclusive_rollback(control_word_t         &ctrl)
301
+         :  mp_ctrl(&ctrl)
302
+      {}
303
+
304
+      void release()
305
+      {  mp_ctrl = 0;   }
306
+
307
+      ~upgradable_to_exclusive_rollback()
308
+      {
309
+         if(mp_ctrl){
310
+            //Recover upgradable lock
311
+            mp_ctrl->upgradable_in = 1;
312
+            ++mp_ctrl->num_upr_shar;
313
+            //Execute the second half of exclusive locking
314
+            mp_ctrl->exclusive_in = 0;
315
+         }
316
+      }
317
+      control_word_t          *mp_ctrl;
318
+   };
319
+
320
+   template<int Dummy>
321
+   struct base_constants_t
322
+   {
323
+      static const unsigned max_readers
324
+         = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2));
325
+   };
326
+   typedef base_constants_t<0> constants;
327
+   #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
328
+};
329
+
330
+#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
331
+
332
+template <int Dummy>
333
+const unsigned interprocess_upgradable_mutex::base_constants_t<Dummy>::max_readers;
334
+
335
+inline interprocess_upgradable_mutex::interprocess_upgradable_mutex()
336
+{
337
+   this->m_ctrl.exclusive_in  = 0;
338
+   this->m_ctrl.upgradable_in = 0;
339
+   this->m_ctrl.num_upr_shar   = 0;
340
+}
341
+
342
+inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex()
343
+{}
344
+
345
+inline void interprocess_upgradable_mutex::lock()
346
+{
347
+   scoped_lock_t lck(m_mut);
348
+
349
+   //The exclusive lock must block in the first gate
350
+   //if an exclusive or upgradable lock has been acquired
351
+   while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
352
+      this->m_first_gate.wait(lck);
353
+   }
354
+
355
+   //Mark that exclusive lock has been acquired
356
+   this->m_ctrl.exclusive_in = 1;
357
+
358
+   //Prepare rollback
359
+   exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
360
+
361
+   //Now wait until all readers are gone
362
+   while (this->m_ctrl.num_upr_shar){
363
+      this->m_second_gate.wait(lck);
364
+   }
365
+   rollback.release();
366
+}
367
+
368
+inline bool interprocess_upgradable_mutex::try_lock()
369
+{
370
+   scoped_lock_t lck(m_mut, try_to_lock);
371
+
372
+   //If we can't lock or any has there is any exclusive, upgradable
373
+   //or sharable mark return false;
374
+   if(!lck.owns()
375
+      || this->m_ctrl.exclusive_in
376
+      || this->m_ctrl.num_upr_shar){
377
+      return false;
378
+   }
379
+   this->m_ctrl.exclusive_in = 1;
380
+   return true;
381
+}
382
+
383
+inline bool interprocess_upgradable_mutex::timed_lock
384
+   (const boost::posix_time::ptime &abs_time)
385
+{
386
+   //Mutexes and condvars handle just fine infinite abs_times
387
+   //so avoid checking it here
388
+   scoped_lock_t lck(m_mut, abs_time);
389
+   if(!lck.owns())   return false;
390
+
391
+   //The exclusive lock must block in the first gate
392
+   //if an exclusive or upgradable lock has been acquired
393
+   while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
394
+      if(!this->m_first_gate.timed_wait(lck, abs_time)){
395
+         if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){
396
+            return false;
397
+         }
398
+         break;
399
+      }
400
+   }
401
+
402
+   //Mark that exclusive lock has been acquired
403
+   this->m_ctrl.exclusive_in = 1;
404
+
405
+   //Prepare rollback
406
+   exclusive_rollback rollback(this->m_ctrl, this->m_first_gate);
407
+
408
+   //Now wait until all readers are gone
409
+   while (this->m_ctrl.num_upr_shar){
410
+      if(!this->m_second_gate.timed_wait(lck, abs_time)){
411
+         if(this->m_ctrl.num_upr_shar){
412
+            return false;
413
+         }
414
+         break;
415
+      }
416
+   }
417
+   rollback.release();
418
+   return true;
419
+}
420
+
421
+inline void interprocess_upgradable_mutex::unlock()
422
+{
423
+   scoped_lock_t lck(m_mut);
424
+   this->m_ctrl.exclusive_in = 0;
425
+   this->m_first_gate.notify_all();
426
+}
427
+
428
+//Upgradable locking
429
+
430
+inline void interprocess_upgradable_mutex::lock_upgradable()
431
+{
432
+   scoped_lock_t lck(m_mut);
433
+
434
+   //The upgradable lock must block in the first gate
435
+   //if an exclusive or upgradable lock has been acquired
436
+   //or there are too many sharable locks
437
+   while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in
438
+         || this->m_ctrl.num_upr_shar == constants::max_readers){
439
+      this->m_first_gate.wait(lck);
440
+   }
441
+
442
+   //Mark that upgradable lock has been acquired
443
+   //And add upgradable to the sharable count
444
+   this->m_ctrl.upgradable_in = 1;
445
+   ++this->m_ctrl.num_upr_shar;
446
+}
447
+
448
+inline bool interprocess_upgradable_mutex::try_lock_upgradable()
449
+{
450
+   scoped_lock_t lck(m_mut, try_to_lock);
451
+
452
+   //The upgradable lock must fail
453
+   //if an exclusive or upgradable lock has been acquired
454
+   //or there are too many sharable locks
455
+   if(!lck.owns()
456
+      || this->m_ctrl.exclusive_in
457
+      || this->m_ctrl.upgradable_in
458
+      || this->m_ctrl.num_upr_shar == constants::max_readers){
459
+      return false;
460
+   }
461
+
462
+   //Mark that upgradable lock has been acquired
463
+   //And add upgradable to the sharable count
464
+   this->m_ctrl.upgradable_in = 1;
465
+   ++this->m_ctrl.num_upr_shar;
466
+   return true;
467
+}
468
+
469
+inline bool interprocess_upgradable_mutex::timed_lock_upgradable
470
+   (const boost::posix_time::ptime &abs_time)
471
+{
472
+   //Mutexes and condvars handle just fine infinite abs_times
473
+   //so avoid checking it here
474
+   scoped_lock_t lck(m_mut, abs_time);
475
+   if(!lck.owns())   return false;
476
+
477
+   //The upgradable lock must block in the first gate
478
+   //if an exclusive or upgradable lock has been acquired
479
+   //or there are too many sharable locks
480
+   while(this->m_ctrl.exclusive_in
481
+         || this->m_ctrl.upgradable_in
482
+         || this->m_ctrl.num_upr_shar == constants::max_readers){
483
+      if(!this->m_first_gate.timed_wait(lck, abs_time)){
484
+         if((this->m_ctrl.exclusive_in
485
+             || this->m_ctrl.upgradable_in
486
+             || this->m_ctrl.num_upr_shar == constants::max_readers)){
487
+            return false;