Cache deletion is now async

This commit is contained in:
Strahinja Val Markovic 2013-03-16 12:10:24 -07:00
parent 1fce7ccec2
commit 4cb9f17c5f
5 changed files with 56 additions and 10 deletions

View File

@ -262,13 +262,21 @@ ClangCompleter::CandidatesForQueryAndLocationInFileAsync(
}
void ClangCompleter::DeleteCachesForFile( const std::string &filename ) {
// If the clang thread is currently parsing the file when the user deletes the
// buffer and thus we try to delete the caches, Vim's GUI thread would block
// until the clang thread releases the mutex. Move this operation to the clang
// thread.
void ClangCompleter::DeleteCachesForFileAsync( const std::string &filename ) {
file_cache_delete_stack_.Push( filename );
}
void ClangCompleter::DeleteCaches() {
std::vector< std::string > filenames;
if ( !file_cache_delete_stack_.PopAllNoWait( filenames ) )
return;
lock_guard< mutex > lock( filename_to_translation_unit_mutex_ );
filename_to_translation_unit_.erase( filename );
foreach( const std::string &filename, filenames ) {
filename_to_translation_unit_.erase( filename );
}
}
@ -466,8 +474,10 @@ void ClangCompleter::ClangThreadMain() {
else
task->parsing_task_();
if ( !has_completions_task )
if ( !has_completions_task ) {
DeleteCaches();
continue;
}
unique_future< AsyncCompletions > future =
task->completions_task_.get_future();

View File

@ -19,6 +19,7 @@
#define CLANGCOMPLETE_H_WLKDU0ZV
#include "ConcurrentLatestValue.h"
#include "ConcurrentStack.h"
#include "Future.h"
#include "UnsavedFile.h"
#include "Diagnostic.h"
@ -93,10 +94,12 @@ public:
const std::vector< UnsavedFile > &unsaved_files,
const std::vector< std::string > &flags );
void DeleteCachesForFile( const std::string &filename );
void DeleteCachesForFileAsync( const std::string &filename );
private:
void DeleteCaches();
// This is basically a union. Only one of the two tasks is set to something
// valid, the other task is invalid. Which one is valid depends on the caller.
struct ClangPackagedTask {
@ -111,6 +114,8 @@ private:
typedef ConcurrentLatestValue <
boost::shared_ptr< ClangPackagedTask > > LatestClangTask;
typedef ConcurrentStack< std::string > FileCacheDeleteStack;
bool ShouldSkipClangResultCache( const std::string &query,
int line,
int column );
@ -173,6 +178,8 @@ private:
ClangResultsCache latest_clang_results_;
FileCacheDeleteStack file_cache_delete_stack_;
// Unfortunately clang is not thread-safe so we need to be careful when we
// access it. Only one thread at a time is allowed to access any single
// translation unit. Currently we only use one thread to access clang and that

View File

@ -37,6 +37,7 @@ public:
condition_variable_.notify_one();
}
T Pop() {
boost::unique_lock< boost::mutex > lock( mutex_ );
@ -49,6 +50,33 @@ public:
return top;
}
// Gets all the items from the stack and appends them to the input vector.
// Does not wait for the stack to get items; if the stack is empty, returns
// false and does not touch the input vector.
bool PopAllNoWait( std::vector< T > &items ) {
boost::unique_lock< boost::mutex > lock( mutex_ );
if ( stack_.empty() )
return false;
int num_items = stack_.size();
items.reserve( num_items + items.size() );
for ( int i = 0; i < num_items; ++i ) {
items.push_back( stack_.top() );
stack_.pop();
}
return true;
}
bool Empty() {
boost::unique_lock< boost::mutex > lock( mutex_ );
return stack_.empty();
}
private:
std::stack< T > stack_;
boost::mutex mutex_;

View File

@ -115,7 +115,8 @@ BOOST_PYTHON_MODULE(ycm_core)
class_< ClangCompleter, boost::noncopyable >( "ClangCompleter" )
.def( "EnableThreading", &ClangCompleter::EnableThreading )
.def( "DiagnosticsForFile", &ClangCompleter::DiagnosticsForFile )
.def( "DeleteCachesForFile", &ClangCompleter::DeleteCachesForFile )
.def( "DeleteCachesForFileAsync",
&ClangCompleter::DeleteCachesForFileAsync )
.def( "UpdatingTranslationUnit", &ClangCompleter::UpdatingTranslationUnit )
.def( "UpdateTranslationUnitAsync",
&ClangCompleter::UpdateTranslationUnitAsync )

View File

@ -148,7 +148,7 @@ class ClangCompleter( Completer ):
def OnBufferDelete( self, deleted_buffer_file ):
self.completer.DeleteCachesForFile( deleted_buffer_file )
self.completer.DeleteCachesForFileAsync( deleted_buffer_file )
def DiagnosticsForCurrentFileReady( self ):