diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarLockFile_unix.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/core/StarLockFile_unix.cpp')
-rw-r--r-- | source/core/StarLockFile_unix.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/source/core/StarLockFile_unix.cpp b/source/core/StarLockFile_unix.cpp new file mode 100644 index 0000000..2b6e0bf --- /dev/null +++ b/source/core/StarLockFile_unix.cpp @@ -0,0 +1,94 @@ +#include "StarLockFile.hpp" +#include "StarTime.hpp" +#include "StarThread.hpp" + +#include <sys/file.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +namespace Star { + +int64_t const LockFile::MaximumSleepMillis; + +Maybe<LockFile> LockFile::acquireLock(String const& filename, int64_t lockTimeout) { + LockFile lock(move(filename)); + if (lock.lock(lockTimeout)) + return move(lock); + return {}; +} + +LockFile::LockFile(String const& filename) : m_filename(move(filename)) {} + +LockFile::LockFile(LockFile&& lockFile) { + operator=(move(lockFile)); +} + +LockFile::~LockFile() { + unlock(); +} + +LockFile& LockFile::operator=(LockFile&& lockFile) { + m_filename = move(lockFile.m_filename); + m_handle = move(lockFile.m_handle); + + return *this; +} + +bool LockFile::lock(int64_t timeout) { + auto doFLock = [](String const& filename, bool block) -> shared_ptr<int> { + int fd = open(filename.utf8Ptr(), O_RDONLY | O_CREAT, 0644); + if (fd < 0) + throw StarException(strf("Could not open lock file %s, %s\n", filename, strerror(errno))); + + int ret; + if (block) + ret = flock(fd, LOCK_EX); + else + ret = flock(fd, LOCK_EX | LOCK_NB); + + if (ret != 0) { + close(fd); + if (errno != EWOULDBLOCK) + throw StarException(strf("Could not lock file %s, %s\n", filename, strerror(errno))); + return {}; + } + + return make_shared<int>(fd); + }; + + if (timeout < 0) { + m_handle = doFLock(m_filename, true); + return true; + } else if (timeout == 0) { + m_handle = doFLock(m_filename, false); + return (bool)m_handle; + } else { + int64_t startTime = Time::monotonicMilliseconds(); + while (true) { + m_handle = doFLock(m_filename, false); + if (m_handle) + return true; + + if (Time::monotonicMilliseconds() - startTime > timeout) + return false; + + Thread::sleep(min(timeout / 4, MaximumSleepMillis)); + } + } +} + +void LockFile::unlock() { + if (m_handle) { + int fd = *(int*)m_handle.get(); + unlink(m_filename.utf8Ptr()); + close(fd); + m_handle.reset(); + } +} + +bool LockFile::isLocked() const { + return (bool)m_handle; +} + +} |