1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2009-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)
7 // See http://www.boost.org/libs/interprocess for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
12 #define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
27 #include <sys/types.h>
31 #include <boost/interprocess/detail/os_file_functions.hpp>
33 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
35 #if defined(BOOST_INTERPROCESS_WINDOWS)
39 #include <sys/locking.h>
41 #else //defined(BOOST_INTERPROCESS_WINDOWS)
47 #endif //defined(BOOST_INTERPROCESS_WINDOWS)
50 namespace interprocess{
53 #if defined(BOOST_INTERPROCESS_WINDOWS)
55 struct locking_file_serial_id
58 unsigned long dwVolumeSerialNumber;
59 unsigned long nFileIndexHigh;
60 unsigned long nFileIndexLow;
61 //This reference count counts the number of modules attached
62 //to the shared memory and lock file. This serves to unlink
63 //the locking file and shared memory when all modules are
64 //done with the global memory (shared memory)
65 volatile boost::uint32_t modules_attached_to_gmem_count;
68 inline bool lock_locking_file(int fd)
71 while(ret != 0 && errno == EDEADLK){
72 ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/);
77 inline bool try_lock_locking_file(int fd)
79 return 0 == _locking(fd, _LK_NBLCK , 1);
82 inline int open_or_create_and_lock_file(const char *name)
87 file_handle_t handle = create_or_open_file(name, read_write, p);
88 int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
93 if(!try_lock_locking_file(fd)){
98 if(0 == _stat(name, &s)){
107 inline int try_open_and_lock_file(const char *name)
109 file_handle_t handle = open_existing_file(name, read_write);
110 int fd = _open_osfhandle((intptr_t)handle, _O_TEXT);
115 if(!try_lock_locking_file(fd)){
122 inline void close_lock_file(int fd)
125 inline bool is_valid_fd(int fd)
128 return EBADF != _fstat(fd, &s);
131 inline bool is_normal_file(int fd)
136 if(0 != _fstat(fd, &s))
138 return 0 != (s.st_mode & _S_IFREG);
141 inline std::size_t get_size(int fd)
144 if(0 != _fstat(fd, &s))
146 return (std::size_t)s.st_size;
149 inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
151 winapi::interprocess_by_handle_file_information info;
152 if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
155 id.dwVolumeSerialNumber = info.dwVolumeSerialNumber;
156 id.nFileIndexHigh = info.nFileIndexHigh;
157 id.nFileIndexLow = info.nFileIndexLow;
158 id.modules_attached_to_gmem_count = 1; //Initialize attached count
162 inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
164 winapi::interprocess_by_handle_file_information info;
165 if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info))
168 return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber &&
169 id.nFileIndexHigh == info.nFileIndexHigh &&
170 id.nFileIndexLow == info.nFileIndexLow;
175 struct locking_file_serial_id
180 //This reference count counts the number of modules attached
181 //to the shared memory and lock file. This serves to unlink
182 //the locking file and shared memory when all modules are
183 //done with the global memory (shared memory)
184 volatile boost::uint32_t modules_attached_to_gmem_count;
187 inline bool lock_locking_file(int fd)
190 while(ret != 0 && errno != EINTR){
192 lock.l_type = F_WRLCK;
193 lock.l_whence = SEEK_SET;
196 ret = fcntl (fd, F_SETLKW, &lock);
201 inline bool try_lock_locking_file(int fd)
204 lock.l_type = F_WRLCK;
205 lock.l_whence = SEEK_SET;
208 return 0 == fcntl (fd, F_SETLK, &lock);
211 inline int open_or_create_and_lock_file(const char *name)
214 p.set_unrestricted();
216 int fd = create_or_open_file(name, read_write, p);
220 if(!try_lock_locking_file(fd)){
225 if(0 == stat(name, &s)){
234 inline int try_open_and_lock_file(const char *name)
236 int fd = open_existing_file(name, read_write);
240 if(!try_lock_locking_file(fd)){
247 inline void close_lock_file(int fd)
250 inline bool is_valid_fd(int fd)
253 return EBADF != fstat(fd, &s);
256 inline bool is_normal_file(int fd)
259 if(0 != fstat(fd, &s))
261 return 0 != (s.st_mode & S_IFREG);
264 inline std::size_t get_size(int fd)
267 if(0 != fstat(fd, &s))
269 return (std::size_t)s.st_size;
272 inline bool fill_file_serial_id(int fd, locking_file_serial_id &id)
275 if(0 != fstat(fd, &s))
278 id.st_dev = s.st_dev;
279 id.st_ino = s.st_ino;
280 id.modules_attached_to_gmem_count = 1; //Initialize attached count
284 inline bool compare_file_serial(int fd, const locking_file_serial_id &id)
287 if(0 != fstat(fd, &info))
290 return id.st_dev == info.st_dev &&
291 id.st_ino == info.st_ino;
296 } //namespace ipcdetail{
297 } //namespace interprocess{
300 #include <boost/interprocess/detail/config_end.hpp>
302 #endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP