diff --git a/src/clang_complete.cc b/src/clang_complete.cc index f310180d..f4fde92c 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -618,14 +618,14 @@ void CompletionManager::NotifySave(const std::string &filename) { void CompletionManager::OnClose(const std::string &filename) { std::lock_guard lock(sessions_lock_); - preloads.TryTake(filename); - sessions.TryTake(filename); + preloads.Take(filename); + sessions.Take(filename); } bool CompletionManager::EnsureCompletionOrCreatePreloadSession( const std::string &path) { std::lock_guard lock(sessions_lock_); - if (preloads.TryGet(path) || sessions.TryGet(path)) + if (preloads.Get(path) || sessions.Get(path)) return false; // No CompletionSession, create new one. @@ -644,11 +644,11 @@ std::shared_ptr CompletionManager::TryGetSession(const std::string &path, bool preload, bool *is_open) { std::lock_guard lock(sessions_lock_); - std::shared_ptr session = preloads.TryGet(path); + std::shared_ptr session = preloads.Get(path); if (session) { if (!preload) { - preloads.TryTake(path); + preloads.Take(path); sessions.Insert(path, session); if (is_open) *is_open = true; @@ -656,7 +656,7 @@ CompletionManager::TryGetSession(const std::string &path, bool preload, return session; } - session = sessions.TryGet(path); + session = sessions.Get(path); if (!session && !preload) { session = std::make_shared( project_->FindEntry(path, false), wfiles_, PCH); diff --git a/src/clang_complete.hh b/src/clang_complete.hh index e158aa0d..d067818c 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -16,7 +16,6 @@ limitations under the License. #pragma once #include "clang_tu.hh" -#include "lru_cache.hh" #include "lsp.hh" #include "project.hh" #include "threaded_queue.hh" @@ -26,10 +25,12 @@ limitations under the License. #include #include +#include #include #include #include #include +#include namespace ccls { struct PreambleData; @@ -52,6 +53,40 @@ TextEdit ToTextEdit(const clang::SourceManager &SM, const clang::LangOptions &L, const clang::FixItHint &FixIt); +template struct LruCache { + LruCache(int capacity) : capacity(capacity) {} + + std::shared_ptr Get(const K &key) { + for (auto it = items.begin(); it != items.end(); ++it) + if (it->first == key) { + auto x = std::move(*it); + std::move_backward(items.begin(), it, it + 1); + items[0] = std::move(x); + return items[0].second; + } + return nullptr; + } + std::shared_ptr Take(const K &key) { + for (auto it = items.begin(); it != items.end(); ++it) + if (it->first == key) { + auto x = std::move(it->second); + items.erase(it); + return x; + } + return nullptr; + } + void Insert(const K &key, std::shared_ptr value) { + if ((int)items.size() >= capacity) + items.pop_back(); + items.emplace(items.begin(), key, std::move(value)); + } + void Clear() { items.clear(); } + +private: + std::vector>> items; + int capacity; +}; + struct CompletionSession : public std::enable_shared_from_this { std::mutex mutex; diff --git a/src/lru_cache.hh b/src/lru_cache.hh deleted file mode 100644 index 5e0253a2..00000000 --- a/src/lru_cache.hh +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include -#include -#include -#include -#include - -// Cache that evicts old entries which have not been used recently. Implemented -// using array/linear search so this works well for small array sizes. -template struct LruCache { - explicit LruCache(int max_entries); - - // Fetches an entry for |key|. If it does not exist, |allocator| will be - // invoked to create one. - template - std::shared_ptr Get(const TKey &key, TAllocator allocator); - // Fetches the entry for |filename| and updates it's usage so it is less - // likely to be evicted. - std::shared_ptr TryGet(const TKey &key); - // TryGetEntry, except the entry is removed from the cache. - std::shared_ptr TryTake(const TKey &key); - // Inserts an entry. Evicts the oldest unused entry if there is no space. - void Insert(const TKey &key, const std::shared_ptr &value); - - // Call |func| on existing entries. If |func| returns false iteration - // temrinates early. - template void IterateValues(TFunc func); - - // Empties the cache - void Clear(void); - -private: - // There is a global score counter, when we access an element we increase - // its score to the current global value, so it has the highest overall - // score. This means that the oldest/least recently accessed value has the - // lowest score. - // - // There is a bit of special logic to handle score overlow. - struct Entry { - uint32_t score = 0; - TKey key; - std::shared_ptr value; - bool operator<(const Entry &other) const { return score < other.score; } - }; - - void IncrementScore(); - - std::vector entries_; - int max_entries_ = 1; - uint32_t next_score_ = 0; -}; - -template -LruCache::LruCache(int max_entries) : max_entries_(max_entries) { - assert(max_entries > 0); -} - -template -template -std::shared_ptr LruCache::Get(const TKey &key, - TAllocator allocator) { - std::shared_ptr result = TryGet(key); - if (!result) - Insert(key, result = allocator()); - return result; -} - -template -std::shared_ptr LruCache::TryGet(const TKey &key) { - // Assign new score. - for (Entry &entry : entries_) { - if (entry.key == key) { - entry.score = next_score_; - IncrementScore(); - return entry.value; - } - } - - return nullptr; -} - -template -std::shared_ptr LruCache::TryTake(const TKey &key) { - for (size_t i = 0; i < entries_.size(); ++i) { - if (entries_[i].key == key) { - std::shared_ptr copy = entries_[i].value; - entries_.erase(entries_.begin() + i); - return copy; - } - } - - return nullptr; -} - -template -void LruCache::Insert(const TKey &key, - const std::shared_ptr &value) { - if ((int)entries_.size() >= max_entries_) - entries_.erase(std::min_element(entries_.begin(), entries_.end())); - - Entry entry; - entry.score = next_score_; - IncrementScore(); - entry.key = key; - entry.value = value; - entries_.push_back(entry); -} - -template -template -void LruCache::IterateValues(TFunc func) { - for (Entry &entry : entries_) { - if (!func(entry.value)) - break; - } -} - -template -void LruCache::IncrementScore() { - // Overflow. - if (++next_score_ == 0) { - std::sort(entries_.begin(), entries_.end()); - for (Entry &entry : entries_) - entry.score = next_score_++; - } -} - -template -void LruCache::Clear(void) { - entries_.clear(); - next_score_ = 0; -} diff --git a/src/message_handler.cc b/src/message_handler.cc index c9ff275d..ee67ee6c 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -32,7 +32,7 @@ MAKE_HASHABLE(ccls::SymbolIdx, t.usr, t.kind); namespace ccls { MAKE_REFLECT_STRUCT(CodeActionParam::Context, diagnostics); MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context); -MAKE_REFLECT_STRUCT(EmptyParam, placeholder); +void Reflect(Reader &, EmptyParam &) {} MAKE_REFLECT_STRUCT(TextDocumentParam, textDocument); MAKE_REFLECT_STRUCT(DidOpenTextDocumentParam, textDocument); MAKE_REFLECT_STRUCT(TextDocumentContentChangeEvent, range, rangeLength, text); diff --git a/src/message_handler.hh b/src/message_handler.hh index e5e07844..8eca9375 100644 --- a/src/message_handler.hh +++ b/src/message_handler.hh @@ -43,9 +43,7 @@ struct CodeActionParam { std::vector diagnostics; } context; }; -struct EmptyParam { - bool placeholder; -}; +struct EmptyParam {}; struct DidOpenTextDocumentParam { TextDocumentItem textDocument; }; diff --git a/src/pipeline.cc b/src/pipeline.cc index 347ecab7..c91f338d 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -465,7 +465,6 @@ void LaunchStdin() { std::string method; ReflectMember(reader, "id", id); ReflectMember(reader, "method", method); - auto param = std::make_unique(); on_request->PushBack( {id, std::move(method), std::move(message), std::move(document)});