aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/Path.cpp
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2020-04-22 23:00:12 +0700
committerSerge Pavlov <sepavloff@gmail.com>2020-06-03 12:22:45 +0700
commitf51bc4fb60fbcef26d18eff549fc68307fd46489 (patch)
treebd8be13530a067b56f1f0b9134b4ee4cd93316ca /llvm/unittests/Support/Path.cpp
parent70f1b4b4122088c1bd7324b519bc449dbfeaf298 (diff)
downloadllvm-f51bc4fb60fbcef26d18eff549fc68307fd46489.zip
llvm-f51bc4fb60fbcef26d18eff549fc68307fd46489.tar.gz
llvm-f51bc4fb60fbcef26d18eff549fc68307fd46489.tar.bz2
[Support] Add file lock/unlock functions
New functions `lockFile`, `tryLockFile` and `unlockFile` implement simple file locking. They lock or unlock entire file. This must be enough to support simulataneous writes to log files in parallel builds. Differential Revision: https://reviews.llvm.org/D78896
Diffstat (limited to 'llvm/unittests/Support/Path.cpp')
-rw-r--r--llvm/unittests/Support/Path.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/llvm/unittests/Support/Path.cpp b/llvm/unittests/Support/Path.cpp
index 8e842a9..92b3917 100644
--- a/llvm/unittests/Support/Path.cpp
+++ b/llvm/unittests/Support/Path.cpp
@@ -39,6 +39,8 @@
#include <sys/stat.h>
#endif
+#include <future>
+
using namespace llvm;
using namespace llvm::sys;
@@ -2038,4 +2040,47 @@ TEST_F(FileSystemTest, widenPath) {
}
#endif
+TEST_F(FileSystemTest, lockFile) {
+ int FD1, FD2;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("test", "temp", FD1, TempPath));
+ FileRemover Cleanup(TempPath);
+ ASSERT_NO_ERROR(fs::openFileForReadWrite(TempPath, FD2, fs::CD_OpenExisting,
+ fs::OF_Append));
+ ASSERT_NO_ERROR(fs::tryLockFile(FD1));
+
+ ASSERT_EQ(errc::no_lock_available,
+ fs::tryLockFile(FD2, std::chrono::milliseconds(5)));
+ ASSERT_NO_ERROR(fs::unlockFile(FD1));
+ ASSERT_NO_ERROR(fs::tryLockFile(FD2));
+ ASSERT_NO_ERROR(fs::unlockFile(FD2));
+}
+
+TEST_F(FileSystemTest, lockFileThread) {
+#if LLVM_ENABLE_THREADS
+ int FD1, FD2;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("test", "temp", FD1, TempPath));
+ FileRemover Cleanup(TempPath);
+ ASSERT_NO_ERROR(fs::openFileForReadWrite(TempPath, FD2, fs::CD_OpenExisting,
+ fs::OF_Append));
+
+ ASSERT_NO_ERROR(fs::tryLockFile(FD1));
+ ASSERT_ERROR(fs::tryLockFile(FD2));
+ std::future<std::error_code> Future = std::async(std::launch::async, [&] {
+ return fs::tryLockFile(FD2, std::chrono::seconds(5));
+ });
+ ASSERT_NO_ERROR(fs::unlockFile(FD1));
+ ASSERT_NO_ERROR(Future.get());
+ fs::unlockFile(FD2);
+
+ ASSERT_NO_ERROR(fs::tryLockFile(FD1));
+ ASSERT_ERROR(fs::tryLockFile(FD2));
+ Future = std::async(std::launch::async, [&] { return fs::lockFile(FD2); });
+ ASSERT_NO_ERROR(fs::unlockFile(FD1));
+ ASSERT_NO_ERROR(Future.get());
+ fs::unlockFile(FD2);
+#endif
+}
+
} // anonymous namespace