mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 09:05:10 +00:00
Make EmptyParam empty & rewrite LruCache
This commit is contained in:
parent
9603a73421
commit
38e87a0729
@ -607,14 +607,14 @@ void CompletionManager::NotifySave(const std::string &filename) {
|
||||
|
||||
void CompletionManager::OnClose(const std::string &filename) {
|
||||
std::lock_guard<std::mutex> 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<std::mutex> 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<ccls::CompletionSession>
|
||||
CompletionManager::TryGetSession(const std::string &path, bool preload,
|
||||
bool *is_open) {
|
||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||
std::shared_ptr<ccls::CompletionSession> session = preloads.TryGet(path);
|
||||
std::shared_ptr<ccls::CompletionSession> 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<ccls::CompletionSession>(
|
||||
project_->FindEntry(path, false), wfiles_, PCH);
|
||||
|
@ -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 <clang/Frontend/FrontendActions.h>
|
||||
#include <clang/Sema/CodeCompleteOptions.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ccls {
|
||||
struct PreambleData;
|
||||
@ -40,6 +41,40 @@ TextEdit ToTextEdit(const clang::SourceManager &SM,
|
||||
const clang::LangOptions &L,
|
||||
const clang::FixItHint &FixIt);
|
||||
|
||||
template <typename K, typename V> struct LruCache {
|
||||
LruCache(int capacity) : capacity(capacity) {}
|
||||
|
||||
std::shared_ptr<V> 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<V> 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<V> value) {
|
||||
if ((int)items.size() >= capacity)
|
||||
items.pop_back();
|
||||
items.emplace(items.begin(), key, std::move(value));
|
||||
}
|
||||
void Clear() { items.clear(); }
|
||||
|
||||
private:
|
||||
std::vector<std::pair<K, std::shared_ptr<V>>> items;
|
||||
int capacity;
|
||||
};
|
||||
|
||||
struct CompletionSession
|
||||
: public std::enable_shared_from_this<CompletionSession> {
|
||||
std::mutex mutex;
|
||||
|
136
src/lru_cache.hh
136
src/lru_cache.hh
@ -1,136 +0,0 @@
|
||||
// Copyright 2017-2018 ccls Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// 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 <typename TKey, typename TValue> 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 <typename TAllocator>
|
||||
std::shared_ptr<TValue> 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<TValue> TryGet(const TKey &key);
|
||||
// TryGetEntry, except the entry is removed from the cache.
|
||||
std::shared_ptr<TValue> 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<TValue> &value);
|
||||
|
||||
// Call |func| on existing entries. If |func| returns false iteration
|
||||
// temrinates early.
|
||||
template <typename TFunc> 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<TValue> value;
|
||||
bool operator<(const Entry &other) const { return score < other.score; }
|
||||
};
|
||||
|
||||
void IncrementScore();
|
||||
|
||||
std::vector<Entry> entries_;
|
||||
int max_entries_ = 1;
|
||||
uint32_t next_score_ = 0;
|
||||
};
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
LruCache<TKey, TValue>::LruCache(int max_entries) : max_entries_(max_entries) {
|
||||
assert(max_entries > 0);
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
template <typename TAllocator>
|
||||
std::shared_ptr<TValue> LruCache<TKey, TValue>::Get(const TKey &key,
|
||||
TAllocator allocator) {
|
||||
std::shared_ptr<TValue> result = TryGet(key);
|
||||
if (!result)
|
||||
Insert(key, result = allocator());
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
std::shared_ptr<TValue> LruCache<TKey, TValue>::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 <typename TKey, typename TValue>
|
||||
std::shared_ptr<TValue> LruCache<TKey, TValue>::TryTake(const TKey &key) {
|
||||
for (size_t i = 0; i < entries_.size(); ++i) {
|
||||
if (entries_[i].key == key) {
|
||||
std::shared_ptr<TValue> copy = entries_[i].value;
|
||||
entries_.erase(entries_.begin() + i);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::Insert(const TKey &key,
|
||||
const std::shared_ptr<TValue> &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 <typename TKey, typename TValue>
|
||||
template <typename TFunc>
|
||||
void LruCache<TKey, TValue>::IterateValues(TFunc func) {
|
||||
for (Entry &entry : entries_) {
|
||||
if (!func(entry.value))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::IncrementScore() {
|
||||
// Overflow.
|
||||
if (++next_score_ == 0) {
|
||||
std::sort(entries_.begin(), entries_.end());
|
||||
for (Entry &entry : entries_)
|
||||
entry.score = next_score_++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
void LruCache<TKey, TValue>::Clear(void) {
|
||||
entries_.clear();
|
||||
next_score_ = 0;
|
||||
}
|
@ -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);
|
||||
|
@ -31,9 +31,7 @@ struct CodeActionParam {
|
||||
std::vector<Diagnostic> diagnostics;
|
||||
} context;
|
||||
};
|
||||
struct EmptyParam {
|
||||
bool placeholder;
|
||||
};
|
||||
struct EmptyParam {};
|
||||
struct DidOpenTextDocumentParam {
|
||||
TextDocumentItem textDocument;
|
||||
};
|
||||
|
@ -453,7 +453,6 @@ void LaunchStdin() {
|
||||
std::string method;
|
||||
ReflectMember(reader, "id", id);
|
||||
ReflectMember(reader, "method", method);
|
||||
auto param = std::make_unique<rapidjson::Value>();
|
||||
on_request->PushBack(
|
||||
{id, std::move(method), std::move(message), std::move(document)});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user