diff --git a/uppsrc/CppBase/CppBase.h b/uppsrc/CppBase/CppBase.h index f5a0c189e..ec71c8205 100644 --- a/uppsrc/CppBase/CppBase.h +++ b/uppsrc/CppBase/CppBase.h @@ -226,7 +226,7 @@ void PreprocessParse(CppBase& base, Stream& in, int file, const String& path, Event error); String PreprocessCpp(const String& src, const String& path); -ParserContext AssistParse(CppBase& base, const String& src, const String& path_, Event error); +ParserContext AssistParse(const String& src, const String& path_, Event error); void SimpleParse(CppBase& cpp, const String& txt, const String& cls); diff --git a/uppsrc/CppBase/Iface.cpp b/uppsrc/CppBase/Iface.cpp index 7fb93c24d..a32a7d22e 100644 --- a/uppsrc/CppBase/Iface.cpp +++ b/uppsrc/CppBase/Iface.cpp @@ -55,7 +55,7 @@ String PreprocessCpp(const String& src, const String& path) return cpp.output; } -ParserContext AssistParse(CppBase& base, const String& src, const String& path_, Event error) +ParserContext AssistParse(const String& src, const String& path_, Event error) { String path = NormalizeSourcePath(path_); Cpp cpp; @@ -64,7 +64,8 @@ ParserContext AssistParse(CppBase& base, const String& src, const String& path_, Parser parser; parser.dobody = true; // will do bodies and not write anything to base StringStream pin(cpp.output); - parser.Do(pin, base, Null, Null, GetFileTitle(path), error, + CppBase dummy; + parser.Do(pin, dummy, Null, Null, GetFileTitle(path), error, Vector(), cpp.namespace_stack, cpp.namespace_using); // needs CodeBase to identify type names return pick(parser); } diff --git a/uppsrc/CtrlLib/PushCtrl.h b/uppsrc/CtrlLib/PushCtrl.h index 9e257c029..d77803d10 100644 --- a/uppsrc/CtrlLib/PushCtrl.h +++ b/uppsrc/CtrlLib/PushCtrl.h @@ -58,7 +58,6 @@ public: virtual ~Pusher(); }; - class Button : public Pusher { public: virtual void Paint(Draw& draw); diff --git a/uppsrc/ide/Browser/Base.cpp b/uppsrc/ide/Browser/Base.cpp index 313d14797..7fd9e5e6b 100644 --- a/uppsrc/ide/Browser/Base.cpp +++ b/uppsrc/ide/Browser/Base.cpp @@ -22,20 +22,35 @@ static StaticMutex sGLock; static thread_local int sGLockLevel = 0; - -CodeBaseLock::CodeBaseLock() + +bool DeadLockCheck() +{ + if(sGLockLevel) { + PostCallback([] { Exclamation("Internal error (deadlock on sGLock)"); }); + return true; + } + return false; +} + +void LockCodeBase() { if(sGLockLevel++ == 0) sGLock.Enter(); } -CodeBaseLock::~CodeBaseLock() +void UnlockCodeBase() { - ASSERT(sGLockLevel > 0); - if(--sGLockLevel == 0) + if(sGLockLevel > 0 && --sGLockLevel == 0) sGLock.Leave(); } +void UnlockCodeBaseAll() +{ + if(sGLockLevel > 0) + sGLock.Leave(); + sGLockLevel = 0; // just in case +} + INITIALIZER(CodeBase) { void InitializeTopicModule(); @@ -121,7 +136,7 @@ void BrowserScanError(int line, const String& text, int file) void SerializeCodeBase(Stream& s) { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); MLOG(s.IsLoading()); source_file.Serialize(s); @@ -134,7 +149,7 @@ void SerializeCodeBase(Stream& s) void SaveCodeBase() { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); LTIMING("SaveCodeBase"); LLOG("Save code base " << CodeBase().GetCount()); @@ -148,7 +163,7 @@ void SaveCodeBase() bool TryLoadCodeBase(const char *pattern) { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return false; Mutex::Lock __(CppBaseMutex); LLOG("+++ Trying to load " << pattern); FindFile ff(pattern); @@ -176,7 +191,7 @@ bool TryLoadCodeBase(const char *pattern) void LoadCodeBase() { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); MLOG("LoadCodeBase start: " << MemoryUsedKb()); TryLoadCodeBase(CodeBaseCacheFile()) || @@ -191,7 +206,7 @@ void FinishCodeBase() { LTIMING("FinishBase"); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); Qualify(CodeBase()); } @@ -199,7 +214,7 @@ void FinishCodeBase() void LoadDefs() { LTIMING("LoadDefs"); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); Vector defs; defs.Add(ConfigFile("global.defs")); @@ -230,7 +245,7 @@ void LoadDefs() void BaseInfoSync(Progress& pi) { // clears temporary caches (file times etc..) - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); PPSync(TheIde()->IdeGetIncludePath()); @@ -313,7 +328,7 @@ bool CheckFile0(SourceFileInfo& f, const String& path) bool CheckFile(SourceFileInfo& f, const String& path) { LTIMING("CheckFile"); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return false; Mutex::Lock __(CppBaseMutex); return CheckFile0(f, path); } @@ -321,7 +336,7 @@ bool CheckFile(SourceFileInfo& f, const String& path) void UpdateCodeBase2(Progress& pi) { CLOG("============= UpdateCodeBase2 " << GetSysTime()); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); Index parse_file; { @@ -416,9 +431,6 @@ void CodeBaseScanFile0(Stream& in, const String& fn) { LLOG("===== CodeBaseScanFile " << fn); - ASSERT(sGLockLevel == 0); - Mutex::Lock __(CppBaseMutex); - InvalidateFileTimeCache(NormalizeSourcePath(fn)); PPSync(TheIde()->IdeGetIncludePath()); @@ -436,6 +448,8 @@ void CodeBaseScanFile0(Stream& in, const String& fn) void CodeBaseScanFile(Stream& in, const String& fn) { + if(DeadLockCheck()) return; + Mutex::Lock __(CppBaseMutex); CodeBaseScanFile0(in, fn); FinishCodeBase(); } @@ -443,11 +457,11 @@ void CodeBaseScanFile(Stream& in, const String& fn) void CodeBaseScanFile(const String& fn, bool auto_check) { LLOG("CodeBaseScanFile " << fn); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); String md5sum = GetPPMD5(fn); FileIn in(fn); - CodeBaseScanFile(in, fn); + CodeBaseScanFile0(in, fn); int file = GetSourceFileIndex(fn); SourceFileInfo& f = source_file[file]; CLOG("CodeBaseScanFile " << fn << ", " << md5sum << " " << f.md5sum); @@ -463,7 +477,7 @@ void CodeBaseScanFile(const String& fn, bool auto_check) void ClearCodeBase() { // TODO: Create combined defs - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); CleanPP(); CodeBase().Clear(); @@ -475,7 +489,7 @@ void SyncCodeBase() LTIMING("SyncCodeBase"); LTIMESTOP("SyncCodeBase"); CLOG("============= Sync code base"); - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); if(IsNull(IdeGetCurrentMainPackage())) { ClearCodeBase(); @@ -489,7 +503,7 @@ void SyncCodeBase() void NewCodeBase() { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); ReduceCodeBaseCache(); if(IsNull(IdeGetCurrentMainPackage())) { @@ -510,7 +524,7 @@ void NewCodeBase() void RescanCodeBase() { - ASSERT(sGLockLevel == 0); + if(DeadLockCheck()) return; Mutex::Lock __(CppBaseMutex); ClearCodeBase(); s_console = true; diff --git a/uppsrc/ide/Browser/Browser.h b/uppsrc/ide/Browser/Browser.h index 9d86b9afe..4e12f3434 100644 --- a/uppsrc/ide/Browser/Browser.h +++ b/uppsrc/ide/Browser/Browser.h @@ -20,9 +20,13 @@ class Browser; void ReduceCacheFolder(const char *path, int max_total); +void LockCodeBase(); +void UnlockCodeBase(); +void UnlockCodeBaseAll(); + struct CodeBaseLock { // Use when accessing CodeBase - CodeBaseLock(); - ~CodeBaseLock(); + CodeBaseLock() { LockCodeBase(); } + ~CodeBaseLock() { UnlockCodeBase(); } }; CppBase& CodeBase(); diff --git a/uppsrc/ide/ContextGoto.cpp b/uppsrc/ide/ContextGoto.cpp index 80217dca6..6228ee002 100644 --- a/uppsrc/ide/ContextGoto.cpp +++ b/uppsrc/ide/ContextGoto.cpp @@ -459,10 +459,11 @@ void Ide::JumpToDefinition(const Array& n, int q, const String& scope) } i++; } - const CppItem& pos = n[qimpl >= 0 ? qimpl : qcpp >= 0 ? qcpp : q]; + CppItem pos = n[qimpl >= 0 ? qimpl : qcpp >= 0 ? qcpp : q]; String path = GetSourceFilePath(pos.file); editastext.RemoveKey(path); editashex.RemoveKey(path); + UnlockCodeBaseAll(); if(!GotoDesignerFile(path, scope, pos.name, pos.line)) GotoCpp(pos); } diff --git a/uppsrc/ide/Cpp.cpp b/uppsrc/ide/Cpp.cpp index a304fe3dd..53218e6b3 100644 --- a/uppsrc/ide/Cpp.cpp +++ b/uppsrc/ide/Cpp.cpp @@ -14,16 +14,19 @@ String ResolveTParam(const String& type, const Vector& tparam) { + CodeBaseLock __; return ResolveTParam(CodeBase(), type, tparam); } void ResolveTParam(Vector& type, const Vector& tparam) { + CodeBaseLock __; return ResolveTParam(CodeBase(), type, tparam); } String Qualify(const String& scope, const String& type, const String& usings) { + CodeBaseLock __; return Qualify(CodeBase(), scope, type, usings); } @@ -41,7 +44,7 @@ void AssistEditor::Context(ParserContext& parser, int pos) theide->ScanFile(true); - parser = AssistParse(CodeBase(), Get(0, pos), theide->editfile, AssistScanError); + parser = AssistParse(Get(0, pos), theide->editfile, AssistScanError); inbody = parser.IsInBody(); #ifdef _DEBUG PutVerbose("body: " + AsString(inbody)); @@ -54,6 +57,7 @@ void AssistEditor::Context(ParserContext& parser, int pos) Index AssistEditor::EvaluateExpressionType(const ParserContext& parser, const Vector& xp) { + CodeBaseLock __; return GetExpressionType(CodeBase(), parser, xp); } @@ -71,6 +75,7 @@ void AssistEditor::GatherItems(const String& type, bool only_public, Index= 0) { LLOG("-> recursion, exiting"); return; diff --git a/uppsrc/ide/Swaps.cpp b/uppsrc/ide/Swaps.cpp index f4bd38a1d..d61002bcd 100644 --- a/uppsrc/ide/Swaps.cpp +++ b/uppsrc/ide/Swaps.cpp @@ -61,7 +61,9 @@ bool Ide::SwapSIf(const char *cref) break; } } - GotoCpp(*n[i % n.GetCount()]); + CppItem m = *n[i % n.GetCount()]; + UnlockCodeBaseAll(); + GotoCpp(m); return true; }