diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2020-04-22 23:00:12 +0700 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2020-06-03 12:22:45 +0700 |
commit | f51bc4fb60fbcef26d18eff549fc68307fd46489 (patch) | |
tree | bd8be13530a067b56f1f0b9134b4ee4cd93316ca /llvm/unittests/Support/Path.cpp | |
parent | 70f1b4b4122088c1bd7324b519bc449dbfeaf298 (diff) | |
download | llvm-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.cpp | 45 |
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 |