//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_SERIALIZATION_MODULECACHE_H
#define LLVM_CLANG_SERIALIZATION_MODULECACHE_H

#include "clang/Basic/LLVM.h"

#include <ctime>

namespace llvm {
class AdvisoryLock;
} // namespace llvm

namespace clang {
class InMemoryModuleCache;

/// The module cache used for compiling modules implicitly. This centralizes the
/// operations the compiler might want to perform on the cache.
class ModuleCache {
public:
  /// May perform any work that only needs to be performed once for multiple
  /// calls \c getLock() with the same module filename.
  virtual void prepareForGetLock(StringRef ModuleFilename) = 0;

  /// Returns lock for the given module file. The lock is initially unlocked.
  virtual std::unique_ptr<llvm::AdvisoryLock>
  getLock(StringRef ModuleFilename) = 0;

  // TODO: Abstract away timestamps with isUpToDate() and markUpToDate().
  // TODO: Consider exposing a "validation lock" API to prevent multiple clients
  // concurrently noticing an out-of-date module file and validating its inputs.

  /// Returns the timestamp denoting the last time inputs of the module file
  /// were validated.
  virtual std::time_t getModuleTimestamp(StringRef ModuleFilename) = 0;

  /// Updates the timestamp denoting the last time inputs of the module file
  /// were validated.
  virtual void updateModuleTimestamp(StringRef ModuleFilename) = 0;

  /// Prune module files that haven't been accessed in a long time.
  virtual void maybePrune(StringRef Path, time_t PruneInterval,
                          time_t PruneAfter) = 0;

  /// Returns this process's view of the module cache.
  virtual InMemoryModuleCache &getInMemoryModuleCache() = 0;
  virtual const InMemoryModuleCache &getInMemoryModuleCache() const = 0;

  // TODO: Virtualize writing/reading PCM files, etc.

  virtual ~ModuleCache() = default;
};

/// Creates new \c ModuleCache backed by a file system directory that may be
/// operated on by multiple processes. This instance must be used across all
/// \c CompilerInstance instances participating in building modules for single
/// translation unit in order to share the same \c InMemoryModuleCache.
std::shared_ptr<ModuleCache> createCrossProcessModuleCache();

/// Shared implementation of `ModuleCache::maybePrune()`.
void maybePruneImpl(StringRef Path, time_t PruneInterval, time_t PruneAfter);
} // namespace clang

#endif
