Implement new threading model for computing index updates (prepare IdMap on querydb thread)

This commit is contained in:
Jacob Dufault 2017-04-07 23:45:28 -07:00
parent 22cc140d80
commit 4249fc4a38
4 changed files with 204 additions and 183 deletions

View File

@ -30,7 +30,7 @@ const int kQueueSizeBytes = 1024 * 8;
const int kMaxWorkspaceSearchResults = 1000; const int kMaxWorkspaceSearchResults = 1000;
} }
struct IndexTranslationUnitRequest { struct Index_DoIndex {
enum class Type { enum class Type {
Import, Import,
Update Update
@ -40,18 +40,37 @@ struct IndexTranslationUnitRequest {
std::vector<std::string> args; std::vector<std::string> args;
Type type; Type type;
IndexTranslationUnitRequest(Type type) : type(type) {} Index_DoIndex(Type type) : type(type) {}
}; };
struct IndexTranslationUnitResponse { struct Index_DoIdMap {
std::unique_ptr<IndexedFile> previous;
std::unique_ptr<IndexedFile> current;
explicit Index_DoIdMap(std::unique_ptr<IndexedFile> previous,
std::unique_ptr<IndexedFile> current)
: previous(std::move(previous)),
current(std::move(current)) {}
};
struct Index_OnIdMapped {
std::unique_ptr<IndexedFile> previous_index;
std::unique_ptr<IndexedFile> current_index;
std::unique_ptr<IdMap> previous_id_map;
std::unique_ptr<IdMap> current_id_map;
};
struct Index_OnIndexed {
IndexUpdate update; IndexUpdate update;
explicit IndexTranslationUnitResponse(IndexUpdate& update) : update(update) {} explicit Index_OnIndexed(IndexUpdate& update) : update(update) {}
}; };
// TODO: Rename TypedBidiMessageQueue to IpcTransport? // TODO: Rename TypedBidiMessageQueue to IpcTransport?
using IpcMessageQueue = TypedBidiMessageQueue<IpcId, BaseIpcMessage>; using IpcMessageQueue = TypedBidiMessageQueue<IpcId, BaseIpcMessage>;
using IndexRequestQueue = ThreadedQueue<IndexTranslationUnitRequest>; using Index_DoIndexQueue = ThreadedQueue<std::unique_ptr<Index_DoIndex>>;
using IndexResponseQueue = ThreadedQueue<IndexTranslationUnitResponse>; using Index_DoIdMapQueue = ThreadedQueue<std::unique_ptr<Index_DoIdMap>>;
using Index_OnIdMappedQueue = ThreadedQueue<std::unique_ptr<Index_OnIdMapped>>;
using Index_OnIndexedQueue = ThreadedQueue<std::unique_ptr<Index_OnIndexed>>;
template<typename TMessage> template<typename TMessage>
void SendMessage(IpcMessageQueue& t, MessageQueue* destination, TMessage& message) { void SendMessage(IpcMessageQueue& t, MessageQueue* destination, TMessage& message) {
@ -222,22 +241,26 @@ std::string GetCachedFileName(std::string source_file) {
return kCacheDirectory + source_file + ".json"; return kCacheDirectory + source_file + ".json";
} }
optional<IndexedFile> LoadCachedFile(std::string filename) { std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename) {
// TODO FIXME FIXME FIXME // TODO FIXME FIXME FIXME
return nullopt; return nullptr;
std::string cache_file = GetCachedFileName(filename); std::string cache_file = GetCachedFileName(filename);
std::ifstream cache; std::ifstream cache;
cache.open(GetCachedFileName(filename)); cache.open(GetCachedFileName(filename));
if (!cache.good()) if (!cache.good())
return nullopt; return nullptr;
std::string file_content = std::string( std::string file_content = std::string(
std::istreambuf_iterator<char>(cache), std::istreambuf_iterator<char>(cache),
std::istreambuf_iterator<char>()); std::istreambuf_iterator<char>());
return Deserialize(filename, file_content); optional<IndexedFile> indexed = Deserialize(filename, file_content);
if (indexed)
return MakeUnique<IndexedFile>(indexed.value());
return nullptr;
} }
void WriteToCache(std::string filename, IndexedFile& file) { void WriteToCache(std::string filename, IndexedFile& file) {
@ -250,111 +273,85 @@ void WriteToCache(std::string filename, IndexedFile& file) {
cache.close(); cache.close();
} }
void IndexMain(IndexRequestQueue* requests, IndexResponseQueue* responses) {
while (true) {
// Try to get a request. If there isn't one, sleep for a little while.
optional<IndexTranslationUnitRequest> request = requests->TryDequeue();
if (!request) {
// TODO: use CV to wakeup?
std::this_thread::sleep_for(std::chrono::milliseconds(500));
continue;
}
bool IndexMain_DoIndex(Index_DoIndexQueue* queue_do_index,
Index_DoIdMapQueue* queue_do_id_map) {
optional<std::unique_ptr<Index_DoIndex>> opt_index_request = queue_do_index->TryDequeue();
if (!opt_index_request)
return false;
std::unique_ptr<Index_DoIndex> index_request = std::move(opt_index_request.value());
Timer time; Timer time;
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(index_request->path);
time.ResetAndPrint("Loading cached index");
// If the index update is an import, then we will load the previous index // If the index update is an import, then we will load the previous index
// into memory if we have a previous index. After that, we dispatch an // into memory if we have a previous index. After that, we dispatch an
// update request to get the latest version. // update request to get the latest version.
if (request->type == IndexTranslationUnitRequest::Type::Import) { if (old_index && index_request->type == Index_DoIndex::Type::Import) {
request->type = IndexTranslationUnitRequest::Type::Update; auto response = MakeUnique<Index_DoIdMap>(nullptr /*previous*/, std::move(old_index) /*current*/);
queue_do_id_map->Enqueue(std::move(response));
// TODO: we're not serializing out the files cache. We only ever want to import references index_request->type = Index_DoIndex::Type::Update;
// from the primary file though, so that should be ok. We need to cleanup indexer output. queue_do_index->Enqueue(std::move(index_request));
optional<IndexedFile> old_index = LoadCachedFile(request->path);
if (old_index.has_value()) {
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO: We need to create IdMap on QueryDb thread.
IdMap old_id_map(nullptr, old_index->id_cache);
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
IndexUpdate update = IndexUpdate::CreateImport(old_id_map, old_index.value());
IndexTranslationUnitResponse response(update);
responses->Enqueue(response);
time.ResetAndPrint("Loading cached index");
requests->Enqueue(request.value());
continue;
}
}
assert(request->type == IndexTranslationUnitRequest::Type::Update);
// Parse request and send a response.
std::cerr << "Parsing file " << request->path << " with args "
<< Join(request->args, ", ") << std::endl;
IndexedFile new_index = Parse(request->path, request->args);
time.ResetAndPrint("Parsing/indexing");
// If we have a cached index, that means it is already imported, which
// means we want to apply a delta update.
optional<IndexedFile> old_index = LoadCachedFile(request->path);
time.ResetAndPrint("Loading previous index");
if (old_index) {
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO: We need to create IdMap on QueryDb thread.
IdMap old_id_map(nullptr, old_index->id_cache);
IdMap new_id_map(nullptr, new_index.id_cache);
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// Apply delta update.
IndexUpdate update = IndexUpdate::CreateDelta(old_id_map, new_id_map, old_index.value(), new_index);
IndexTranslationUnitResponse response(update);
time.ResetAndPrint("Creating delta index update/response");
responses->Enqueue(response);
time.ResetAndPrint("Sending update to server");
} }
else { else {
// TODO/FIXME/TODO // Parse request and send a response.
// TODO/FIXME/TODO std::cerr << "Parsing file " << index_request->path << " with args "
// TODO/FIXME/TODO << Join(index_request->args, ", ") << std::endl;
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO: We need to create IdMap on QueryDb thread.
IdMap new_id_map(nullptr, new_index.id_cache);
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// TODO/FIXME/TODO
// Apply full update. // TODO: parse should return unique_ptr. Then we can eliminate copy below. Make sure to not
IndexUpdate update = IndexUpdate::CreateImport(new_id_map, new_index); // reuse moved pointer in WriteToCache if we do so.
IndexTranslationUnitResponse response(update); IndexedFile current_index = Parse(index_request->path, index_request->args);
time.ResetAndPrint("Creating index update/response");
responses->Enqueue(response); time.ResetAndPrint("Parsing/indexing");
time.ResetAndPrint("Sending update to server");
} auto response = MakeUnique<Index_DoIdMap>(std::move(old_index) /*previous*/, MakeUnique<IndexedFile>(current_index) /*current*/);
queue_do_id_map->Enqueue(std::move(response));
// Cache file so we can diff it later. // Cache file so we can diff it later.
WriteToCache(request->path, new_index); WriteToCache(index_request->path, current_index);
time.ResetAndPrint("Cache index update to disk"); time.ResetAndPrint("Cache index update to disk");
} }
return true;
}
bool IndexMain_DoCreateIndexUpdate(Index_OnIdMappedQueue* queue_on_id_mapped,
Index_OnIndexedQueue* queue_on_indexed) {
optional<std::unique_ptr<Index_OnIdMapped>> opt_response = queue_on_id_mapped->TryDequeue();
if (!opt_response)
return false;
std::unique_ptr<Index_OnIdMapped> response = std::move(opt_response.value());
Timer time;
IndexUpdate update = IndexUpdate::CreateDelta(response->previous_id_map.get(), response->current_id_map.get(),
response->previous_index.get(), response->current_index.get());
time.ResetAndPrint("Creating delta IndexUpdate");
auto reply = MakeUnique<Index_OnIndexed>(update);
queue_on_indexed->Enqueue(std::move(reply));
time.ResetAndPrint("Sending update to server");
return true;
}
void IndexMain(Index_DoIndexQueue* queue_do_index,
Index_DoIdMapQueue* queue_do_id_map,
Index_OnIdMappedQueue* queue_on_id_mapped,
Index_OnIndexedQueue* queue_on_indexed) {
while (true) {
// TODO: process all off IndexMain_DoIndex before calling IndexMain_DoCreateIndexUpdate for
// better icache behavior. We need to have some threads spinning on both though
// otherwise memory usage will get bad.
if (!IndexMain_DoIndex(queue_do_index, queue_do_id_map) &&
!IndexMain_DoCreateIndexUpdate(queue_on_id_mapped, queue_on_indexed)) {
// TODO: use CV to wakeup?
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
} }
QueryableFile* FindFile(QueryableDatabase* db, const std::string& filename) { QueryableFile* FindFile(QueryableDatabase* db, const std::string& filename) {
@ -457,8 +454,10 @@ void AddCodeLens(std::vector<TCodeLens>* result,
void QueryDbMainLoop( void QueryDbMainLoop(
QueryableDatabase* db, QueryableDatabase* db,
IpcMessageQueue* language_client, IpcMessageQueue* language_client,
IndexRequestQueue* index_requests, Index_DoIndexQueue* queue_do_index,
IndexResponseQueue* index_responses, Index_DoIdMapQueue* queue_do_id_map,
Index_OnIdMappedQueue* queue_on_id_mapped,
Index_OnIndexedQueue* queue_on_indexed,
Project* project, Project* project,
WorkingFiles* working_files, WorkingFiles* working_files,
CompletionManager* completion_manager) { CompletionManager* completion_manager) {
@ -496,10 +495,10 @@ void QueryDbMainLoop(
<< "] Dispatching index request for file " << filepath << "] Dispatching index request for file " << filepath
<< std::endl; << std::endl;
IndexTranslationUnitRequest request(IndexTranslationUnitRequest::Type::Import); auto request = MakeUnique<Index_DoIndex>(Index_DoIndex::Type::Import);
request.path = filepath; request->path = filepath;
request.args = entry.args; request->args = entry.args;
index_requests->Enqueue(request); queue_do_index->Enqueue(std::move(request));
} }
std::cerr << "Done" << std::endl; std::cerr << "Done" << std::endl;
break; break;
@ -711,7 +710,7 @@ void QueryDbMainLoop(
std::string query = msg->params.query; std::string query = msg->params.query;
for (int i = 0; i < db->qualified_names.size(); ++i) { for (int i = 0; i < db->qualified_names.size(); ++i) {
if (response.result.size() > kMaxWorkspaceSearchResults) { if (response.result.size() > kMaxWorkspaceSearchResults) {
std::cerr << "Query exceeded maximum number of responses (" << kMaxWorkspaceSearchResults << "), output may not contain all results"; std::cerr << "Query exceeded maximum number of responses (" << kMaxWorkspaceSearchResults << "), output may not contain all results" << std::endl;
break; break;
} }
@ -729,6 +728,8 @@ void QueryDbMainLoop(
switch (symbol.kind) { switch (symbol.kind) {
case SymbolKind::File: { case SymbolKind::File: {
QueryableFile& def = db->files[symbol.idx]; QueryableFile& def = db->files[symbol.idx];
info.name = def.def.usr;
info.kind = lsSymbolKind::File;
info.location.uri.SetPath(def.def.usr); info.location.uri.SetPath(def.def.usr);
break; break;
} }
@ -795,10 +796,32 @@ void QueryDbMainLoop(
// TODO: consider rate-limiting and checking for IPC messages so we don't block // TODO: consider rate-limiting and checking for IPC messages so we don't block
// requests / we can serve partial requests. // requests / we can serve partial requests.
while (true) { while (true) {
optional<IndexTranslationUnitResponse> response = index_responses->TryDequeue(); optional<std::unique_ptr<Index_DoIdMap>> opt_request = queue_do_id_map->TryDequeue();
if (!response) if (!opt_request)
break; break;
std::unique_ptr<Index_DoIdMap> request = std::move(opt_request.value());
auto response = MakeUnique<Index_OnIdMapped>();
Timer time;
if (request->previous) {
response->previous_id_map = MakeUnique<IdMap>(db, request->previous->id_cache);
response->previous_index = std::move(request->previous);
}
response->current_id_map = MakeUnique<IdMap>(db, request->current->id_cache);
response->current_index = std::move(request->current);
time.ResetAndPrint("Create IdMap");
queue_on_id_mapped->Enqueue(std::move(response));
}
while (true) {
optional<std::unique_ptr<Index_OnIndexed>> opt_response = queue_on_indexed->TryDequeue();
if (!opt_response)
break;
std::unique_ptr<Index_OnIndexed> response = std::move(opt_response.value());
Timer time; Timer time;
db->ApplyIndexUpdate(&response->update); db->ApplyIndexUpdate(&response->update);
@ -811,8 +834,11 @@ void QueryDbMain() {
// Create queues. // Create queues.
std::unique_ptr<IpcMessageQueue> ipc = BuildIpcMessageQueue(kIpcLanguageClientName, kQueueSizeBytes); std::unique_ptr<IpcMessageQueue> ipc = BuildIpcMessageQueue(kIpcLanguageClientName, kQueueSizeBytes);
IndexRequestQueue index_request_queue; Index_DoIndexQueue queue_do_index;
IndexResponseQueue index_response_queue; Index_DoIdMapQueue queue_do_id_map;
Index_OnIdMappedQueue queue_on_id_mapped;
Index_OnIndexedQueue queue_on_indexed;
Project project; Project project;
WorkingFiles working_files; WorkingFiles working_files;
CompletionManager completion_manager(&project, &working_files); CompletionManager completion_manager(&project, &working_files);
@ -820,14 +846,14 @@ void QueryDbMain() {
// Start indexer threads. // Start indexer threads.
for (int i = 0; i < kNumIndexers; ++i) { for (int i = 0; i < kNumIndexers; ++i) {
new std::thread([&]() { new std::thread([&]() {
IndexMain(&index_request_queue, &index_response_queue); IndexMain(&queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed);
}); });
} }
// Run query db main loop. // Run query db main loop.
QueryableDatabase db; QueryableDatabase db;
while (true) { while (true) {
QueryDbMainLoop(&db, ipc.get(), &index_request_queue, &index_response_queue, &project, &working_files, &completion_manager); QueryDbMainLoop(&db, ipc.get(), &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed, &project, &working_files, &completion_manager);
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }

View File

@ -452,8 +452,6 @@ int GetOrAddSymbol(QueryableDatabase* query_db, SymbolKind kind, const Usr& usr)
IdMap::IdMap(QueryableDatabase* query_db, const IdCache& local_ids) IdMap::IdMap(QueryableDatabase* query_db, const IdCache& local_ids)
: local_ids(local_ids) { : local_ids(local_ids) {
assert(query_db); // TODO: remove after testing.
index_file_id = GetQueryFileIdFromUsr(query_db, local_ids.primary_file); index_file_id = GetQueryFileIdFromUsr(query_db, local_ids.primary_file);
cached_type_ids_.reserve(local_ids.type_id_to_usr.size()); cached_type_ids_.reserve(local_ids.type_id_to_usr.size());
@ -489,19 +487,16 @@ IdMap::IdMap(QueryableDatabase* query_db, const IdCache& local_ids)
// static // static
IndexUpdate IndexUpdate::CreateImport(const IdMap& id_map, IndexedFile& file) { IndexUpdate IndexUpdate::CreateDelta(const IdMap* previous_id_map, const IdMap* current_id_map, IndexedFile* previous, IndexedFile* current) {
// Return standard diff constructor but with an empty file so everything is if (!previous_id_map) {
// added. assert(!previous);
IndexedFile previous(file.path); IndexedFile previous(current->path);
return IndexUpdate(id_map, id_map, previous, file); return IndexUpdate(*current_id_map, *current_id_map, previous, *current);
}
return IndexUpdate(*previous_id_map, *current_id_map, *previous, *current);
} }
// static IndexUpdate::IndexUpdate(const IdMap& previous_id_map, const IdMap& current_id_map, IndexedFile& previous_file, IndexedFile& current_file) {
IndexUpdate IndexUpdate::CreateDelta(const IdMap& current_id_map, const IdMap& previous_id_map, IndexedFile& current, IndexedFile& updated) {
return IndexUpdate(current_id_map, previous_id_map, current, updated);
}
IndexUpdate::IndexUpdate(const IdMap& current_id_map, const IdMap& previous_id_map, IndexedFile& previous_file, IndexedFile& current_file) {
// |query_name| is the name of the variable on the query type. // |query_name| is the name of the variable on the query type.
// |index_name| is the name of the variable on the index type. // |index_name| is the name of the variable on the index type.
// |type| is the type of the variable. // |type| is the type of the variable.
@ -638,7 +633,16 @@ void IndexUpdate::Merge(const IndexUpdate& update) {
void UpdateQualifiedName(QueryableDatabase* db, int* qualified_name_index, SymbolKind kind, int symbol_index, const std::string& name) {
if (*qualified_name_index == -1) {
db->qualified_names.push_back(name);
db->symbols.push_back(SymbolIdx(kind, symbol_index));
*qualified_name_index = db->qualified_names.size() - 1;
}
else {
db->qualified_names[*qualified_name_index] = name;
}
}
@ -654,67 +658,53 @@ void QueryableDatabase::RemoveUsrs(const std::vector<Usr>& to_remove) {
void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableFile::DefUpdate>& updates) { void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableFile::DefUpdate>& updates) {
for (auto& def : updates) { for (auto& def : updates) {
auto it = usr_to_symbol.find(def.usr); auto it = usr_to_symbol.find(def.usr);
if (it == usr_to_symbol.end()) { assert(it != usr_to_symbol.end());
qualified_names.push_back(def.usr);
symbols.push_back(SymbolIdx(SymbolKind::File, files.size()));
usr_to_symbol[def.usr] = SymbolIdx(SymbolKind::File, files.size());
files.push_back(QueryableFile(def));
}
else {
QueryableFile& existing = files[it->second.idx]; QueryableFile& existing = files[it->second.idx];
existing.def = def; existing.def = def;
} UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::File, it->second.idx, def.usr);
} }
} }
void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableTypeDef::DefUpdate>& updates) { void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableTypeDef::DefUpdate>& updates) {
for (auto& def : updates) { for (auto& def : updates) {
if (!def.definition_extent)
continue;
auto it = usr_to_symbol.find(def.usr); auto it = usr_to_symbol.find(def.usr);
if (it == usr_to_symbol.end()) { assert(it != usr_to_symbol.end());
qualified_names.push_back(def.qualified_name);
symbols.push_back(SymbolIdx(SymbolKind::Type, types.size()));
usr_to_symbol[def.usr] = SymbolIdx(SymbolKind::Type, types.size());
types.push_back(QueryableTypeDef(def));
}
else {
QueryableTypeDef& existing = types[it->second.idx]; QueryableTypeDef& existing = types[it->second.idx];
if (def.definition_extent)
existing.def = def; existing.def = def;
} UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::Type, it->second.idx, def.usr);
} }
} }
void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableFuncDef::DefUpdate>& updates) { void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableFuncDef::DefUpdate>& updates) {
for (auto& def : updates) { for (auto& def : updates) {
if (!def.definition_extent)
continue;
auto it = usr_to_symbol.find(def.usr); auto it = usr_to_symbol.find(def.usr);
if (it == usr_to_symbol.end()) { assert(it != usr_to_symbol.end());
qualified_names.push_back(def.qualified_name);
symbols.push_back(SymbolIdx(SymbolKind::Func, funcs.size()));
usr_to_symbol[def.usr] = SymbolIdx(SymbolKind::Func, funcs.size());
funcs.push_back(QueryableFuncDef(def));
}
else {
QueryableFuncDef& existing = funcs[it->second.idx]; QueryableFuncDef& existing = funcs[it->second.idx];
if (def.definition_extent)
existing.def = def; existing.def = def;
} UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::Func, it->second.idx, def.usr);
} }
} }
void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableVarDef::DefUpdate>& updates) { void QueryableDatabase::ImportOrUpdate(const std::vector<QueryableVarDef::DefUpdate>& updates) {
for (auto& def : updates) { for (auto& def : updates) {
if (!def.definition_extent)
continue;
auto it = usr_to_symbol.find(def.usr); auto it = usr_to_symbol.find(def.usr);
if (it == usr_to_symbol.end()) { assert(it != usr_to_symbol.end());
qualified_names.push_back(def.qualified_name);
symbols.push_back(SymbolIdx(SymbolKind::Var, vars.size()));
usr_to_symbol[def.usr] = SymbolIdx(SymbolKind::Var, vars.size());
vars.push_back(QueryableVarDef(def));
}
else {
QueryableVarDef& existing = vars[it->second.idx]; QueryableVarDef& existing = vars[it->second.idx];
if (def.definition_extent)
existing.def = def; existing.def = def;
} UpdateQualifiedName(this, &existing.qualified_name_idx, SymbolKind::Var, it->second.idx, def.usr);
} }
} }

View File

@ -118,6 +118,7 @@ struct QueryableFile {
using DefUpdate = Def; using DefUpdate = Def;
DefUpdate def; DefUpdate def;
int qualified_name_idx = -1;
QueryableFile(const Usr& usr) { def.usr = usr; } QueryableFile(const Usr& usr) { def.usr = usr; }
QueryableFile(const Def& def) : def(def) {} QueryableFile(const Def& def) : def(def) {}
@ -134,6 +135,7 @@ struct QueryableTypeDef {
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<Usr> instantiations; std::vector<Usr> instantiations;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
int qualified_name_idx = -1;
QueryableTypeDef(const Usr& usr) : def(usr) {} QueryableTypeDef(const Usr& usr) : def(usr) {}
QueryableTypeDef(const DefUpdate& def) : def(def) {} QueryableTypeDef(const DefUpdate& def) : def(def) {}
@ -152,6 +154,7 @@ struct QueryableFuncDef {
std::vector<Usr> derived; std::vector<Usr> derived;
std::vector<UsrRef> callers; std::vector<UsrRef> callers;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
int qualified_name_idx = -1;
QueryableFuncDef(const Usr& usr) : def(usr) {} QueryableFuncDef(const Usr& usr) : def(usr) {}
QueryableFuncDef(const DefUpdate& def) : def(def) {} QueryableFuncDef(const DefUpdate& def) : def(def) {}
@ -164,6 +167,7 @@ struct QueryableVarDef {
DefUpdate def; DefUpdate def;
std::vector<QueryableLocation> uses; std::vector<QueryableLocation> uses;
int qualified_name_idx = -1;
QueryableVarDef(const Usr& usr) : def(usr) {} QueryableVarDef(const Usr& usr) : def(usr) {}
QueryableVarDef(const DefUpdate& def) : def(def) {} QueryableVarDef(const DefUpdate& def) : def(def) {}
@ -181,9 +185,9 @@ struct SymbolIdx {
struct IndexUpdate { struct IndexUpdate {
// Creates a new IndexUpdate that will import |file|. // Creates a new IndexUpdate based on the delta from previous to current. If
static IndexUpdate CreateImport(const IdMap& id_map, IndexedFile& file); // no delta computation should be done just pass null for previous.
static IndexUpdate CreateDelta(const IdMap& current_id_map, const IdMap& previous_id_map, IndexedFile& current, IndexedFile& updated); static IndexUpdate CreateDelta(const IdMap* previous_id_map, const IdMap* current_id_map, IndexedFile* previous, IndexedFile* current);
// Merge |update| into this update; this can reduce overhead / index update // Merge |update| into this update; this can reduce overhead / index update
// work can be parallelized. // work can be parallelized.
@ -217,7 +221,7 @@ struct IndexUpdate {
// Creates an index update assuming that |previous| is already // Creates an index update assuming that |previous| is already
// in the index, so only the delta between |previous| and |current| // in the index, so only the delta between |previous| and |current|
// will be applied. // will be applied.
IndexUpdate(const IdMap& current_id_map, const IdMap& previous_id_map, IndexedFile& previous, IndexedFile& current); IndexUpdate(const IdMap& previous_id_map, const IdMap& current_id_map, IndexedFile& previous, IndexedFile& current);
}; };

View File

@ -15,9 +15,9 @@ template <class T>
class ThreadedQueue { class ThreadedQueue {
public: public:
// Add an element to the queue. // Add an element to the queue.
void Enqueue(T t) { void Enqueue(T&& t) {
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
queue_.push(t); queue_.push(std::move(t));
cv_.notify_one(); cv_.notify_one();
} }
@ -29,7 +29,8 @@ public:
// release lock as long as the wait and reaquire it afterwards. // release lock as long as the wait and reaquire it afterwards.
cv_.wait(lock); cv_.wait(lock);
} }
T val = queue_.front();
auto val = std::move(queue_.front());
queue_.pop(); queue_.pop();
return val; return val;
} }
@ -41,7 +42,7 @@ public:
if (queue_.empty()) if (queue_.empty())
return nullopt; return nullopt;
T val = queue_.front(); auto val = std::move(queue_.front());
queue_.pop(); queue_.pop();
return val; return val;
} }