Apollo 11.0
自动驾驶开放平台
shm_dispatcher.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_TRANSPORT_DISPATCHER_SHM_DISPATCHER_H_
18#define CYBER_TRANSPORT_DISPATCHER_SHM_DISPATCHER_H_
19
20#include <cstring>
21#include <memory>
22#include <string>
23#include <thread>
24#include <unordered_map>
25
28#include "cyber/common/log.h"
29#include "cyber/common/macros.h"
34#include "cyber/time/time.h"
39
40namespace apollo {
41namespace cyber {
42namespace transport {
43
44class ShmDispatcher;
49
50class ShmDispatcher : public Dispatcher {
51 public:
52 // key: channel_id
53 using SegmentContainer = std::unordered_map<uint64_t, SegmentPtr>;
54
55 virtual ~ShmDispatcher();
56
57 void Shutdown() override;
58
59 template <typename MessageT>
60 void AddListener(const RoleAttributes& self_attr,
61 const MessageListener<MessageT>& listener);
62
63 template <typename MessageT>
64 void AddListener(const RoleAttributes& self_attr,
65 const RoleAttributes& opposite_attr,
66 const MessageListener<MessageT>& listener);
67
68 template <typename MessageT>
69 void AddArenaListener(const RoleAttributes& self_attr,
70 const MessageListener<MessageT>& listener);
71
72 template <typename MessageT>
73 void AddArenaListener(const RoleAttributes& self_attr,
74 const RoleAttributes& opposite_attr,
75 const MessageListener<MessageT>& listener);
76
77 private:
78 void AddSegment(const RoleAttributes& self_attr);
79 void ReadMessage(uint64_t channel_id, uint32_t block_index);
80 void OnMessage(uint64_t channel_id, const std::shared_ptr<ReadableBlock>& rb,
81 const MessageInfo& msg_info);
82 void ReadArenaMessage(uint64_t channel_id, uint32_t arena_block_index);
83 void OnArenaMessage(uint64_t channel_id,
84 const std::shared_ptr<ReadableBlock>& rb,
85 const MessageInfo& msg_info);
86 void ThreadFunc();
87 bool Init();
88
89 uint64_t host_id_;
90 SegmentContainer segments_;
91 std::unordered_map<uint64_t, uint32_t> previous_indexes_;
92 std::unordered_map<uint64_t, uint32_t> arena_previous_indexes_;
94 AtomicRWLock segments_lock_;
95 std::thread thread_;
96 NotifierPtr notifier_;
97
99};
100
101template <typename MessageT>
103 const RoleAttributes& self_attr,
104 const MessageListener<MessageT>& listener) {
105 if (is_shutdown_.load()) {
106 return;
107 }
108 uint64_t channel_id = self_attr.channel_id();
109
110 std::shared_ptr<ListenerHandler<MessageT>> handler;
111 ListenerHandlerBasePtr* handler_base = nullptr;
112 if (arena_msg_listeners_.Get(channel_id, &handler_base)) {
113 handler =
114 std::dynamic_pointer_cast<ListenerHandler<MessageT>>(*handler_base);
115 if (handler == nullptr) {
116 AERROR << "please ensure that readers with the same channel["
117 << self_attr.channel_name()
118 << "] in the same process have the same message type";
119 return;
120 }
121 } else {
122 ADEBUG << "new reader for channel:"
123 << GlobalData::GetChannelById(channel_id);
124 handler.reset(new ListenerHandler<MessageT>());
125 arena_msg_listeners_.Set(channel_id, handler);
126 }
127 handler->Connect(self_attr.id(), listener);
128}
129
130template <typename MessageT>
132 const RoleAttributes& self_attr, const RoleAttributes& opposite_attr,
133 const MessageListener<MessageT>& listener) {
134 if (is_shutdown_.load()) {
135 return;
136 }
137 uint64_t channel_id = self_attr.channel_id();
138 std::shared_ptr<ListenerHandler<MessageT>> handler;
139 ListenerHandlerBasePtr* handler_base = nullptr;
140 if (arena_msg_listeners_.Get(channel_id, &handler_base)) {
141 handler =
142 std::dynamic_pointer_cast<ListenerHandler<MessageT>>(*handler_base);
143 if (handler == nullptr) {
144 AERROR << "please ensuore that readers with the same channel["
145 << self_attr.channel_name()
146 << "] in the same process have the same message type";
147 return;
148 }
149 } else {
150 ADEBUG << "new reader for channel:"
151 << GlobalData::GetChannelById(channel_id);
152 handler.reset(new ListenerHandler<MessageT>());
153 arena_msg_listeners_.Set(channel_id, handler);
154 }
155 handler->Connect(self_attr.id(), listener);
156}
157
158template <typename MessageT>
160 const MessageListener<MessageT>& listener) {
161 // FIXME: make it more clean
162 if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm(
163 self_attr.channel_id()) &&
164 self_attr.message_type() != message::MessageType<message::RawMessage>() &&
165 self_attr.message_type() !=
166 message::MessageType<message::PyMessageWrap>()) {
167 auto listener_adapter = [listener, self_attr](
168 const std::shared_ptr<ReadableBlock>& rb,
169 const MessageInfo& msg_info) {
170 auto msg = std::make_shared<MessageT>();
171 // TODO(ALL): read config from msg_info
172 auto arena_manager = ProtobufArenaManager::Instance();
173 auto msg_wrapper = arena_manager->CreateMessageWrapper();
174 memcpy(msg_wrapper->GetData(), rb->buf, 1024);
175 MessageT* msg_p;
176 if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(),
177 &msg_p)) {
178 AERROR << "ParseFromArenaMessageWrapper failed";
179 }
180 // msg->CopyFrom(*msg_p);
181 // msg = arena_manager->LoadMessage<MessageT>(msg_wrapper.get())
182 auto segment = arena_manager->GetSegment(self_attr.channel_id());
183 auto msg_addr = reinterpret_cast<uint64_t>(msg_p);
184 msg.reset(reinterpret_cast<MessageT*>(msg_addr),
185 [arena_manager, segment, msg_wrapper](MessageT* p) {
186 // fprintf(stderr, "msg deleter invoked\n");
187 // auto related_blocks =
188 // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get());
189 // for (auto block_index : related_blocks) {
190 // // segment->ReleaseBlockForReadByIndex(block_index);
191 // segment->RemoveBlockReadLock(block_index);
192 // }
193 });
194 for (auto block_index :
195 arena_manager->GetMessageRelatedBlocks(msg_wrapper.get())) {
196 segment->AddBlockReadLock(block_index);
197 }
198
199 auto send_time = msg_info.send_time();
200 auto msg_seq_num = msg_info.msg_seq_num();
201
202 statistics::Statistics::Instance()->AddRecvCount(self_attr,
203 msg_info.msg_seq_num());
204 statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr,
205 msg_seq_num);
206
207 auto recv_time = Time::Now().ToNanosecond();
208
209 // sampling in microsecond
210 auto tran_diff = (recv_time - send_time) / 1000;
211 if (tran_diff > 0) {
212 // sample transport latency in microsecond
213 statistics::Statistics::Instance()->SamplingTranLatency<uint64_t>(
214 self_attr, tran_diff);
215 }
216 statistics::Statistics::Instance()->SetProcStatus(self_attr,
217 recv_time / 1000);
218 listener(msg, msg_info);
219 auto related_blocks =
220 arena_manager->GetMessageRelatedBlocks(msg_wrapper.get());
221 for (auto block_index : related_blocks) {
222 // segment->ReleaseBlockForReadByIndex(block_index);
223 segment->RemoveBlockReadLock(block_index);
224 }
225 };
226
227 AddArenaListener<ReadableBlock>(self_attr, listener_adapter);
228 } else {
229 auto listener_adapter = [listener, self_attr](
230 const std::shared_ptr<ReadableBlock>& rb,
231 const MessageInfo& msg_info) {
232 auto msg = std::make_shared<MessageT>();
233 // TODO(ALL): read config from msg_info
235 rb->buf, static_cast<int>(rb->block->msg_size()), msg.get()));
236
237 auto send_time = msg_info.send_time();
238 auto msg_seq_num = msg_info.msg_seq_num();
239
240 statistics::Statistics::Instance()->AddRecvCount(self_attr,
241 msg_info.msg_seq_num());
242 statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr,
243 msg_seq_num);
244
245 auto recv_time = Time::Now().ToNanosecond();
246
247 // sampling in microsecond
248 auto tran_diff = (recv_time - send_time) / 1000;
249 if (tran_diff > 0) {
250 // sample transport latency in microsecond
251 statistics::Statistics::Instance()->SamplingTranLatency<uint64_t>(
252 self_attr, tran_diff);
253 }
254 statistics::Statistics::Instance()->SetProcStatus(self_attr,
255 recv_time / 1000);
256 listener(msg, msg_info);
257 };
258
259 Dispatcher::AddListener<ReadableBlock>(self_attr, listener_adapter);
260 }
261 AddSegment(self_attr);
262}
263
264template <typename MessageT>
266 const RoleAttributes& opposite_attr,
267 const MessageListener<MessageT>& listener) {
268 // FIXME: make it more clean
269 if (cyber::common::GlobalData::Instance()->IsChannelEnableArenaShm(
270 self_attr.channel_id()) &&
271 self_attr.message_type() != message::MessageType<message::RawMessage>() &&
272 self_attr.message_type() !=
273 message::MessageType<message::PyMessageWrap>()) {
274 auto listener_adapter = [listener, self_attr](
275 const std::shared_ptr<ReadableBlock>& rb,
276 const MessageInfo& msg_info) {
277 auto msg = std::make_shared<MessageT>();
278 auto arena_manager = ProtobufArenaManager::Instance();
279 auto msg_wrapper = arena_manager->CreateMessageWrapper();
280 memcpy(msg_wrapper->GetData(), rb->buf, 1024);
281 MessageT* msg_p;
282 if (!message::ParseFromArenaMessageWrapper(msg_wrapper.get(), msg.get(),
283 &msg_p)) {
284 AERROR << "ParseFromArenaMessageWrapper failed";
285 }
286 // msg->CopyFrom(*msg_p);
287 // msg = arena_manager->LoadMessage<MessageT>(msg_wrapper.get())
288 auto segment = arena_manager->GetSegment(self_attr.channel_id());
289 auto msg_addr = reinterpret_cast<uint64_t>(msg_p);
290 msg.reset(reinterpret_cast<MessageT*>(msg_addr),
291 [arena_manager, segment, msg_wrapper](MessageT* p) {
292 // fprintf(stderr, "msg deleter invoked\n");
293 // auto related_blocks =
294 // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get());
295 // for (auto block_index : related_blocks) {
296 // // segment->ReleaseBlockForReadByIndex(block_index);
297 // segment->RemoveBlockReadLock(block_index);
298 // }
299 });
300 for (auto block_index :
301 arena_manager->GetMessageRelatedBlocks(msg_wrapper.get())) {
302 segment->AddBlockReadLock(block_index);
303 }
304
305 auto send_time = msg_info.send_time();
306 auto msg_seq_num = msg_info.msg_seq_num();
307
308 statistics::Statistics::Instance()->AddRecvCount(self_attr,
309 msg_info.msg_seq_num());
310 statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr,
311 msg_seq_num);
312
313 auto recv_time = Time::Now().ToNanosecond();
314
315 // sampling in microsecond
316 auto tran_diff = (recv_time - send_time) / 1000;
317 if (tran_diff > 0) {
318 statistics::Statistics::Instance()->SamplingTranLatency<uint64_t>(
319 self_attr, tran_diff);
320 }
321 statistics::Statistics::Instance()->SetProcStatus(self_attr,
322 recv_time / 1000);
323
324 listener(msg, msg_info);
325 auto related_blocks =
326 arena_manager->GetMessageRelatedBlocks(msg_wrapper.get());
327 for (auto block_index : related_blocks) {
328 // segment->ReleaseBlockForReadByIndex(block_index);
329 segment->RemoveBlockReadLock(block_index);
330 }
331 };
332
333 AddArenaListener<ReadableBlock>(self_attr, opposite_attr, listener_adapter);
334 } else {
335 auto listener_adapter = [listener, self_attr](
336 const std::shared_ptr<ReadableBlock>& rb,
337 const MessageInfo& msg_info) {
338 auto msg = std::make_shared<MessageT>();
340 rb->buf, static_cast<int>(rb->block->msg_size()), msg.get()));
341
342 auto send_time = msg_info.send_time();
343 auto msg_seq_num = msg_info.msg_seq_num();
344
345 statistics::Statistics::Instance()->AddRecvCount(self_attr,
346 msg_info.msg_seq_num());
347 statistics::Statistics::Instance()->SetTotalMsgsStatus(self_attr,
348 msg_seq_num);
349
350 auto recv_time = Time::Now().ToNanosecond();
351
352 // sampling in microsecond
353 auto tran_diff = (recv_time - send_time) / 1000;
354 if (tran_diff > 0) {
355 statistics::Statistics::Instance()->SamplingTranLatency<uint64_t>(
356 self_attr, tran_diff);
357 }
358 statistics::Statistics::Instance()->SetProcStatus(self_attr,
359 recv_time / 1000);
360
361 listener(msg, msg_info);
362 };
363
364 Dispatcher::AddListener<ReadableBlock>(self_attr, opposite_attr,
365 listener_adapter);
366 }
367 AddSegment(self_attr);
368}
369
370} // namespace transport
371} // namespace cyber
372} // namespace apollo
373
374#endif // CYBER_TRANSPORT_DISPATCHER_SHM_DISPATCHER_H_
uint64_t ToNanosecond() const
convert time to nanosecond.
Definition time.cc:83
static Time Now()
get the current time.
Definition time.cc:57
A implementation of lock-free fixed size hash map
static std::string GetChannelById(uint64_t id)
void AddArenaListener(const RoleAttributes &self_attr, const MessageListener< MessageT > &listener)
void AddListener(const RoleAttributes &self_attr, const MessageListener< MessageT > &listener)
std::unordered_map< uint64_t, SegmentPtr > SegmentContainer
#define DECLARE_SINGLETON(classname)
Definition macros.h:52
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define RETURN_IF(condition)
Definition log.h:106
std::enable_if< HasParseFromArenaMessageWrapper< T >::value, bool >::type ParseFromArenaMessageWrapper(ArenaMessageWrapper *wrapper, T *message, T **message_ptr)
std::enable_if< HasParseFromArray< T >::value, bool >::type ParseFromArray(const void *data, int size, T *message)
std::shared_ptr< ListenerHandlerBase > ListenerHandlerBasePtr
std::function< void(const std::shared_ptr< MessageT > &, const MessageInfo &)> MessageListener
Definition dispatcher.h:53
class register implement
Definition arena_queue.h:37