]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
enhance: Add util::FileLock
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 10 Nov 2024 10:36:37 +0000 (11:36 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Fri, 15 Nov 2024 21:16:52 +0000 (22:16 +0100)
src/ccache/util/CMakeLists.txt
src/ccache/util/filelock.cpp [new file with mode: 0644]
src/ccache/util/filelock.hpp [new file with mode: 0644]

index 4983bedcd00020486df313d56928b6b152e73446..5d5a68ced2ef1059e691dbf00b21cb1e092ff867 100644 (file)
@@ -7,6 +7,7 @@ set(
   environment.cpp
   error.cpp
   file.cpp
+  filelock.cpp
   filesystem.cpp
   lockfile.cpp
   logging.cpp
diff --git a/src/ccache/util/filelock.cpp b/src/ccache/util/filelock.cpp
new file mode 100644 (file)
index 0000000..e687496
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright (C) 2024 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "filelock.hpp"
+
+#include <cerrno>
+#include <cstring>
+
+#ifdef _WIN32
+#  include <io.h>
+#  include <windows.h>
+#else
+#  include <fcntl.h>
+#  include <sys/file.h>
+#  include <unistd.h>
+#endif
+
+namespace util {
+
+FileLock::FileLock(int fd) : m_fd(fd)
+{
+}
+
+FileLock::FileLock(FileLock&& other) noexcept
+  : m_fd(other.m_fd),
+    m_acquired(other.m_acquired)
+{
+  other.m_fd = -1;
+  other.m_acquired = false;
+}
+
+FileLock&
+FileLock::operator=(FileLock&& other) noexcept
+{
+  if (&other != this) {
+    m_fd = other.m_fd;
+    m_acquired = other.m_acquired;
+    other.m_fd = -1;
+    other.m_acquired = false;
+  }
+  return *this;
+}
+
+bool
+FileLock::acquire()
+{
+#ifdef _WIN32
+  HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(m_fd));
+  if (handle == INVALID_HANDLE_VALUE) {
+    return false;
+  }
+  m_acquired = LockFile(handle, 0, 0, MAXDWORD, MAXDWORD) != 0;
+#else
+  struct flock lock;
+  memset(&lock, 0, sizeof(lock));
+  lock.l_type = F_WRLCK;
+  lock.l_whence = SEEK_SET;
+  int result;
+  do {
+    result = fcntl(m_fd, F_SETLKW, &lock);
+  } while (result != 0 && errno == EINTR);
+  m_acquired = result == 0;
+#endif
+  return m_acquired;
+}
+
+void
+FileLock::release()
+{
+  if (!acquired()) {
+    return;
+  }
+
+#ifdef _WIN32
+  HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(m_fd));
+  if (handle != INVALID_HANDLE_VALUE) {
+    UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD);
+  }
+#else
+  struct flock lock;
+  memset(&lock, 0, sizeof(lock));
+  lock.l_type = F_UNLCK;
+  lock.l_whence = SEEK_SET;
+  int result;
+  do {
+    result = fcntl(m_fd, F_SETLK, &lock);
+  } while (result != 0 && errno == EINTR);
+#endif
+  m_acquired = false;
+}
+
+} // namespace util
diff --git a/src/ccache/util/filelock.hpp b/src/ccache/util/filelock.hpp
new file mode 100644 (file)
index 0000000..806784f
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (C) 2024 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include <ccache/util/noncopyable.hpp>
+
+namespace util {
+
+class FileLock : util::NonCopyable
+{
+public:
+  explicit FileLock(int fd);
+  FileLock(FileLock&& other) noexcept;
+
+  FileLock& operator=(FileLock&& other) noexcept;
+
+  // Release the lock if previously acquired.
+  ~FileLock();
+
+  // Acquire lock, blocking. Returns true if acquired, otherwise false.
+  [[nodiscard]] bool acquire();
+
+  // Release lock early. If not previously acquired, nothing happens.
+  void release();
+
+  // Return whether the lock is acquired successfully.
+  bool acquired() const;
+
+private:
+  int m_fd = -1;
+  bool m_acquired = false;
+};
+
+inline FileLock::~FileLock()
+{
+  release();
+}
+
+inline bool
+FileLock::acquired() const
+{
+  return m_acquired;
+}
+
+} // namespace util