Apollo  6.0
Open source self driving car software
signal.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2018 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 #ifndef CYBER_BASE_SIGNAL_H_
18 #define CYBER_BASE_SIGNAL_H_
19 
20 #include <algorithm>
21 #include <functional>
22 #include <list>
23 #include <memory>
24 #include <mutex>
25 
26 namespace apollo {
27 namespace cyber {
28 namespace base {
29 
30 template <typename... Args>
31 class Slot;
32 
33 template <typename... Args>
34 class Connection;
35 
36 template <typename... Args>
37 class Signal {
38  public:
39  using Callback = std::function<void(Args...)>;
40  using SlotPtr = std::shared_ptr<Slot<Args...>>;
41  using SlotList = std::list<SlotPtr>;
42  using ConnectionType = Connection<Args...>;
43 
44  Signal() {}
45  virtual ~Signal() { DisconnectAllSlots(); }
46 
47  void operator()(Args... args) {
48  SlotList local;
49  {
50  std::lock_guard<std::mutex> lock(mutex_);
51  for (auto& slot : slots_) {
52  local.emplace_back(slot);
53  }
54  }
55 
56  if (!local.empty()) {
57  for (auto& slot : local) {
58  (*slot)(args...);
59  }
60  }
61 
62  ClearDisconnectedSlots();
63  }
64 
66  auto slot = std::make_shared<Slot<Args...>>(cb);
67  {
68  std::lock_guard<std::mutex> lock(mutex_);
69  slots_.emplace_back(slot);
70  }
71 
72  return ConnectionType(slot, this);
73  }
74 
75  bool Disconnect(const ConnectionType& conn) {
76  bool find = false;
77  {
78  std::lock_guard<std::mutex> lock(mutex_);
79  for (auto& slot : slots_) {
80  if (conn.HasSlot(slot)) {
81  find = true;
82  slot->Disconnect();
83  }
84  }
85  }
86 
87  if (find) {
88  ClearDisconnectedSlots();
89  }
90  return find;
91  }
92 
94  std::lock_guard<std::mutex> lock(mutex_);
95  for (auto& slot : slots_) {
96  slot->Disconnect();
97  }
98  slots_.clear();
99  }
100 
101  private:
102  Signal(const Signal&) = delete;
103  Signal& operator=(const Signal&) = delete;
104 
105  void ClearDisconnectedSlots() {
106  std::lock_guard<std::mutex> lock(mutex_);
107  slots_.erase(
108  std::remove_if(slots_.begin(), slots_.end(),
109  [](const SlotPtr& slot) { return !slot->connected(); }),
110  slots_.end());
111  }
112 
113  SlotList slots_;
114  std::mutex mutex_;
115 };
116 
117 template <typename... Args>
118 class Connection {
119  public:
120  using SlotPtr = std::shared_ptr<Slot<Args...>>;
121  using SignalPtr = Signal<Args...>*;
122 
123  Connection() : slot_(nullptr), signal_(nullptr) {}
124  Connection(const SlotPtr& slot, const SignalPtr& signal)
125  : slot_(slot), signal_(signal) {}
126  virtual ~Connection() {
127  slot_ = nullptr;
128  signal_ = nullptr;
129  }
130 
131  Connection& operator=(const Connection& another) {
132  if (this != &another) {
133  this->slot_ = another.slot_;
134  this->signal_ = another.signal_;
135  }
136  return *this;
137  }
138 
139  bool HasSlot(const SlotPtr& slot) const {
140  if (slot != nullptr && slot_ != nullptr) {
141  return slot_.get() == slot.get();
142  }
143  return false;
144  }
145 
146  bool IsConnected() const {
147  if (slot_) {
148  return slot_->connected();
149  }
150  return false;
151  }
152 
153  bool Disconnect() {
154  if (signal_ && slot_) {
155  return signal_->Disconnect(*this);
156  }
157  return false;
158  }
159 
160  private:
161  SlotPtr slot_;
162  SignalPtr signal_;
163 };
164 
165 template <typename... Args>
166 class Slot {
167  public:
168  using Callback = std::function<void(Args...)>;
169  Slot(const Slot& another)
170  : cb_(another.cb_), connected_(another.connected_) {}
171  explicit Slot(const Callback& cb, bool connected = true)
172  : cb_(cb), connected_(connected) {}
173  virtual ~Slot() {}
174 
175  void operator()(Args... args) {
176  if (connected_ && cb_) {
177  cb_(args...);
178  }
179  }
180 
181  void Disconnect() { connected_ = false; }
182  bool connected() const { return connected_; }
183 
184  private:
185  Callback cb_;
186  bool connected_ = true;
187 };
188 
189 } // namespace base
190 } // namespace cyber
191 } // namespace apollo
192 
193 #endif // CYBER_BASE_SIGNAL_H_
Connection()
Definition: signal.h:123
bool IsConnected() const
Definition: signal.h:146
void operator()(Args... args)
Definition: signal.h:175
bool connected() const
Definition: signal.h:182
bool Disconnect()
Definition: signal.h:153
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
Slot(const Slot &another)
Definition: signal.h:169
void operator()(Args... args)
Definition: signal.h:47
virtual ~Connection()
Definition: signal.h:126
void Disconnect()
Definition: signal.h:181
virtual ~Slot()
Definition: signal.h:173
Slot(const Callback &cb, bool connected=true)
Definition: signal.h:171
std::function< void(Args...)> Callback
Definition: signal.h:168
std::function< void(Args...)> Callback
Definition: signal.h:39
virtual ~Signal()
Definition: signal.h:45
Signal()
Definition: signal.h:44
ConnectionType Connect(const Callback &cb)
Definition: signal.h:65
Definition: signal.h:31
bool Disconnect(const ConnectionType &conn)
Definition: signal.h:75
Connection(const SlotPtr &slot, const SignalPtr &signal)
Definition: signal.h:124
std::shared_ptr< Slot< Args... > > SlotPtr
Definition: signal.h:120
Connection & operator=(const Connection &another)
Definition: signal.h:131
bool HasSlot(const SlotPtr &slot) const
Definition: signal.h:139
Definition: signal.h:37
Definition: signal.h:34
std::list< SlotPtr > SlotList
Definition: signal.h:41
Connection< Args... > ConnectionType
Definition: signal.h:42
std::shared_ptr< Slot< Args... > > SlotPtr
Definition: signal.h:40
void DisconnectAllSlots()
Definition: signal.h:93