aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-10-10 21:57:12 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-10-10 21:57:12 +0000
commita696ece1ac449a2b77e7c0a693b55cb10e9e2068 (patch)
tree9b0b25cf5824213137fe3dce133a0d384409717b
parent9d1bbeab2475fe45a3d4cb8de6810bc3275f1dd7 (diff)
[libclang] Implement ConcurrencyCheck using a recursive mutex to allow re-entrancy in the same thread.
The checks are performed only in DEBUG, it becomes no-op in release mode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141582 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Frontend/ASTUnit.h38
-rw-r--r--lib/Frontend/ASTUnit.cpp30
2 files changed, 50 insertions, 18 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 074b4174be..91c4398d0f 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -151,16 +151,6 @@ private:
/// destroyed.
SmallVector<llvm::sys::Path, 4> TemporaryFiles;
- /// \brief Simple hack to allow us to assert that ASTUnit is not being
- /// used concurrently, which is not supported.
- ///
- /// Clients should create instances of the ConcurrencyCheck class whenever
- /// using the ASTUnit in a way that isn't intended to be concurrent, which is
- /// just about any usage.
- unsigned int ConcurrencyCheckValue;
- static const unsigned int CheckLocked = 28573289;
- static const unsigned int CheckUnlocked = 9803453;
-
/// \brief Counter that determines when we want to try building a
/// precompiled preamble.
///
@@ -406,21 +396,37 @@ private:
unsigned MaxLines = 0);
void RealizeTopLevelDeclsFromPreamble();
+ /// \brief Allows us to assert that ASTUnit is not being used concurrently,
+ /// which is not supported.
+ ///
+ /// Clients should create instances of the ConcurrencyCheck class whenever
+ /// using the ASTUnit in a way that isn't intended to be concurrent, which is
+ /// just about any usage.
+ /// Becomes a noop in release mode; only useful for debug mode checking.
+ class ConcurrencyState {
+ void *Mutex; // a llvm::sys::MutexImpl in debug;
+
+ public:
+ ConcurrencyState();
+ ~ConcurrencyState();
+
+ void start();
+ void finish();
+ };
+ ConcurrencyState ConcurrencyCheckValue;
+
public:
class ConcurrencyCheck {
- volatile ASTUnit &Self;
+ ASTUnit &Self;
public:
explicit ConcurrencyCheck(ASTUnit &Self)
: Self(Self)
{
- assert(Self.ConcurrencyCheckValue == CheckUnlocked &&
- "Concurrent access to ASTUnit!");
- Self.ConcurrencyCheckValue = CheckLocked;
+ Self.ConcurrencyCheckValue.start();
}
-
~ConcurrencyCheck() {
- Self.ConcurrencyCheckValue = CheckUnlocked;
+ Self.ConcurrencyCheckValue.finish();
}
};
friend class ConcurrencyCheck;
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index e84f8bd6e2..c2c67c1229 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Mutex.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdlib>
#include <cstdio>
@@ -99,7 +100,6 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
OwnsRemappedFileBuffers(true),
NumStoredDiagnosticsFromDriver(0),
- ConcurrencyCheckValue(CheckUnlocked),
PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
ShouldCacheCodeCompletionResults(false),
NestedMacroExpansions(true),
@@ -114,7 +114,6 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
}
ASTUnit::~ASTUnit() {
- ConcurrencyCheckValue = CheckLocked;
CleanTemporaryFiles();
if (!PreambleFile.empty())
llvm::sys::Path(PreambleFile).eraseFromDisk();
@@ -2414,3 +2413,30 @@ void ASTUnit::PreambleData::countLines() const {
if (Buffer.back() != '\n')
++NumLines;
}
+
+#ifndef NDEBUG
+ASTUnit::ConcurrencyState::ConcurrencyState() {
+ Mutex = new llvm::sys::MutexImpl(/*recursive=*/true);
+}
+
+ASTUnit::ConcurrencyState::~ConcurrencyState() {
+ delete static_cast<llvm::sys::MutexImpl *>(Mutex);
+}
+
+void ASTUnit::ConcurrencyState::start() {
+ bool acquired = static_cast<llvm::sys::MutexImpl *>(Mutex)->tryacquire();
+ assert(acquired && "Concurrent access to ASTUnit!");
+}
+
+void ASTUnit::ConcurrencyState::finish() {
+ static_cast<llvm::sys::MutexImpl *>(Mutex)->release();
+}
+
+#else // NDEBUG
+
+ASTUnit::ConcurrencyState::ConcurrencyState() {}
+ASTUnit::ConcurrencyState::~ConcurrencyState() {}
+void ASTUnit::ConcurrencyState::start() {}
+void ASTUnit::ConcurrencyState::finish() {}
+
+#endif