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