xref: /llvm-project/clang-tools-extra/clangd/support/Cancellation.cpp (revision ad97ccf6b26a29262c9cbf5b3e7f6e84c6dcf55f)
1*ad97ccf6SSam McCall //===--- Cancellation.cpp -----------------------------------------*-C++-*-===//
2*ad97ccf6SSam McCall //
3*ad97ccf6SSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*ad97ccf6SSam McCall // See https://llvm.org/LICENSE.txt for license information.
5*ad97ccf6SSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*ad97ccf6SSam McCall //
7*ad97ccf6SSam McCall //===----------------------------------------------------------------------===//
8*ad97ccf6SSam McCall 
9*ad97ccf6SSam McCall #include "support/Cancellation.h"
10*ad97ccf6SSam McCall #include <atomic>
11*ad97ccf6SSam McCall 
12*ad97ccf6SSam McCall namespace clang {
13*ad97ccf6SSam McCall namespace clangd {
14*ad97ccf6SSam McCall 
15*ad97ccf6SSam McCall char CancelledError::ID = 0;
16*ad97ccf6SSam McCall 
17*ad97ccf6SSam McCall // We don't want a cancelable scope to "shadow" an enclosing one.
18*ad97ccf6SSam McCall struct CancelState {
19*ad97ccf6SSam McCall   std::shared_ptr<std::atomic<int>> Cancelled;
20*ad97ccf6SSam McCall   const CancelState *Parent;
21*ad97ccf6SSam McCall };
22*ad97ccf6SSam McCall static Key<CancelState> StateKey;
23*ad97ccf6SSam McCall 
cancelableTask(int Reason)24*ad97ccf6SSam McCall std::pair<Context, Canceler> cancelableTask(int Reason) {
25*ad97ccf6SSam McCall   assert(Reason != 0 && "Can't detect cancellation if Reason is zero");
26*ad97ccf6SSam McCall   CancelState State;
27*ad97ccf6SSam McCall   State.Cancelled = std::make_shared<std::atomic<int>>();
28*ad97ccf6SSam McCall   State.Parent = Context::current().get(StateKey);
29*ad97ccf6SSam McCall   return {
30*ad97ccf6SSam McCall       Context::current().derive(StateKey, State),
31*ad97ccf6SSam McCall       [Reason, Flag(State.Cancelled)] { *Flag = Reason; },
32*ad97ccf6SSam McCall   };
33*ad97ccf6SSam McCall }
34*ad97ccf6SSam McCall 
isCancelled(const Context & Ctx)35*ad97ccf6SSam McCall int isCancelled(const Context &Ctx) {
36*ad97ccf6SSam McCall   for (const CancelState *State = Ctx.get(StateKey); State != nullptr;
37*ad97ccf6SSam McCall        State = State->Parent)
38*ad97ccf6SSam McCall     if (int Reason = State->Cancelled->load())
39*ad97ccf6SSam McCall       return Reason;
40*ad97ccf6SSam McCall   return 0;
41*ad97ccf6SSam McCall }
42*ad97ccf6SSam McCall 
43*ad97ccf6SSam McCall } // namespace clangd
44*ad97ccf6SSam McCall } // namespace clang
45