Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clangd/support/Cancellation.h @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang-tools-extra/clangd/support/Cancellation.h Mon May 25 11:55:54 2020 +0900 @@ -0,0 +1,104 @@ +//===--- 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_SUPPORT_CANCELLATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_CANCELLATION_H + +#include "support/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 0 until the Canceler is +/// invoked, and equal to Reason afterwards. +/// Conventionally, Reason may be the LSP error code to return. +std::pair<Context, Canceler> cancelableTask(int Reason = 1); + +/// If the current context is within a cancelled task, returns the reason. +/// (If the context is within multiple nested tasks, true if any are cancelled). +/// Always zero if there is no active cancelable task. +/// This isn't free (context lookup) - don't call it in a tight loop. +int 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; + const int Reason; + + CancelledError(int Reason) : Reason(Reason) {} + + 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