Apollo 10.0
自动驾驶开放平台
signal.h
浏览该文件的文档.
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
26namespace apollo {
27namespace cyber {
28namespace base {
29
30template <typename... Args>
31class Slot;
32
33template <typename... Args>
34class Connection;
35
36template <typename... Args>
37class 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
117template <typename... Args>
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
165template <typename... Args>
166class 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_
Signal< Args... > * SignalPtr
Definition signal.h:121
bool HasSlot(const SlotPtr &slot) const
Definition signal.h:139
Connection & operator=(const Connection &another)
Definition signal.h:131
Connection(const SlotPtr &slot, const SignalPtr &signal)
Definition signal.h:124
std::shared_ptr< Slot< Args... > > SlotPtr
Definition signal.h:120
Connection< Args... > ConnectionType
Definition signal.h:42
std::function< void(Args...)> Callback
Definition signal.h:39
std::list< SlotPtr > SlotList
Definition signal.h:41
bool Disconnect(const ConnectionType &conn)
Definition signal.h:75
std::shared_ptr< Slot< Args... > > SlotPtr
Definition signal.h:40
void operator()(Args... args)
Definition signal.h:47
ConnectionType Connect(const Callback &cb)
Definition signal.h:65
Slot(const Callback &cb, bool connected=true)
Definition signal.h:171
std::function< void(Args...)> Callback
Definition signal.h:168
bool connected() const
Definition signal.h:182
Slot(const Slot &another)
Definition signal.h:169
void operator()(Args... args)
Definition signal.h:175
class register implement
Definition arena_queue.h:37