diff --git a/src/config.h b/src/config.h index 034012dd..72295eb5 100644 --- a/src/config.h +++ b/src/config.h @@ -210,13 +210,13 @@ struct Config { // May be too slow for big projects, so it is off by default. bool onChange = false; + // Number of indexer threads. If 0, 80% of cores are used. + int threads = 0; + // Whether to reparse a file if write times of its dependencies have // changed. The file will always be reparsed if its own write time changes. // 0: no, 1: only after initial load of project, 2: yes - int reparseForDependency = 2; - - // Number of indexer threads. If 0, 80% of cores are used. - int threads = 0; + int trackDependency = 2; std::vector whitelist; } index; @@ -256,7 +256,7 @@ MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, enabled, initialBlacklist, initialWhitelist, multiVersion, multiVersionBlacklist, multiVersionWhitelist, onChange, - reparseForDependency, threads, whitelist); + threads, trackDependency, whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, diff --git a/src/pipeline.cc b/src/pipeline.cc index f811d840..b7b44166 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -50,7 +50,8 @@ bool VFS::Stamp(const std::string &path, int64_t ts, int step) { namespace ccls::pipeline { -int64_t loaded_ts = 0, tick = 0; +std::atomic loaded_ts = ATOMIC_VAR_INIT(0); +int64_t tick = 0; namespace { @@ -187,7 +188,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (!mtime1) return true; if (vfs->Stamp(request.path, *mtime1, 0)) - reparse = 1; + reparse = 2; } if (g_config->index.onChange) { reparse = 2; @@ -196,45 +197,55 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, if (request.path != path_to_index) vfs->state[request.path].step = 0; } - if (!reparse) + bool track = g_config->index.trackDependency > 1 || + (g_config->index.trackDependency == 1 && request.ts < loaded_ts); + if (!reparse && !track) return true; - if (reparse < 2) do { - std::unique_lock lock( + if (reparse < 2) + do { + std::unique_lock lock( mutexes[std::hash()(path_to_index) % N_MUTEXES]); - prev = RawCacheLoad(path_to_index); - if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, - std::nullopt)) - break; - bool update = false; - for (const auto &dep : prev->dependencies) - if (auto mtime1 = LastWriteTime(dep.first.val().str())) { - if (dep.second < *mtime1) - update = true; - } else { - update = true; - } - int forDep = g_config->index.reparseForDependency; - if (update && (forDep > 1 || (forDep == 1 && request.ts < loaded_ts))) - break; + prev = RawCacheLoad(path_to_index); + if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, + std::nullopt)) + break; + if (track) + for (const auto &dep : prev->dependencies) { + if (auto mtime1 = LastWriteTime(dep.first.val().str())) { + if (dep.second < *mtime1) { + reparse = 2; + break; + } + } else { + reparse = 2; + break; + } + } + if (reparse == 0) + return true; + if (reparse == 2) + break; - if (reparse < 2) { + if (vfs->Loaded(path_to_index)) + return true; LOG_S(INFO) << "load cache for " << path_to_index; auto dependencies = prev->dependencies; - if (reparse) { - if (vfs->Loaded(path_to_index)) - return true; - IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); + { std::lock_guard lock1(vfs->mutex); vfs->state[path_to_index].loaded = true; } lock.unlock(); + for (const auto &dep : dependencies) { std::string path = dep.first.val().str(); + if (!vfs->Stamp(path, dep.second, 1)) + continue; std::lock_guard lock1( - mutexes[std::hash()(path) % N_MUTEXES]); + mutexes[std::hash()(path) % N_MUTEXES]); prev = RawCacheLoad(path); if (!prev) continue; @@ -248,15 +259,14 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, } IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); on_indexed->PushBack(std::move(update), - request.mode != IndexMode::NonInteractive); + request.mode != IndexMode::NonInteractive); if (entry.id >= 0) { std::lock_guard lock2(project->mutex_); project->path_to_entry_index[path] = entry.id; } } return true; - } - } while (0); + } while (0); LOG_IF_S(INFO, loud) << "parse " << path_to_index; diff --git a/src/pipeline.hh b/src/pipeline.hh index ed00dda8..ee32482f 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -7,6 +7,7 @@ #include "method.h" #include "query.h" +#include #include #include #include @@ -41,7 +42,8 @@ enum class IndexMode { }; namespace pipeline { -extern int64_t loaded_ts, tick; +extern std::atomic loaded_ts; +extern int64_t tick; void Init(); void LaunchStdin(); void LaunchStdout();