From e6db4c5a4ede8039ed525e3facebd7e0eb7ec1b7 Mon Sep 17 00:00:00 2001 From: Ruslan Baratov Date: Wed, 26 Nov 2014 01:49:25 +0300 Subject: file: Add LOCK subcommand to do file and directory locking Provide options to fail without blocking or to block up to a timeout. Provide options to specify the scope containing the lock so it can be released automatically at the end of a function, file, or process. Extend the RunCMake.file test with cases covering the file(LOCK) command usage and error cases. --- Source/cmFileLockPool.cxx | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 Source/cmFileLockPool.cxx (limited to 'Source/cmFileLockPool.cxx') diff --git a/Source/cmFileLockPool.cxx b/Source/cmFileLockPool.cxx new file mode 100644 index 0000000000..e84e71aa5f --- /dev/null +++ b/Source/cmFileLockPool.cxx @@ -0,0 +1,198 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Ruslan Baratov + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmFileLockPool.h" + +#include + +#include "cmFileLock.h" +#include "cmFileLockResult.h" + +cmFileLockPool::cmFileLockPool() +{ +} + +cmFileLockPool::~cmFileLockPool() +{ + for (It i = this->FunctionScopes.begin(); + i != this->FunctionScopes.end(); ++i) + { + delete *i; + } + + for (It i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) + { + delete *i; + } +} + +void cmFileLockPool::PushFunctionScope() +{ + this->FunctionScopes.push_back(new ScopePool()); +} + +void cmFileLockPool::PopFunctionScope() +{ + assert(!this->FunctionScopes.empty()); + delete this->FunctionScopes.back(); + this->FunctionScopes.pop_back(); +} + +void cmFileLockPool::PushFileScope() +{ + this->FileScopes.push_back(new ScopePool()); +} + +void cmFileLockPool::PopFileScope() +{ + assert(!this->FileScopes.empty()); + delete this->FileScopes.back(); + this->FileScopes.pop_back(); +} + +cmFileLockResult cmFileLockPool::LockFunctionScope( + const std::string& filename, unsigned timeoutSec) +{ + if (this->IsAlreadyLocked(filename)) + { + return cmFileLockResult::MakeAlreadyLocked(); + } + if (this->FunctionScopes.empty()) + { + return cmFileLockResult::MakeNoFunction(); + } + return this->FunctionScopes.back()->Lock(filename, timeoutSec); +} + +cmFileLockResult cmFileLockPool::LockFileScope( + const std::string& filename, unsigned timeoutSec) +{ + if (this->IsAlreadyLocked(filename)) + { + return cmFileLockResult::MakeAlreadyLocked(); + } + assert(!this->FileScopes.empty()); + return this->FileScopes.back()->Lock(filename, timeoutSec); +} + +cmFileLockResult cmFileLockPool::LockProcessScope( + const std::string& filename, unsigned timeoutSec) +{ + if (this->IsAlreadyLocked(filename)) + { + return cmFileLockResult::MakeAlreadyLocked(); + } + return this->ProcessScope.Lock(filename, timeoutSec); +} + +cmFileLockResult cmFileLockPool::Release(const std::string& filename) +{ + for (It i = this->FunctionScopes.begin(); + i != this->FunctionScopes.end(); ++i) + { + const cmFileLockResult result = (*i)->Release(filename); + if (!result.IsOk()) + { + return result; + } + } + + for (It i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) + { + const cmFileLockResult result = (*i)->Release(filename); + if (!result.IsOk()) + { + return result; + } + } + + return this->ProcessScope.Release(filename); +} + +bool cmFileLockPool::IsAlreadyLocked(const std::string& filename) const +{ + for (CIt i = this->FunctionScopes.begin(); + i != this->FunctionScopes.end(); ++i) + { + const bool result = (*i)->IsAlreadyLocked(filename); + if (result) + { + return true; + } + } + + for (CIt i = this->FileScopes.begin(); i != this->FileScopes.end(); ++i) + { + const bool result = (*i)->IsAlreadyLocked(filename); + if (result) + { + return true; + } + } + + return this->ProcessScope.IsAlreadyLocked(filename); +} + +cmFileLockPool::ScopePool::ScopePool() +{ +} + +cmFileLockPool::ScopePool::~ScopePool() +{ + for (It i = this->Locks.begin(); i != this->Locks.end(); ++i) + { + delete *i; + } +} + +cmFileLockResult cmFileLockPool::ScopePool::Lock( + const std::string& filename, unsigned timeoutSec) +{ + cmFileLock *lock = new cmFileLock(); + const cmFileLockResult result = lock->Lock(filename, timeoutSec); + if (result.IsOk()) + { + this->Locks.push_back(lock); + return cmFileLockResult::MakeOk(); + } + else + { + delete lock; + return result; + } +} + +cmFileLockResult cmFileLockPool::ScopePool::Release( + const std::string& filename) +{ + for (It i = this->Locks.begin(); i != this->Locks.end(); ++i) + { + if ((*i)->IsLocked(filename)) + { + return (*i)->Release(); + } + } + return cmFileLockResult::MakeOk(); +} + +bool cmFileLockPool::ScopePool::IsAlreadyLocked( + const std::string& filename) const +{ + for (CIt i = this->Locks.begin(); i != this->Locks.end(); ++i) + { + if ((*i)->IsLocked(filename)) + { + return true; + } + } + return false; +} -- cgit v1.2.1