Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP Chris@16: #define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: #pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #include Chris@16: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #else //defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #endif //defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: namespace boost{ Chris@16: namespace interprocess{ Chris@16: namespace ipcdetail{ Chris@16: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: struct locking_file_serial_id Chris@16: { Chris@16: int fd; Chris@16: unsigned long dwVolumeSerialNumber; Chris@16: unsigned long nFileIndexHigh; Chris@16: unsigned long nFileIndexLow; Chris@16: //This reference count counts the number of modules attached Chris@16: //to the shared memory and lock file. This serves to unlink Chris@16: //the locking file and shared memory when all modules are Chris@16: //done with the global memory (shared memory) Chris@16: volatile boost::uint32_t modules_attached_to_gmem_count; Chris@16: }; Chris@16: Chris@16: inline bool lock_locking_file(int fd) Chris@16: { Chris@16: int ret = 0; Chris@16: while(ret != 0 && errno == EDEADLK){ Chris@16: ret = _locking(fd, _LK_LOCK, 1/*lock_file_contents_length()*/); Chris@16: } Chris@16: return 0 == ret; Chris@16: } Chris@16: Chris@16: inline bool try_lock_locking_file(int fd) Chris@16: { Chris@16: return 0 == _locking(fd, _LK_NBLCK , 1); Chris@16: } Chris@16: Chris@16: inline int open_or_create_and_lock_file(const char *name) Chris@16: { Chris@16: permissions p; Chris@16: p.set_unrestricted(); Chris@16: while(1){ Chris@16: file_handle_t handle = create_or_open_file(name, read_write, p); Chris@16: int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); Chris@16: if(fd < 0){ Chris@16: close_file(handle); Chris@16: return fd; Chris@16: } Chris@16: if(!try_lock_locking_file(fd)){ Chris@16: _close(fd); Chris@16: return -1; Chris@16: } Chris@16: struct _stat s; Chris@16: if(0 == _stat(name, &s)){ Chris@16: return fd; Chris@16: } Chris@16: else{ Chris@16: _close(fd); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: inline int try_open_and_lock_file(const char *name) Chris@16: { Chris@16: file_handle_t handle = open_existing_file(name, read_write); Chris@16: int fd = _open_osfhandle((intptr_t)handle, _O_TEXT); Chris@16: if(fd < 0){ Chris@16: close_file(handle); Chris@16: return fd; Chris@16: } Chris@16: if(!try_lock_locking_file(fd)){ Chris@16: _close(fd); Chris@16: return -1; Chris@16: } Chris@16: return fd; Chris@16: } Chris@16: Chris@16: inline void close_lock_file(int fd) Chris@16: { _close(fd); } Chris@16: Chris@16: inline bool is_valid_fd(int fd) Chris@16: { Chris@16: struct _stat s; Chris@16: return EBADF != _fstat(fd, &s); Chris@16: } Chris@16: Chris@16: inline bool is_normal_file(int fd) Chris@16: { Chris@16: if(_isatty(fd)) Chris@16: return false; Chris@16: struct _stat s; Chris@16: if(0 != _fstat(fd, &s)) Chris@16: return false; Chris@16: return 0 != (s.st_mode & _S_IFREG); Chris@16: } Chris@16: Chris@16: inline std::size_t get_size(int fd) Chris@16: { Chris@16: struct _stat s; Chris@16: if(0 != _fstat(fd, &s)) Chris@16: return 0u; Chris@16: return (std::size_t)s.st_size; Chris@16: } Chris@16: Chris@16: inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) Chris@16: { Chris@16: winapi::interprocess_by_handle_file_information info; Chris@16: if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) Chris@16: return false; Chris@16: id.fd = fd; Chris@16: id.dwVolumeSerialNumber = info.dwVolumeSerialNumber; Chris@16: id.nFileIndexHigh = info.nFileIndexHigh; Chris@16: id.nFileIndexLow = info.nFileIndexLow; Chris@16: id.modules_attached_to_gmem_count = 1; //Initialize attached count Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline bool compare_file_serial(int fd, const locking_file_serial_id &id) Chris@16: { Chris@16: winapi::interprocess_by_handle_file_information info; Chris@16: if(!winapi::get_file_information_by_handle((void*)_get_osfhandle(fd), &info)) Chris@16: return false; Chris@16: Chris@16: return id.dwVolumeSerialNumber == info.dwVolumeSerialNumber && Chris@16: id.nFileIndexHigh == info.nFileIndexHigh && Chris@16: id.nFileIndexLow == info.nFileIndexLow; Chris@16: } Chris@16: Chris@16: #else //UNIX Chris@16: Chris@16: struct locking_file_serial_id Chris@16: { Chris@16: int fd; Chris@16: dev_t st_dev; Chris@16: ino_t st_ino; Chris@16: //This reference count counts the number of modules attached Chris@16: //to the shared memory and lock file. This serves to unlink Chris@16: //the locking file and shared memory when all modules are Chris@16: //done with the global memory (shared memory) Chris@16: volatile boost::uint32_t modules_attached_to_gmem_count; Chris@16: }; Chris@16: Chris@16: inline bool lock_locking_file(int fd) Chris@16: { Chris@16: int ret = 0; Chris@16: while(ret != 0 && errno != EINTR){ Chris@16: struct flock lock; Chris@16: lock.l_type = F_WRLCK; Chris@16: lock.l_whence = SEEK_SET; Chris@16: lock.l_start = 0; Chris@16: lock.l_len = 1; Chris@16: ret = fcntl (fd, F_SETLKW, &lock); Chris@16: } Chris@16: return 0 == ret; Chris@16: } Chris@16: Chris@16: inline bool try_lock_locking_file(int fd) Chris@16: { Chris@16: struct flock lock; Chris@16: lock.l_type = F_WRLCK; Chris@16: lock.l_whence = SEEK_SET; Chris@16: lock.l_start = 0; Chris@16: lock.l_len = 1; Chris@16: return 0 == fcntl (fd, F_SETLK, &lock); Chris@16: } Chris@16: Chris@16: inline int open_or_create_and_lock_file(const char *name) Chris@16: { Chris@16: permissions p; Chris@16: p.set_unrestricted(); Chris@16: while(1){ Chris@16: int fd = create_or_open_file(name, read_write, p); Chris@16: if(fd < 0){ Chris@16: return fd; Chris@16: } Chris@16: if(!try_lock_locking_file(fd)){ Chris@16: close(fd); Chris@16: return -1; Chris@16: } Chris@16: struct stat s; Chris@16: if(0 == stat(name, &s)){ Chris@16: return fd; Chris@16: } Chris@16: else{ Chris@16: close(fd); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: inline int try_open_and_lock_file(const char *name) Chris@16: { Chris@16: int fd = open_existing_file(name, read_write); Chris@16: if(fd < 0){ Chris@16: return fd; Chris@16: } Chris@16: if(!try_lock_locking_file(fd)){ Chris@16: close(fd); Chris@16: return -1; Chris@16: } Chris@16: return fd; Chris@16: } Chris@16: Chris@16: inline void close_lock_file(int fd) Chris@16: { close(fd); } Chris@16: Chris@16: inline bool is_valid_fd(int fd) Chris@16: { Chris@16: struct stat s; Chris@16: return EBADF != fstat(fd, &s); Chris@16: } Chris@16: Chris@16: inline bool is_normal_file(int fd) Chris@16: { Chris@16: struct stat s; Chris@16: if(0 != fstat(fd, &s)) Chris@16: return false; Chris@16: return 0 != (s.st_mode & S_IFREG); Chris@16: } Chris@16: Chris@16: inline std::size_t get_size(int fd) Chris@16: { Chris@16: struct stat s; Chris@16: if(0 != fstat(fd, &s)) Chris@16: return 0u; Chris@16: return (std::size_t)s.st_size; Chris@16: } Chris@16: Chris@16: inline bool fill_file_serial_id(int fd, locking_file_serial_id &id) Chris@16: { Chris@16: struct stat s; Chris@16: if(0 != fstat(fd, &s)) Chris@16: return false; Chris@16: id.fd = fd; Chris@16: id.st_dev = s.st_dev; Chris@16: id.st_ino = s.st_ino; Chris@16: id.modules_attached_to_gmem_count = 1; //Initialize attached count Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline bool compare_file_serial(int fd, const locking_file_serial_id &id) Chris@16: { Chris@16: struct stat info; Chris@16: if(0 != fstat(fd, &info)) Chris@16: return false; Chris@16: Chris@16: return id.st_dev == info.st_dev && Chris@16: id.st_ino == info.st_ino; Chris@16: } Chris@16: Chris@101: #endif Chris@16: Chris@16: } //namespace ipcdetail{ Chris@16: } //namespace interprocess{ Chris@16: } //namespace boost{ Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP