forked from GPUOpen-Drivers/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged master:ecabb39ca11c into amd-gfx:823ae141034e
Local branch amd-gfx 823ae14 Merged master:0cb38699a09d into amd-gfx:534cfb420e64 Remote branch master ecabb39 Revert "[libc++] P1645 constexpr for <numeric>"
- Loading branch information
Showing
41 changed files
with
551 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
//===--- FileCache.cpp ----------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "support/FileCache.h" | ||
|
||
namespace clang { | ||
namespace clangd { | ||
|
||
// Sentinel values for the Size cache key. In both cases, a successful stat of | ||
// the file will never result in the cached value being reused. | ||
|
||
// The cached value does not reflect the current content on disk. | ||
static constexpr uint64_t CacheDiskMismatch = | ||
std::numeric_limits<uint64_t>::max(); | ||
// The cached value reflects that the file doesn't exist. | ||
static constexpr uint64_t FileNotFound = CacheDiskMismatch - 1; | ||
|
||
FileCache::FileCache(llvm::StringRef Path) | ||
: Path(Path), ValidTime(std::chrono::steady_clock::time_point::min()), | ||
ModifiedTime(), Size(CacheDiskMismatch) { | ||
assert(llvm::sys::path::is_absolute(Path)); | ||
} | ||
|
||
void FileCache::read( | ||
const ThreadsafeFS &TFS, std::chrono::steady_clock::time_point FreshTime, | ||
llvm::function_ref<void(llvm::Optional<llvm::StringRef>)> Parse, | ||
llvm::function_ref<void()> Read) const { | ||
|
||
std::lock_guard<std::mutex> Lock(Mu); | ||
// We're going to update the cache and return whatever's in it. | ||
auto Return = llvm::make_scope_exit(Read); | ||
|
||
// Return any sufficiently recent result without doing any further work. | ||
if (ValidTime > FreshTime) | ||
return; | ||
|
||
// Ensure we always bump ValidTime, so that FreshTime imposes a hard limit on | ||
// how often we do IO. | ||
auto BumpValidTime = llvm::make_scope_exit( | ||
[&] { ValidTime = std::chrono::steady_clock::now(); }); | ||
|
||
// stat is cheaper than opening the file. It's usually unchanged. | ||
assert(llvm::sys::path::is_absolute(Path)); | ||
auto FS = TFS.view(/*CWD=*/llvm::None); | ||
auto Stat = FS->status(Path); | ||
if (!Stat || !Stat->isRegularFile()) { | ||
if (Size != FileNotFound) // Allow "not found" value to be cached. | ||
Parse(llvm::None); | ||
// Ensure the cache key won't match any future stat(). | ||
Size = FileNotFound; | ||
return; | ||
} | ||
// If the modified-time and size match, assume the content does too. | ||
if (Size == Stat->getSize() && | ||
ModifiedTime == Stat->getLastModificationTime()) | ||
return; | ||
|
||
// OK, the file has actually changed. Update cache key, compute new value. | ||
Size = Stat->getSize(); | ||
ModifiedTime = Stat->getLastModificationTime(); | ||
// Now read the file from disk. | ||
if (auto Buf = FS->getBufferForFile(Path)) { | ||
Parse(Buf->get()->getBuffer()); | ||
// Result is cacheable if the actual read size matches the new cache key. | ||
// (We can't update the cache key, because we don't know the new mtime). | ||
if (Buf->get()->getBufferSize() != Size) | ||
Size = CacheDiskMismatch; | ||
} else { | ||
// File was unreadable. Keep the old value and try again next time. | ||
Size = CacheDiskMismatch; | ||
} | ||
} | ||
|
||
} // namespace clangd | ||
} // namespace clang |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
//===--- FileCache.h - Revalidating cache of data from disk ------*- 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FILECACHE_H | ||
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FILECACHE_H | ||
|
||
#include "Path.h" | ||
#include "ThreadsafeFS.h" | ||
#include "llvm/ADT/ScopeExit.h" | ||
#include "llvm/Support/Chrono.h" | ||
#include "llvm/Support/VirtualFileSystem.h" | ||
#include <mutex> | ||
|
||
namespace clang { | ||
namespace clangd { | ||
|
||
/// Base class for threadsafe cache of data read from a file on disk. | ||
/// | ||
/// We want configuration files to be "live" as much as possible. | ||
/// Reading them every time is simplest, but caching solves a few problems: | ||
/// - reading and parsing is cheap but not free (and happens on hot paths) | ||
/// - we can ignore invalid data and use the old value (we may see truncated | ||
/// compile_commands.json from non-atomic writers) | ||
/// - we avoid reporting the same errors repeatedly | ||
/// | ||
/// We still read and parse the data synchronously on demand, but skip as much | ||
/// work as possible: | ||
/// - if not enough wall-time has elapsed, assume the data is still up-to-date | ||
/// - if we stat the file and it has the same mtime + size, don't read it | ||
/// - obviously we only have to parse when we re-read the file | ||
/// (Tracking OS change events is an alternative, but difficult to do portably.) | ||
/// | ||
/// Caches for particular data (e.g. compilation databases) should inherit and: | ||
/// - add mutable storage for the cached parsed data | ||
/// - add a public interface implemented on top of read() | ||
class FileCache { | ||
protected: | ||
// Path must be absolute. | ||
FileCache(PathRef Path); | ||
|
||
// Updates the cached value if needed, then provides threadsafe access to it. | ||
// | ||
// Specifically: | ||
// - Parse() may be called (if the cache was not up-to-date) | ||
// The lock is held, so cache storage may be safely written. | ||
// Parse(None) means the file doesn't exist. | ||
// - Read() will always be called, to provide access to the value. | ||
// The lock is again held, so the value can be copied or used. | ||
// | ||
// If the last Parse is newer than FreshTime, we don't check metadata. | ||
// - time_point::min() means we only do IO if we never read the file before | ||
// - time_point::max() means we always at least stat the file | ||
// - steady_clock::now() + seconds(1) means we accept 1 second of staleness | ||
void read(const ThreadsafeFS &TFS, | ||
std::chrono::steady_clock::time_point FreshTime, | ||
llvm::function_ref<void(llvm::Optional<llvm::StringRef>)> Parse, | ||
llvm::function_ref<void()> Read) const; | ||
|
||
PathRef path() const { return Path; } | ||
|
||
private: | ||
std::string Path; | ||
// Members are mutable so read() can present a const interface. | ||
// (It is threadsafe and approximates read-through to TFS). | ||
mutable std::mutex Mu; | ||
// Time when the cache was known valid (reflected disk state). | ||
mutable std::chrono::steady_clock::time_point ValidTime; | ||
// Filesystem metadata corresponding to the currently cached data. | ||
mutable llvm::sys::TimePoint<> ModifiedTime; | ||
mutable uint64_t Size; | ||
}; | ||
|
||
} // namespace clangd | ||
} // namespace clang | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.