mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-11-04 06:15:20 +00:00 
			
		
		
		
	Make EmptyParam empty & rewrite LruCache
This commit is contained in:
		
							parent
							
								
									0606b95754
								
							
						
					
					
						commit
						e6510f7428
					
				@ -618,14 +618,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.
 | 
			
		||||
@ -644,11 +644,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;
 | 
			
		||||
@ -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<ccls::CompletionSession>(
 | 
			
		||||
        project_->FindEntry(path, false), wfiles_, PCH);
 | 
			
		||||
 | 
			
		||||
@ -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 <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;
 | 
			
		||||
@ -52,6 +53,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;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										148
									
								
								src/lru_cache.hh
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								src/lru_cache.hh
									
									
									
									
									
								
							@ -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 <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;
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -43,9 +43,7 @@ struct CodeActionParam {
 | 
			
		||||
    std::vector<Diagnostic> diagnostics;
 | 
			
		||||
  } context;
 | 
			
		||||
};
 | 
			
		||||
struct EmptyParam {
 | 
			
		||||
  bool placeholder;
 | 
			
		||||
};
 | 
			
		||||
struct EmptyParam {};
 | 
			
		||||
struct DidOpenTextDocumentParam {
 | 
			
		||||
  TextDocumentItem textDocument;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -465,7 +465,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