reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
//===--- BackgroundIndexRebuild.h - when to rebuild the bg index--*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains an implementation detail of the background indexer
// (Background.h), which is exposed for testing.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_REBUILD_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_REBUILD_H

#include "index/FileIndex.h"
#include "index/Index.h"
#include "llvm/Support/Threading.h"
#include <cstddef>

namespace clang {
namespace clangd {

// The BackgroundIndexRebuilder builds the serving data structures periodically
// in response to events in the background indexer. The goal is to ensure the
// served data stays fairly fresh, without wasting lots of CPU rebuilding it
// often.
//
// The index is always built after a set of shards are loaded from disk.
// This happens when clangd discovers a compilation database that we've
// previously built an index for. It's a fairly fast process that yields lots
// of data, so we wait to get all of it.
//
// The index is built after indexing a few translation units, if it wasn't built
// already. This ensures quick startup if there's no existing index.
// Waiting for a few random TUs yields coverage of the most common headers.
//
// The index is rebuilt every N TUs, to keep if fresh as files are indexed.
//
// The index is rebuilt every time the queue goes idle, if it's stale.
//
// All methods are threadsafe. They're called after FileSymbols is updated
// etc. Without external locking, the rebuilt index may include more updates
// than intended, which is fine.
//
// This class is exposed in the header so it can be tested.
class BackgroundIndexRebuilder {
public:
  BackgroundIndexRebuilder(SwapIndex *Target, FileSymbols *Source,
                           unsigned Threads)
      : TUsBeforeFirstBuild(Threads), Target(Target), Source(Source) {}

  // Called to indicate a TU has been indexed.
  // May rebuild, if enough TUs have been indexed.
  void indexedTU();
  // Called to indicate that all worker threads are idle.
  // May reindex, if the index is not up to date.
  void idle();
  // Called to indicate we're going to load a batch of shards from disk.
  // startLoading() and doneLoading() must be paired, but multiple loading
  // sessions may happen concurrently.
  void startLoading();
  // Called to indicate some shards were actually loaded from disk.
  void loadedShard(size_t ShardCount);
  // Called to indicate we're finished loading shards from disk.
  // May rebuild (if any were loaded).
  void doneLoading();

  // Ensures we won't start any more rebuilds.
  void shutdown();

  // Thresholds for rebuilding as TUs get indexed.
  const unsigned TUsBeforeFirstBuild; // Typically one per worker thread.
  const unsigned TUsBeforeRebuild = 100;

private:
  // Run Check under the lock, and rebuild if it returns true.
  void maybeRebuild(const char *Reason, std::function<bool()> Check);
  bool enoughTUsToRebuild() const;

  // All transient state is guarded by the mutex.
  std::mutex Mu;
  bool ShouldStop = false;
  // Index builds are versioned. ActiveVersion chases StartedVersion.
  unsigned StartedVersion = 0;
  unsigned ActiveVersion = 0;
  // How many TUs have we indexed so far since startup?
  unsigned IndexedTUs = 0;
  unsigned IndexedTUsAtLastRebuild = 0;
  // Are we loading shards? May be multiple concurrent sessions.
  unsigned Loading = 0;
  unsigned LoadedShards; // In the current loading session.

  SwapIndex *Target;
  FileSymbols *Source;
};

} // namespace clangd
} // namespace clang

#endif