From 38e87a07299559d61a9ee6684001ca088da3efcd Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 26 Nov 2018 21:00:30 -0800 Subject: [PATCH] Make EmptyParam empty & rewrite LruCache --- src/clang_complete.cc | 12 ++-- src/clang_complete.hh | 37 ++++++++++- src/lru_cache.hh | 136 ----------------------------------------- src/message_handler.cc | 2 +- src/message_handler.hh | 4 +- src/pipeline.cc | 1 - 6 files changed, 44 insertions(+), 148 deletions(-) delete mode 100644 src/lru_cache.hh diff --git a/src/clang_complete.cc b/src/clang_complete.cc index 3e52839f..f725d98e 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -607,14 +607,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. @@ -633,11 +633,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; @@ -645,7 +645,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 7223c78f..0a7b8e22 100644 --- a/src/clang_complete.hh +++ b/src/clang_complete.hh @@ -4,7 +4,6 @@ #pragma once #include "clang_tu.hh" -#include "lru_cache.hh" #include "lsp.hh" #include "project.hh" #include "threaded_queue.hh" @@ -14,10 +13,12 @@ #include #include +#include #include #include #include #include +#include namespace ccls { struct PreambleData; @@ -40,6 +41,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 b630a3d8..00000000 --- a/src/lru_cache.hh +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2017-2018 ccls Authors -// SPDX-License-Identifier: Apache-2.0 - -#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 cc5fc28f..48bd432d 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -20,7 +20,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 d3bda369..030f626d 100644 --- a/src/message_handler.hh +++ b/src/message_handler.hh @@ -31,9 +31,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 feed8880..0ef0af0e 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -453,7 +453,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)});