diff --git a/include/eepp/system/lock.hpp b/include/eepp/system/lock.hpp index 8e3443671..d5fe30a0f 100644 --- a/include/eepp/system/lock.hpp +++ b/include/eepp/system/lock.hpp @@ -5,6 +5,7 @@ #include #ifdef EE_DEBUG +// #define EE_REGISTER_SLOW_LOCKS #include #endif @@ -27,7 +28,7 @@ class EE_API Lock : NonCopyable { private: Mutex& mMutex; ///< Mutex to lock / unlock -#ifdef EE_DEBUG +#ifdef EE_REGISTER_SLOW_LOCKS Clock mClock; #endif }; diff --git a/src/eepp/system/lock.cpp b/src/eepp/system/lock.cpp index 5ab6d7021..1a612216a 100644 --- a/src/eepp/system/lock.cpp +++ b/src/eepp/system/lock.cpp @@ -1,6 +1,6 @@ #include #include -#ifdef EE_DEBUG +#ifdef EE_REGISTER_SLOW_LOCKS #include #endif @@ -12,8 +12,10 @@ Lock::Lock( Mutex& mutex ) : mMutex( mutex ) { Lock::~Lock() { mMutex.unlock(); -#ifdef EE_DEBUG +#ifdef EE_REGISTER_SLOW_LOCKS if ( EE::Window::Engine::isMainThread() && mClock.getElapsedTime().asMilliseconds() > 100.f ) { + Log::info( "Something locked the main thread for too long! It was locked for: %s", + mClock.getElapsedTime().toString() ); eeASSERT( false ); } #endif diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 1cb71aeb9..dd41eb41c 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -1703,37 +1703,37 @@ TextRange TextDocument::getLineRange( Int64 line ) const { } std::size_t TextDocument::getLineLength( Int64 line ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? 0 : mLines[line].size(); } String TextDocument::getLineText( Int64 line ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? String() : mLines[line].getText(); } String TextDocument::getLineTextSubStr( Int64 line, std::size_t pos, std::size_t n ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? String() : mLines[line].getText().substr( pos, n ); } String::HashType TextDocument::getLineHash( Int64 line ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? 0 : mLines[line].getHash(); } String TextDocument::getLineTextWithoutNewLine( Int64 line ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? String() : mLines[line].getTextWithoutNewLine(); } void TextDocument::getLineTextToBuffer( Int64 line, String& buffer ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); if ( line >= (Int64)mLines.size() ) { buffer.clear(); @@ -1743,13 +1743,13 @@ void TextDocument::getLineTextToBuffer( Int64 line, String& buffer ) const { } std::string TextDocument::getLineTextUtf8( Int64 line ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); return line >= (Int64)mLines.size() ? std::string() : mLines[line].getText().toUtf8(); } void TextDocument::getLineTextToBufferUtf8( Int64 line, std::string& buffer ) const { - eeASSERT( line < (Int64)linesCount() ); + // eeASSERT( line < (Int64)linesCount() ); Lock l( mLinesMutex ); if ( line >= (Int64)mLines.size() ) { buffer.clear(); diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.cpp b/src/tools/ecode/plugins/lsp/lspclientserver.cpp index c91c0c4d6..bbe639e60 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.cpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.cpp @@ -1628,18 +1628,37 @@ LSPClientServer::didChange( TextDocument* doc, const std::vector& change ) { - Lock l( mDidChangeMutex ); - mDidChangeQueue.push( { document, version, change } ); +void LSPClientServer::queueAndProcess( const URI& document, int version, + const std::vector& change ) { + bool shouldStartWorker = false; + { + Lock l( mDidChangeMutex ); + mDidChangeQueue.push( { document, version, change } ); + if ( !mIsProcessingQueue ) { + mIsProcessingQueue = true; + shouldStartWorker = true; + } + } + + if ( shouldStartWorker ) { + getThreadPool()->run( [this]() { this->processDidChangeQueue(); } ); + } } void LSPClientServer::processDidChangeQueue() { - Lock l( mDidChangeMutex ); - while ( !mDidChangeQueue.empty() ) { - auto& change = mDidChangeQueue.front(); + while ( true ) { + DidChangeQueue change; + { + Lock l( mDidChangeMutex ); + if ( mDidChangeQueue.empty() ) { + mIsProcessingQueue = false; + break; + } + change = mDidChangeQueue.front(); + mDidChangeQueue.pop(); + } + // Process outside the lock to avoid blocking didChange( change.uri, change.version, "", change.change ); - mDidChangeQueue.pop(); } } diff --git a/src/tools/ecode/plugins/lsp/lspclientserver.hpp b/src/tools/ecode/plugins/lsp/lspclientserver.hpp index 96eabe619..8758bd663 100644 --- a/src/tools/ecode/plugins/lsp/lspclientserver.hpp +++ b/src/tools/ecode/plugins/lsp/lspclientserver.hpp @@ -124,8 +124,8 @@ class LSPClientServer { LSPRequestHandle didChange( TextDocument* doc, const std::vector& change = {} ); - void queueDidChange( const URI& document, int version, const std::string& text, - const std::vector& change = {} ); + void queueAndProcess( const URI& document, int version, + const std::vector& change = {} ); void processDidChangeQueue(); @@ -299,6 +299,7 @@ class LSPClientServer { }; std::queue mDidChangeQueue; Mutex mDidChangeMutex; + bool mIsProcessingQueue{ false }; std::mutex mShutdownMutex; std::condition_variable mShutdownCond; diff --git a/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp b/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp index 7e54b2aa2..830360681 100644 --- a/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp +++ b/src/tools/ecode/plugins/lsp/lspdocumentclient.cpp @@ -70,8 +70,7 @@ void LSPDocumentClient::onDocumentTextChanged( const DocumentContentChange& chan ++mVersion; // If several change event are being fired, the thread pool can't guaranteed that it will be // executed in FIFO. Se we accumulate the events in a queue and fire them in correct order. - mServer->queueDidChange( mDoc->getURI(), mVersion, "", { change } ); - mServer->getThreadPool()->run( [this, change]() { mServer->processDidChangeQueue(); } ); + mServer->queueAndProcess( mDoc->getURI(), mVersion, { change } ); requestSymbolsDelayed(); requestSemanticHighlightingDelayed(); }