mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-20 15:40:57 +00:00
Simplify completion session management code.
This commit is contained in:
parent
3e9cffcc62
commit
76cc110cc2
@ -336,8 +336,9 @@ void CompletionParseMain(ClangCompleteManager* completion_manager) {
|
||||
// If we don't get a session then that means we don't care about the file
|
||||
// anymore - abandon the request.
|
||||
std::shared_ptr<CompletionSession> session =
|
||||
completion_manager->TryGetEditSession(request.path,
|
||||
false /*create_if_needed*/);
|
||||
completion_manager->TryGetSession(request.path,
|
||||
false /*mark_as_completion*/,
|
||||
false /*create_if_needed*/);
|
||||
if (!session)
|
||||
continue;
|
||||
|
||||
@ -369,7 +370,8 @@ void CompletionQueryMain(ClangCompleteManager* completion_manager) {
|
||||
std::string path = request->document.uri.GetPath();
|
||||
|
||||
std::shared_ptr<CompletionSession> session =
|
||||
completion_manager->TryGetEditSession(path, true /*create_if_needed*/);
|
||||
completion_manager->TryGetSession(path, true /*mark_as_completion*/,
|
||||
true /*create_if_needed*/);
|
||||
|
||||
std::lock_guard<std::mutex> lock(session->tu_lock);
|
||||
Timer timer;
|
||||
@ -548,8 +550,8 @@ ClangCompleteManager::ClangCompleteManager(Config* config,
|
||||
working_files_(working_files),
|
||||
on_diagnostic_(on_diagnostic),
|
||||
on_index_(on_index),
|
||||
view_sessions_(kMaxViewSessions),
|
||||
edit_sessions_(kMaxEditSessions) {
|
||||
preloaded_sessions_(kMaxPreloadedSessions),
|
||||
completion_sessions_(kMaxCompletionSessions) {
|
||||
new std::thread([&]() {
|
||||
SetCurrentThreadName("completequery");
|
||||
CompletionQueryMain(this);
|
||||
@ -600,44 +602,19 @@ void ClangCompleteManager::NotifyView(const std::string& filename) {
|
||||
// parsed soon.
|
||||
//
|
||||
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
|
||||
// Already a view or edit session, do nothing.
|
||||
if (view_sessions_.TryGetEntry(filename) ||
|
||||
edit_sessions_.TryGetEntry(filename)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new view session.
|
||||
view_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||
parse_requests_.Enqueue(ParseRequest(filename));
|
||||
// Only reparse the file if we create a new CompletionSession.
|
||||
if (EnsureCompletionOrCreatePreloadSession(filename))
|
||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||
}
|
||||
|
||||
void ClangCompleteManager::NotifyEdit(const std::string& filename) {
|
||||
//
|
||||
// On edit, we reparse only if the file has not been parsed. The existence of
|
||||
// a CompletionSession instance implies the file is already parsed or will be
|
||||
// parsed soon.
|
||||
// We treat an edit like a view, because the completion logic will handle
|
||||
// moving the CompletionSession instance from preloaded to completion
|
||||
// storage.
|
||||
//
|
||||
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
|
||||
if (edit_sessions_.TryGetEntry(filename))
|
||||
return;
|
||||
|
||||
// Move the session from view to edit.
|
||||
std::shared_ptr<CompletionSession> view_session =
|
||||
view_sessions_.TryTakeEntry(filename);
|
||||
if (view_session) {
|
||||
edit_sessions_.InsertEntry(view_session);
|
||||
return;
|
||||
}
|
||||
|
||||
// No view session, create a new session.
|
||||
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||
NotifyView(filename);
|
||||
}
|
||||
|
||||
void ClangCompleteManager::NotifySave(const std::string& filename) {
|
||||
@ -645,22 +622,7 @@ void ClangCompleteManager::NotifySave(const std::string& filename) {
|
||||
// On save, always reparse.
|
||||
//
|
||||
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
|
||||
// If for whatever reason we have a view session and not an edit session,
|
||||
// move the session from view to edit.
|
||||
std::shared_ptr<CompletionSession> view_session =
|
||||
view_sessions_.TryTakeEntry(filename);
|
||||
if (view_session) {
|
||||
edit_sessions_.InsertEntry(view_session);
|
||||
}
|
||||
|
||||
// If no edit session create one.
|
||||
if (!edit_sessions_.TryGetEntry(filename)) {
|
||||
edit_sessions_.InsertEntry(std::make_shared<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_));
|
||||
}
|
||||
|
||||
EnsureCompletionOrCreatePreloadSession(filename);
|
||||
parse_requests_.PriorityEnqueue(ParseRequest(filename));
|
||||
}
|
||||
|
||||
@ -673,39 +635,60 @@ void ClangCompleteManager::NotifyClose(const std::string& filename) {
|
||||
|
||||
// Take and drop. It's okay if we don't actually drop the file, it'll
|
||||
// eventually get pushed out of the caches as the user opens other files.
|
||||
auto view_ptr = view_sessions_.TryTakeEntry(filename);
|
||||
LOG_IF_S(INFO, !!view_ptr)
|
||||
<< "Dropped view-based code completion session for " << filename;
|
||||
auto edit_ptr = edit_sessions_.TryTakeEntry(filename);
|
||||
LOG_IF_S(INFO, !!edit_ptr)
|
||||
<< "Dropped edit-based code completion session for " << filename;
|
||||
auto preloaded_ptr = preloaded_sessions_.TryTakeEntry(filename);
|
||||
LOG_IF_S(INFO, !!preloaded_ptr)
|
||||
<< "Dropped preloaded-based code completion session for " << filename;
|
||||
auto completion_ptr = completion_sessions_.TryTakeEntry(filename);
|
||||
LOG_IF_S(INFO, !!completion_ptr)
|
||||
<< "Dropped completion-based code completion session for " << filename;
|
||||
|
||||
// We should never have both a view and edit session.
|
||||
assert((view_ptr && edit_ptr) == false);
|
||||
// We should never have both a preloaded and completion session.
|
||||
assert((preloaded_ptr && completion_ptr) == false);
|
||||
}
|
||||
|
||||
std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetEditSession(
|
||||
bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession(
|
||||
const std::string& filename) {
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
if (!preloaded_sessions_.TryGetEntry(filename) &&
|
||||
!completion_sessions_.TryGetEntry(filename)) {
|
||||
auto session = std::make_shared<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_);
|
||||
preloaded_sessions_.InsertEntry(session);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<CompletionSession> ClangCompleteManager::TryGetSession(
|
||||
const std::string& filename,
|
||||
bool mark_as_completion,
|
||||
bool create_if_needed) {
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
|
||||
// Try to find a view session. If found move it to |edit_sessions_|.
|
||||
std::shared_ptr<CompletionSession> view_session =
|
||||
view_sessions_.TryTakeEntry(filename);
|
||||
if (view_session) {
|
||||
assert(!edit_sessions_.TryGetEntry(filename));
|
||||
edit_sessions_.InsertEntry(view_session);
|
||||
return view_session;
|
||||
// Try to find a preloaded session.
|
||||
std::shared_ptr<CompletionSession> preloaded_session =
|
||||
preloaded_sessions_.TryGetEntry(filename);
|
||||
|
||||
if (preloaded_session) {
|
||||
// If this request is for a completion, we should move it to
|
||||
// |completion_sessions|.
|
||||
if (mark_as_completion) {
|
||||
assert(!completion_sessions_.TryGetEntry(filename));
|
||||
preloaded_sessions_.TryTakeEntry(filename);
|
||||
completion_sessions_.InsertEntry(preloaded_session);
|
||||
}
|
||||
|
||||
return preloaded_session;
|
||||
}
|
||||
|
||||
// Try to find an edit session. If none create if requested.
|
||||
std::shared_ptr<CompletionSession> edit_session =
|
||||
edit_sessions_.TryTakeEntry(filename);
|
||||
if (!edit_session && create_if_needed) {
|
||||
edit_session = std::make_shared<CompletionSession>(
|
||||
// Try to find a completion session. If none create one.
|
||||
std::shared_ptr<CompletionSession> completion_session =
|
||||
completion_sessions_.TryTakeEntry(filename);
|
||||
if (!completion_session && create_if_needed) {
|
||||
completion_session = std::make_shared<CompletionSession>(
|
||||
project_->FindCompilationEntryForFile(filename), working_files_);
|
||||
edit_sessions_.InsertEntry(edit_session);
|
||||
completion_sessions_.InsertEntry(completion_session);
|
||||
}
|
||||
|
||||
return edit_session;
|
||||
return completion_session;
|
||||
}
|
||||
|
@ -99,15 +99,18 @@ struct ClangCompleteManager {
|
||||
// completion session will be dropped.
|
||||
void NotifyClose(const std::string& filename);
|
||||
|
||||
// Ensures there is a completion or preloaded session. Returns true if a new
|
||||
// session was created.
|
||||
bool EnsureCompletionOrCreatePreloadSession(const std::string& filename);
|
||||
// Tries to find an edit session for |filename|. This will move the session
|
||||
// from view to edit.
|
||||
std::shared_ptr<CompletionSession> TryGetEditSession(
|
||||
const std::string& filename,
|
||||
bool create_if_needed);
|
||||
std::shared_ptr<CompletionSession> TryGetSession(const std::string& filename,
|
||||
bool mark_as_completion,
|
||||
bool create_if_needed);
|
||||
|
||||
// TODO: make these configurable.
|
||||
const int kMaxViewSessions = 10;
|
||||
const int kMaxEditSessions = 5;
|
||||
const int kMaxPreloadedSessions = 10;
|
||||
const int kMaxCompletionSessions = 5;
|
||||
|
||||
// Global state.
|
||||
Config* config_;
|
||||
@ -116,11 +119,13 @@ struct ClangCompleteManager {
|
||||
OnDiagnostic on_diagnostic_;
|
||||
OnIndex on_index_;
|
||||
|
||||
// Sessions which have never had a real text-edit applied, but are preloaded
|
||||
// to give a fast initial experience.
|
||||
LruSessionCache view_sessions_;
|
||||
// Completion sessions which have been edited.
|
||||
LruSessionCache edit_sessions_;
|
||||
// CompletionSession instances which are preloaded, ie, files which the user
|
||||
// has viewed but not requested code completion for.
|
||||
LruSessionCache preloaded_sessions_;
|
||||
// CompletionSession instances which the user has actually performed
|
||||
// completion on. This is more rare so these instances tend to stay alive
|
||||
// much longer than the ones in |preloaded_sessions_|.
|
||||
LruSessionCache completion_sessions_;
|
||||
// Mutex which protects |view_sessions_| and |edit_sessions_|.
|
||||
std::mutex sessions_lock_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user