comparison DEPENDENCIES/generic/include/boost/interprocess/sync/file_lock.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
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 #if (defined _MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif
17
18 #include <boost/interprocess/detail/config_begin.hpp>
19 #include <boost/interprocess/detail/workaround.hpp>
20 #include <boost/interprocess/exceptions.hpp>
21 #include <boost/interprocess/detail/os_file_functions.hpp>
22 #include <boost/interprocess/detail/os_thread_functions.hpp>
23 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
24 #include <boost/interprocess/sync/spin/wait.hpp>
25 #include <boost/move/move.hpp>
26
27 //!\file
28 //!Describes a class that wraps file locking capabilities.
29
30 namespace boost {
31 namespace interprocess {
32
33
34 //!A file lock, is a mutual exclusion utility similar to a mutex using a
35 //!file. A file lock has sharable and exclusive locking capabilities and
36 //!can be used with scoped_lock and sharable_lock classes.
37 //!A file lock can't guarantee synchronization between threads of the same
38 //!process so just use file locks to synchronize threads from different processes.
39 class file_lock
40 {
41 /// @cond
42 //Non-copyable
43 BOOST_MOVABLE_BUT_NOT_COPYABLE(file_lock)
44 /// @endcond
45
46 public:
47 //!Constructs an empty file mapping.
48 //!Does not throw
49 file_lock()
50 : m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
51 {}
52
53 //!Opens a file lock. Throws interprocess_exception if the file does not
54 //!exist or there are no operating system resources.
55 file_lock(const char *name);
56
57 //!Moves the ownership of "moved"'s file mapping object to *this.
58 //!After the call, "moved" does not represent any file mapping object.
59 //!Does not throw
60 file_lock(BOOST_RV_REF(file_lock) moved)
61 : m_file_hnd(file_handle_t(ipcdetail::invalid_file()))
62 { this->swap(moved); }
63
64 //!Moves the ownership of "moved"'s file mapping to *this.
65 //!After the call, "moved" does not represent any file mapping.
66 //!Does not throw
67 file_lock &operator=(BOOST_RV_REF(file_lock) moved)
68 {
69 file_lock tmp(boost::move(moved));
70 this->swap(tmp);
71 return *this;
72 }
73
74 //!Closes a file lock. Does not throw.
75 ~file_lock();
76
77 //!Swaps two file_locks.
78 //!Does not throw.
79 void swap(file_lock &other)
80 {
81 file_handle_t tmp = m_file_hnd;
82 m_file_hnd = other.m_file_hnd;
83 other.m_file_hnd = tmp;
84 }
85
86 //Exclusive locking
87
88 //!Effects: The calling thread tries to obtain exclusive ownership of the mutex,
89 //! and if another thread has exclusive, or sharable ownership of
90 //! the mutex, it waits until it can obtain the ownership.
91 //!Throws: interprocess_exception on error.
92 void lock();
93
94 //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
95 //! without waiting. If no other thread has exclusive, or sharable
96 //! ownership of the mutex this succeeds.
97 //!Returns: If it can acquire exclusive ownership immediately returns true.
98 //! If it has to wait, returns false.
99 //!Throws: interprocess_exception on error.
100 bool try_lock();
101
102 //!Effects: The calling thread tries to acquire exclusive ownership of the mutex
103 //! waiting if necessary until no other thread has exclusive, or sharable
104 //! ownership of the mutex or abs_time is reached.
105 //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false.
106 //!Throws: interprocess_exception on error.
107 bool timed_lock(const boost::posix_time::ptime &abs_time);
108
109 //!Precondition: The thread must have exclusive ownership of the mutex.
110 //!Effects: The calling thread releases the exclusive ownership of the mutex.
111 //!Throws: An exception derived from interprocess_exception on error.
112 void unlock();
113
114 //Sharable locking
115
116 //!Effects: The calling thread tries to obtain sharable ownership of the mutex,
117 //! and if another thread has exclusive ownership of the mutex, waits until
118 //! it can obtain the ownership.
119 //!Throws: interprocess_exception on error.
120 void lock_sharable();
121
122 //!Effects: The calling thread tries to acquire sharable ownership of the mutex
123 //! without waiting. If no other thread has exclusive ownership of the
124 //! 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 bool try_lock_sharable();
129
130 //!Effects: The calling thread tries to acquire sharable ownership of the mutex
131 //! waiting if necessary until no other thread has exclusive ownership of
132 //! the mutex or abs_time is reached.
133 //!Returns: If acquires sharable ownership, returns true. Otherwise returns false.
134 //!Throws: interprocess_exception on error.
135 bool timed_lock_sharable(const boost::posix_time::ptime &abs_time);
136
137 //!Precondition: The thread must have sharable ownership of the mutex.
138 //!Effects: The calling thread releases the sharable ownership of the mutex.
139 //!Throws: An exception derived from interprocess_exception on error.
140 void unlock_sharable();
141 /// @cond
142 private:
143 file_handle_t m_file_hnd;
144
145 bool timed_acquire_file_lock
146 (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
147 {
148 //Obtain current count and target time
149 boost::posix_time::ptime now = microsec_clock::universal_time();
150 using namespace boost::detail;
151
152 if(now >= abs_time) return false;
153 spin_wait swait;
154 do{
155 if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
156 return false;
157
158 if(acquired)
159 return true;
160 else{
161 now = microsec_clock::universal_time();
162
163 if(now >= abs_time){
164 acquired = false;
165 return true;
166 }
167 // relinquish current time slice
168 swait.yield();
169 }
170 }while (true);
171 }
172
173 bool timed_acquire_file_lock_sharable
174 (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time)
175 {
176 //Obtain current count and target time
177 boost::posix_time::ptime now = microsec_clock::universal_time();
178 using namespace boost::detail;
179
180 if(now >= abs_time) return false;
181
182 spin_wait swait;
183 do{
184 if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
185 return false;
186
187 if(acquired)
188 return true;
189 else{
190 now = microsec_clock::universal_time();
191
192 if(now >= abs_time){
193 acquired = false;
194 return true;
195 }
196 // relinquish current time slice
197 swait.yield();
198 }
199 }while (true);
200 }
201 /// @endcond
202 };
203
204 inline file_lock::file_lock(const char *name)
205 {
206 m_file_hnd = ipcdetail::open_existing_file(name, read_write);
207
208 if(m_file_hnd == ipcdetail::invalid_file()){
209 error_info err(system_error_code());
210 throw interprocess_exception(err);
211 }
212 }
213
214 inline file_lock::~file_lock()
215 {
216 if(m_file_hnd != ipcdetail::invalid_file()){
217 ipcdetail::close_file(m_file_hnd);
218 m_file_hnd = ipcdetail::invalid_file();
219 }
220 }
221
222 inline void file_lock::lock()
223 {
224 if(!ipcdetail::acquire_file_lock(m_file_hnd)){
225 error_info err(system_error_code());
226 throw interprocess_exception(err);
227 }
228 }
229
230 inline bool file_lock::try_lock()
231 {
232 bool result;
233 if(!ipcdetail::try_acquire_file_lock(m_file_hnd, result)){
234 error_info err(system_error_code());
235 throw interprocess_exception(err);
236 }
237 return result;
238 }
239
240 inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time)
241 {
242 if(abs_time == boost::posix_time::pos_infin){
243 this->lock();
244 return true;
245 }
246 bool result;
247 if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){
248 error_info err(system_error_code());
249 throw interprocess_exception(err);
250 }
251 return result;
252 }
253
254 inline void file_lock::unlock()
255 {
256 if(!ipcdetail::release_file_lock(m_file_hnd)){
257 error_info err(system_error_code());
258 throw interprocess_exception(err);
259 }
260 }
261
262 inline void file_lock::lock_sharable()
263 {
264 if(!ipcdetail::acquire_file_lock_sharable(m_file_hnd)){
265 error_info err(system_error_code());
266 throw interprocess_exception(err);
267 }
268 }
269
270 inline bool file_lock::try_lock_sharable()
271 {
272 bool result;
273 if(!ipcdetail::try_acquire_file_lock_sharable(m_file_hnd, result)){
274 error_info err(system_error_code());
275 throw interprocess_exception(err);
276 }
277 return result;
278 }
279
280 inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time)
281 {
282 if(abs_time == boost::posix_time::pos_infin){
283 this->lock_sharable();
284 return true;
285 }
286 bool result;
287 if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){
288 error_info err(system_error_code());
289 throw interprocess_exception(err);
290 }
291 return result;
292 }
293
294 inline void file_lock::unlock_sharable()
295 {
296 if(!ipcdetail::release_file_lock_sharable(m_file_hnd)){
297 error_info err(system_error_code());
298 throw interprocess_exception(err);
299 }
300 }
301
302 } //namespace interprocess {
303 } //namespace boost {
304
305 #include <boost/interprocess/detail/config_end.hpp>
306
307 #endif //BOOST_INTERPROCESS_FILE_LOCK_HPP