From 6352e8e3196f78388b6c771073f9e03eaa612673 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:33:09 +1000 Subject: everything everywhere all at once --- source/core/StarLockFile_unix.cpp | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 source/core/StarLockFile_unix.cpp (limited to 'source/core/StarLockFile_unix.cpp') 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 +#include +#include +#include + +namespace Star { + +int64_t const LockFile::MaximumSleepMillis; + +Maybe 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 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(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; +} + +} -- cgit v1.2.3