15 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
19 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
30 #define F_OFD_GETLK 36
31 #define F_OFD_SETLK 37
32 #define F_OFD_SETLKW 38
38 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
40 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
41 Impl() : _file(nullptr) {}
50 catch (
const SystemException& ex)
52 fatality(SystemException(ex.string()));
56 const Path&
path() const noexcept {
return _path; }
64 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
65 _file = open(_path.string().c_str(), O_CREAT | O_RDWR, 0644);
67 throwex FileSystemException(
"Cannot create or open file-lock file!").Attach(
path);
68 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
70 const std::wstring wpath = _path.wstring();
71 const int attempts = 1000;
72 const int sleep = 100;
73 for (
int attempt = 0; attempt < attempts; ++attempt)
75 _file = CreateFileW(wpath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_FLAG_DELETE_ON_CLOSE,
nullptr);
76 if (_file == INVALID_HANDLE_VALUE)
83 throwex FileSystemException(
"Cannot create or open file-lock file!").Attach(
path);
92 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
93 int result = close(_file);
95 fatality(FileSystemException(
"Cannot close the file-lock descriptor!").Attach(_path));
99 unlink(_path.string().c_str());
100 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
101 if (!CloseHandle(_file))
102 fatality(FileSystemException(
"Cannot close the file-lock handle!").Attach(_path));
109 #if defined(linux) || defined(__linux) || defined(__linux__)
111 lock.l_type = F_RDLCK;
112 lock.l_whence = SEEK_SET;
116 int result = fcntl(_file, F_OFD_SETLK, &lock);
122 throwex FileSystemException(
"Failed to try lock for read!").Attach(_path);
126 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
127 int result = flock(_file, LOCK_SH | LOCK_NB);
130 if (errno == EWOULDBLOCK)
133 throwex FileSystemException(
"Failed to try lock for read!").Attach(_path);
137 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
138 OVERLAPPED overlapped;
139 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
140 return LockFileEx(_file, LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) != 0;
146 #if defined(linux) || defined(__linux) || defined(__linux__)
148 lock.l_type = F_WRLCK;
149 lock.l_whence = SEEK_SET;
153 int result = fcntl(_file, F_OFD_SETLK, &lock);
159 throwex FileSystemException(
"Failed to try lock for write!").Attach(_path);
163 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
164 int result = flock(_file, LOCK_EX | LOCK_NB);
167 if (errno == EWOULDBLOCK)
170 throwex FileSystemException(
"Failed to try lock for write!").Attach(_path);
174 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
175 OVERLAPPED overlapped;
176 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
177 return LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, MAXDWORD, MAXDWORD, &overlapped) != 0;
183 #if defined(linux) || defined(__linux) || defined(__linux__)
185 lock.l_type = F_RDLCK;
186 lock.l_whence = SEEK_SET;
190 int result = fcntl(_file, F_OFD_SETLKW, &lock);
192 throwex FileSystemException(
"Failed to lock for read!").Attach(_path);
193 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
194 int result = flock(_file, LOCK_SH);
196 throwex FileSystemException(
"Failed to lock for read!").Attach(_path);
197 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
198 OVERLAPPED overlapped;
199 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
200 if (!LockFileEx(_file, 0, 0, MAXDWORD, MAXDWORD, &overlapped))
201 throwex FileSystemException(
"Failed to lock for read!").Attach(_path);
207 #if defined(linux) || defined(__linux) || defined(__linux__)
209 lock.l_type = F_WRLCK;
210 lock.l_whence = SEEK_SET;
214 int result = fcntl(_file, F_OFD_SETLKW, &lock);
216 throwex FileSystemException(
"Failed to lock for write!").Attach(_path);
217 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
218 int result = flock(_file, LOCK_EX);
220 throwex FileSystemException(
"Failed to lock for write!").Attach(_path);
221 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
222 OVERLAPPED overlapped;
223 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
224 if (!LockFileEx(_file, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped))
225 throwex FileSystemException(
"Failed to lock for write!").Attach(_path);
231 #if defined(linux) || defined(__linux) || defined(__linux__)
233 lock.l_type = F_UNLCK;
234 lock.l_whence = SEEK_SET;
238 int result = fcntl(_file, F_OFD_SETLK, &lock);
240 throwex FileSystemException(
"Failed to unlock the read lock!").Attach(_path);
241 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
242 int result = flock(_file, LOCK_UN);
244 throwex FileSystemException(
"Failed to unlock the read lock!").Attach(_path);
245 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
246 OVERLAPPED overlapped;
247 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
248 if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
249 throwex FileSystemException(
"Failed to unlock the read lock!").Attach(_path);
255 #if defined(linux) || defined(__linux) || defined(__linux__)
257 lock.l_type = F_UNLCK;
258 lock.l_whence = SEEK_SET;
262 int result = fcntl(_file, F_OFD_SETLK, &lock);
264 throwex FileSystemException(
"Failed to unlock the write lock!").Attach(_path);
265 #elif (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
266 int result = flock(_file, LOCK_UN);
268 throwex FileSystemException(
"Failed to unlock the write lock!").Attach(_path);
269 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
270 OVERLAPPED overlapped;
271 ZeroMemory(&overlapped,
sizeof(OVERLAPPED));
272 if (!UnlockFileEx(_file, 0, MAXDWORD, MAXDWORD, &overlapped))
273 throwex FileSystemException(
"Failed to unlock the write lock!").Attach(_path);
279 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
281 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
292 static_assert((StorageSize >=
sizeof(Impl)),
"FileLock::StorageSize must be increased!");
293 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"FileLock::StorageAlign must be adjusted!");
296 new(&_storage)Impl();
303 static_assert((StorageSize >=
sizeof(Impl)),
"FileLock::StorageSize must be increased!");
304 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"FileLock::StorageAlign must be adjusted!");
307 new(&_storage)Impl();
315 reinterpret_cast<Impl*
>(&_storage)->~Impl();
File-lock synchronization primitive.
void UnlockRead()
Release read lock.
FileLock & operator=(const Path &path)
bool TryLockWrite()
Try to acquire write lock without block.
void LockRead()
Acquire read lock with block.
bool TryLockReadFor(const Timespan ×pan)
Try to acquire read lock for the given timespan.
const Path & path() const noexcept
Get the file-lock path.
void UnlockWrite()
Release write lock.
bool TryLockRead()
Try to acquire read lock without block.
void Reset()
Reset file-lock.
bool TryLockWriteFor(const Timespan ×pan)
Try to acquire write lock for the given timespan.
void Assign(const Path &path)
Assign a new file-lock path.
void LockWrite()
Acquire write lock with block.
High resolution timestamp.
static void Yield() noexcept
Yield to other threads.
Aligned storage validator.
#define throwex
Throw extended exception macro.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
File-lock synchronization primitive definition.
C++ Common project definitions.
Aligned storage validator definition.