clang-tools  10.0.0svn
Function.h
Go to the documentation of this file.
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_FUNCTION_H
14 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_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  }
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.
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
std::function< void(const std::vector< std::string > &)> Listener
Definition: Function.h:34
const Node * Parent
Subscription(Subscription &&Other)
Definition: Function.h:48
An Event<T> allows events of type T to be broadcast to listeners.
Definition: Function.h:31
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
Definition: Function.h:28
Subscription & operator=(Subscription &&Other)
Definition: Function.h:51
void broadcast(const T &V)
Definition: Function.h:83
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Subscription observe(Listener L)
Definition: Function.h:75