mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 03:25:54 -04:00

to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
100 lines
3.4 KiB
C++
100 lines
3.4 KiB
C++
//===--- Cancellation.h -------------------------------------------*-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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// Cancellation mechanism for long-running tasks.
|
|
//
|
|
// This manages interactions between:
|
|
//
|
|
// 1. Client code that starts some long-running work, and maybe cancels later.
|
|
//
|
|
// std::pair<Context, Canceler> Task = cancelableTask();
|
|
// {
|
|
// WithContext Cancelable(std::move(Task.first));
|
|
// Expected
|
|
// deepThoughtAsync([](int answer){ errs() << answer; });
|
|
// }
|
|
// // ...some time later...
|
|
// if (User.fellAsleep())
|
|
// Task.second();
|
|
//
|
|
// (This example has an asynchronous computation, but synchronous examples
|
|
// work similarly - the Canceler should be invoked from another thread).
|
|
//
|
|
// 2. Library code that executes long-running work, and can exit early if the
|
|
// result is not needed.
|
|
//
|
|
// void deepThoughtAsync(std::function<void(int)> Callback) {
|
|
// runAsync([Callback]{
|
|
// int A = ponder(6);
|
|
// if (isCancelled())
|
|
// return;
|
|
// int B = ponder(9);
|
|
// if (isCancelled())
|
|
// return;
|
|
// Callback(A * B);
|
|
// });
|
|
// }
|
|
//
|
|
// (A real example may invoke the callback with an error on cancellation,
|
|
// the CancelledError is provided for this purpose).
|
|
//
|
|
// Cancellation has some caveats:
|
|
// - the work will only stop when/if the library code next checks for it.
|
|
// Code outside clangd such as Sema will not do this.
|
|
// - it's inherently racy: client code must be prepared to accept results
|
|
// even after requesting cancellation.
|
|
// - it's Context-based, so async work must be dispatched to threads in
|
|
// ways that preserve the context. (Like runAsync() or TUScheduler).
|
|
//
|
|
// FIXME: We could add timestamps to isCancelled() and CancelledError.
|
|
// Measuring the start -> cancel -> acknowledge -> finish timeline would
|
|
// help find where libraries' cancellation should be improved.
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CANCELLATION_H
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CANCELLATION_H
|
|
|
|
#include "Context.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include <functional>
|
|
#include <system_error>
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
|
|
/// A canceller requests cancellation of a task, when called.
|
|
/// Calling it again has no effect.
|
|
using Canceler = std::function<void()>;
|
|
|
|
/// Defines a new task whose cancellation may be requested.
|
|
/// The returned Context defines the scope of the task.
|
|
/// When the context is active, isCancelled() is false until the Canceler is
|
|
/// invoked, and true afterwards.
|
|
std::pair<Context, Canceler> cancelableTask();
|
|
|
|
/// True if the current context is within a cancelable task which was cancelled.
|
|
/// Always false if there is no active cancelable task.
|
|
/// This isn't free (context lookup) - don't call it in a tight loop.
|
|
bool isCancelled(const Context &Ctx = Context::current());
|
|
|
|
/// Conventional error when no result is returned due to cancellation.
|
|
class CancelledError : public llvm::ErrorInfo<CancelledError> {
|
|
public:
|
|
static char ID;
|
|
|
|
void log(llvm::raw_ostream &OS) const override {
|
|
OS << "Task was cancelled.";
|
|
}
|
|
std::error_code convertToErrorCode() const override {
|
|
return std::make_error_code(std::errc::operation_canceled);
|
|
}
|
|
};
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|
|
|
|
#endif
|