Mercurial > hg > CbC > CbC_llvm
comparison clang-tools-extra/clangd/support/Function.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 | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
172:9fbae9c8bf63 | 173:0572611fdcc8 |
---|---|
1 //===--- Function.h - Utility callable wrappers -----------------*- 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 // This file provides utilities for callable objects. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 | |
13 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FUNCTION_H | |
14 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_FUNCTION_H | |
15 | |
16 #include "llvm/ADT/FunctionExtras.h" | |
17 #include "llvm/Support/Error.h" | |
18 #include <mutex> | |
19 #include <tuple> | |
20 #include <utility> | |
21 | |
22 namespace clang { | |
23 namespace clangd { | |
24 | |
25 /// A Callback<T> is a void function that accepts Expected<T>. | |
26 /// This is accepted by ClangdServer functions that logically return T. | |
27 template <typename T> | |
28 using Callback = llvm::unique_function<void(llvm::Expected<T>)>; | |
29 | |
30 /// An Event<T> allows events of type T to be broadcast to listeners. | |
31 template <typename T> class Event { | |
32 public: | |
33 // A Listener is the callback through which events are delivered. | |
34 using Listener = std::function<void(const T &)>; | |
35 | |
36 // A subscription defines the scope of when a listener should receive events. | |
37 // After destroying the subscription, no more events are received. | |
38 class LLVM_NODISCARD Subscription { | |
39 Event *Parent; | |
40 unsigned ListenerID; | |
41 | |
42 Subscription(Event *Parent, unsigned ListenerID) | |
43 : Parent(Parent), ListenerID(ListenerID) {} | |
44 friend Event; | |
45 | |
46 public: | |
47 Subscription() : Parent(nullptr) {} | |
48 Subscription(Subscription &&Other) : Parent(nullptr) { | |
49 *this = std::move(Other); | |
50 } | |
51 Subscription &operator=(Subscription &&Other) { | |
52 // If *this is active, unsubscribe. | |
53 if (Parent) { | |
54 std::lock_guard<std::recursive_mutex>(Parent->ListenersMu); | |
55 llvm::erase_if(Parent->Listeners, | |
56 [&](const std::pair<Listener, unsigned> &P) { | |
57 return P.second == ListenerID; | |
58 }); | |
59 } | |
60 // Take over the other subscription, and mark it inactive. | |
61 std::tie(Parent, ListenerID) = std::tie(Other.Parent, Other.ListenerID); | |
62 Other.Parent = nullptr; | |
63 return *this; | |
64 } | |
65 // Destroying a subscription may block if an event is being broadcast. | |
66 ~Subscription() { | |
67 if (Parent) | |
68 *this = Subscription(); // Unsubscribe. | |
69 } | |
70 }; | |
71 | |
72 // Adds a listener that will observe all future events until the returned | |
73 // subscription is destroyed. | |
74 // May block if an event is currently being broadcast. | |
75 Subscription observe(Listener L) { | |
76 std::lock_guard<std::recursive_mutex> Lock(ListenersMu); | |
77 Listeners.push_back({std::move(L), ++ListenerCount}); | |
78 return Subscription(this, ListenerCount); | |
79 } | |
80 | |
81 // Synchronously sends an event to all registered listeners. | |
82 // Must not be called from a listener to this event. | |
83 void broadcast(const T &V) { | |
84 // FIXME: it would be nice to dynamically check non-reentrancy here. | |
85 std::lock_guard<std::recursive_mutex> Lock(ListenersMu); | |
86 for (const auto &L : Listeners) | |
87 L.first(V); | |
88 } | |
89 | |
90 ~Event() { | |
91 std::lock_guard<std::recursive_mutex> Lock(ListenersMu); | |
92 assert(Listeners.empty()); | |
93 } | |
94 | |
95 private: | |
96 static_assert(std::is_same<typename std::decay<T>::type, T>::value, | |
97 "use a plain type: event values are always passed by const&"); | |
98 | |
99 std::recursive_mutex ListenersMu; | |
100 bool IsBroadcasting = false; | |
101 std::vector<std::pair<Listener, unsigned>> Listeners; | |
102 unsigned ListenerCount = 0; | |
103 }; | |
104 | |
105 } // namespace clangd | |
106 } // namespace clang | |
107 | |
108 #endif |