diff options
author | Ruslan Baratov <ruslan_baratov@yahoo.com> | 2014-11-26 01:49:25 +0300 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2014-12-03 09:47:44 -0500 |
commit | e6db4c5a4ede8039ed525e3facebd7e0eb7ec1b7 (patch) | |
tree | f5e6a3dce7b89725f9fa4e5fcafd040114a85466 /Source/cmFileLockPool.cxx | |
parent | 05d6531c7a8ecfad513a0e76b44b273b70fa919b (diff) | |
download | cmake-e6db4c5a4ede8039ed525e3facebd7e0eb7ec1b7.tar.gz |
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.
Diffstat (limited to 'Source/cmFileLockPool.cxx')
-rw-r--r-- | Source/cmFileLockPool.cxx | 198 |
1 files changed, 198 insertions, 0 deletions
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 <assert.h> + +#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; +} |