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) {
|
void CompletionManager::OnClose(const std::string &filename) {
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||||
preloads.TryTake(filename);
|
preloads.Take(filename);
|
||||||
sessions.TryTake(filename);
|
sessions.Take(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompletionManager::EnsureCompletionOrCreatePreloadSession(
|
bool CompletionManager::EnsureCompletionOrCreatePreloadSession(
|
||||||
const std::string &path) {
|
const std::string &path) {
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
std::lock_guard<std::mutex> lock(sessions_lock_);
|
||||||
if (preloads.TryGet(path) || sessions.TryGet(path))
|
if (preloads.Get(path) || sessions.Get(path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// No CompletionSession, create new one.
|
// No CompletionSession, create new one.
|
||||||
@ -633,11 +633,11 @@ std::shared_ptr<ccls::CompletionSession>
|
|||||||
CompletionManager::TryGetSession(const std::string &path, bool preload,
|
CompletionManager::TryGetSession(const std::string &path, bool preload,
|
||||||
bool *is_open) {
|
bool *is_open) {
|
||||||
std::lock_guard<std::mutex> lock(sessions_lock_);
|
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 (session) {
|
||||||
if (!preload) {
|
if (!preload) {
|
||||||
preloads.TryTake(path);
|
preloads.Take(path);
|
||||||
sessions.Insert(path, session);
|
sessions.Insert(path, session);
|
||||||
if (is_open)
|
if (is_open)
|
||||||
*is_open = true;
|
*is_open = true;
|
||||||
@ -645,7 +645,7 @@ CompletionManager::TryGetSession(const std::string &path, bool preload,
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
session = sessions.TryGet(path);
|
session = sessions.Get(path);
|
||||||
if (!session && !preload) {
|
if (!session && !preload) {
|
||||||
session = std::make_shared<ccls::CompletionSession>(
|
session = std::make_shared<ccls::CompletionSession>(
|
||||||
project_->FindEntry(path, false), wfiles_, PCH);
|
project_->FindEntry(path, false), wfiles_, PCH);
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "clang_tu.hh"
|
#include "clang_tu.hh"
|
||||||
#include "lru_cache.hh"
|
|
||||||
#include "lsp.hh"
|
#include "lsp.hh"
|
||||||
#include "project.hh"
|
#include "project.hh"
|
||||||
#include "threaded_queue.hh"
|
#include "threaded_queue.hh"
|
||||||
@ -14,10 +13,12 @@
|
|||||||
#include <clang/Frontend/FrontendActions.h>
|
#include <clang/Frontend/FrontendActions.h>
|
||||||
#include <clang/Sema/CodeCompleteOptions.h>
|
#include <clang/Sema/CodeCompleteOptions.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
struct PreambleData;
|
struct PreambleData;
|
||||||
@ -40,6 +41,40 @@ TextEdit ToTextEdit(const clang::SourceManager &SM,
|
|||||||
const clang::LangOptions &L,
|
const clang::LangOptions &L,
|
||||||
const clang::FixItHint &FixIt);
|
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
|
struct CompletionSession
|
||||||
: public std::enable_shared_from_this<CompletionSession> {
|
: public std::enable_shared_from_this<CompletionSession> {
|
||||||
std::mutex mutex;
|
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 {
|
namespace ccls {
|
||||||
MAKE_REFLECT_STRUCT(CodeActionParam::Context, diagnostics);
|
MAKE_REFLECT_STRUCT(CodeActionParam::Context, diagnostics);
|
||||||
MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context);
|
MAKE_REFLECT_STRUCT(CodeActionParam, textDocument, range, context);
|
||||||
MAKE_REFLECT_STRUCT(EmptyParam, placeholder);
|
void Reflect(Reader &, EmptyParam &) {}
|
||||||
MAKE_REFLECT_STRUCT(TextDocumentParam, textDocument);
|
MAKE_REFLECT_STRUCT(TextDocumentParam, textDocument);
|
||||||
MAKE_REFLECT_STRUCT(DidOpenTextDocumentParam, textDocument);
|
MAKE_REFLECT_STRUCT(DidOpenTextDocumentParam, textDocument);
|
||||||
MAKE_REFLECT_STRUCT(TextDocumentContentChangeEvent, range, rangeLength, text);
|
MAKE_REFLECT_STRUCT(TextDocumentContentChangeEvent, range, rangeLength, text);
|
||||||
|
@ -31,9 +31,7 @@ struct CodeActionParam {
|
|||||||
std::vector<Diagnostic> diagnostics;
|
std::vector<Diagnostic> diagnostics;
|
||||||
} context;
|
} context;
|
||||||
};
|
};
|
||||||
struct EmptyParam {
|
struct EmptyParam {};
|
||||||
bool placeholder;
|
|
||||||
};
|
|
||||||
struct DidOpenTextDocumentParam {
|
struct DidOpenTextDocumentParam {
|
||||||
TextDocumentItem textDocument;
|
TextDocumentItem textDocument;
|
||||||
};
|
};
|
||||||
|
@ -453,7 +453,6 @@ void LaunchStdin() {
|
|||||||
std::string method;
|
std::string method;
|
||||||
ReflectMember(reader, "id", id);
|
ReflectMember(reader, "id", id);
|
||||||
ReflectMember(reader, "method", method);
|
ReflectMember(reader, "method", method);
|
||||||
auto param = std::make_unique<rapidjson::Value>();
|
|
||||||
on_request->PushBack(
|
on_request->PushBack(
|
||||||
{id, std::move(method), std::move(message), std::move(document)});
|
{id, std::move(method), std::move(message), std::move(document)});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user