Apollo 9.0
自动驾驶开放平台
shm_transmitter.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_TRANSMITTER_SHM_TRANSMITTER_H_
18#define CYBER_TRANSPORT_TRANSMITTER_SHM_TRANSMITTER_H_
19
20#include <cstring>
21#include <iostream>
22#include <memory>
23#include <string>
24
26#include "cyber/common/log.h"
27#include "cyber/common/util.h"
36
37namespace apollo {
38namespace cyber {
39namespace transport {
40
41template <typename M>
42class ShmTransmitter : public Transmitter<M> {
43 public:
44 using MessagePtr = std::shared_ptr<M>;
45
46 explicit ShmTransmitter(const RoleAttributes& attr);
47 virtual ~ShmTransmitter();
48
49 void Enable() override;
50 void Disable() override;
51
52 void Enable(const RoleAttributes& opposite_attr);
53 void Disable(const RoleAttributes& opposite_attr);
54
55 bool Transmit(const MessagePtr& msg, const MessageInfo& msg_info) override;
56
57 bool AcquireMessage(std::shared_ptr<M>& msg);
58
59 private:
60 bool Transmit(const M& msg, const MessageInfo& msg_info);
61
62 SegmentPtr segment_;
63 uint64_t channel_id_;
64 uint64_t host_id_;
65 NotifierPtr notifier_;
66 std::atomic<int> serialized_receiver_count_;
67 std::atomic<int> arena_receiver_count_;
68 bool arena_transmit_;
69};
70
71template <typename M>
72bool ShmTransmitter<M>::AcquireMessage(std::shared_ptr<M>& msg) {
73 if (this->enabled_) {
74 auto msg_o = msg.get();
75 auto arena_manager = ProtobufArenaManager::Instance();
76 if (!arena_manager->Enable() ||
77 !arena_manager->EnableSegment(this->attr_.channel_id())) {
78 ADEBUG << "arena manager enable failed.";
79 return false;
80 }
81 arena_manager->AcquireArenaMessage(channel_id_, msg);
82 if (msg.get() != msg_o) {
83 return true;
84 } else {
85 return false;
86 }
87 }
88 return false;
89}
90
91template <typename M>
93 : Transmitter<M>(attr),
94 segment_(nullptr),
95 channel_id_(attr.channel_id()),
96 notifier_(nullptr),
97 serialized_receiver_count_(0),
98 arena_receiver_count_(0) {
99 host_id_ = common::Hash(attr.host_ip());
100 arena_transmit_ = common::GlobalData::Instance()->IsChannelEnableArenaShm(
101 this->attr_.channel_id());
102}
103
104template <typename M>
108
109template <typename M>
110void ShmTransmitter<M>::Enable(const RoleAttributes& opposite_attr) {
111 if (arena_transmit_) {
112 if (opposite_attr.message_type() ==
113 message::MessageType<message::RawMessage>() ||
114 opposite_attr.message_type() ==
115 message::MessageType<message::PyMessageWrap>()) {
116 serialized_receiver_count_.fetch_add(1);
117 } else {
118 arena_receiver_count_.fetch_add(1);
119 }
120 } else {
121 serialized_receiver_count_.fetch_add(1);
122 }
123 if (!this->enabled_) {
124 this->Enable();
125 }
126}
127
128template <typename M>
129void ShmTransmitter<M>::Disable(const RoleAttributes& opposite_attr) {
130 if (this->enabled_) {
131 if (arena_transmit_) {
132 if (opposite_attr.message_type() ==
133 message::MessageType<message::RawMessage>() ||
134 opposite_attr.message_type() ==
135 message::MessageType<message::PyMessageWrap>()) {
136 serialized_receiver_count_.fetch_sub(1);
137 } else {
138 arena_receiver_count_.fetch_sub(1);
139 }
140 if (serialized_receiver_count_.load() <= 0 &&
141 arena_receiver_count_.load() <= 0) {
142 this->Disable();
143 }
144 } else {
145 serialized_receiver_count_.fetch_sub(1);
146 if (serialized_receiver_count_.load() <= 0) {
147 this->Disable();
148 }
149 }
150 }
151}
152
153template <typename M>
155 if (this->enabled_) {
156 return;
157 }
158
159 if (serialized_receiver_count_.load() == 0 &&
160 arena_receiver_count_.load() == 0) {
161 AERROR << "please enable shm transmitter by passing role attr.";
162 return;
163 }
164
165 if (arena_transmit_) {
166 auto arena_manager = ProtobufArenaManager::Instance();
167 if (!arena_manager->Enable() ||
168 !arena_manager->EnableSegment(this->attr_.channel_id())) {
169 AERROR << "arena manager enable failed.";
170 return;
171 }
172 }
173
174 segment_ = SegmentFactory::CreateSegment(channel_id_);
176 this->enabled_ = true;
177}
178
179template <typename M>
181 if (this->enabled_) {
182 segment_ = nullptr;
183 notifier_ = nullptr;
184 this->enabled_ = false;
185 }
186}
187
188template <typename M>
190 const MessageInfo& msg_info) {
191 return Transmit(*msg, msg_info);
192}
193
194template <typename M>
195bool ShmTransmitter<M>::Transmit(const M& msg, const MessageInfo& msg_info) {
196 if (!this->enabled_) {
197 ADEBUG << "not enable.";
198 return false;
199 }
200
201 ReadableInfo readable_info;
202 WritableBlock arena_wb;
203 WritableBlock wb;
204
205 readable_info.set_host_id(host_id_);
206 readable_info.set_channel_id(channel_id_);
207 readable_info.set_arena_block_index(-1);
208 readable_info.set_block_index(-1);
209
210 if (arena_transmit_) {
211 // std::size_t msg_size = sizeof(message::ArenaMessageWrapper);
212 std::size_t msg_size = 1024;
213 if (!segment_->AcquireArenaBlockToWrite(msg_size, &arena_wb)) {
214 AERROR << "acquire block failed.";
215 return false;
216 }
217
218 ADEBUG << "arena block index: " << arena_wb.index;
219 auto arena_manager = ProtobufArenaManager::Instance();
220 auto msg_wrapper = arena_manager->CreateMessageWrapper();
221 arena_manager->SetMessageChannelId(msg_wrapper.get(), channel_id_);
222 M* msg_p;
223 // arena_manager->CreateMessage(msg_wrapper.get(), msg);
224 if (!message::SerializeToArenaMessageWrapper(msg, msg_wrapper.get(),
225 &msg_p)) {
226 AERROR << "serialize to arena message wrapper failed.";
227 segment_->ReleaseArenaWrittenBlock(arena_wb);
228 return false;
229 }
230 auto segment = arena_manager->GetSegment(channel_id_);
231 // auto msg_n =
232 // std::shared_ptr<M>(
233 // msg_p, [arena_manager, segment, msg_wrapper](M* p) {
234 // auto related_blocks =
235 // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get());
236 // for (auto block_index : related_blocks) {
237 // // segment->ReleaseBlockForWriteByIndex(block_index);
238 // segment->RemoveBlockWriteLock(block_index);
239 // }
240 // });
241 // for (auto block_index :
242 // arena_manager->GetMessageRelatedBlocks(msg_wrapper.get())) {
243 // segment->LockBlockForWriteByIndex(block_index);
244 // }
245 memcpy(arena_wb.buf, msg_wrapper->GetData(), msg_size);
246 arena_wb.block->set_msg_size(msg_size);
247
248 char* msg_info_addr = reinterpret_cast<char*>(arena_wb.buf) + msg_size;
249 if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) {
250 AERROR << "serialize message info failed.";
251 segment_->ReleaseArenaWrittenBlock(arena_wb);
252 return false;
253 }
254 arena_wb.block->set_msg_info_size(MessageInfo::kSize);
255 readable_info.set_arena_block_index(arena_wb.index);
256 if (serialized_receiver_count_.load() > 0) {
257 std::size_t msg_size = message::ByteSize(msg);
258 if (!segment_->AcquireBlockToWrite(msg_size, &wb)) {
259 AERROR << "acquire block failed.";
260 return false;
261 }
262
263 ADEBUG << "block index: " << wb.index;
264 if (!message::SerializeToArray(msg, wb.buf, static_cast<int>(msg_size))) {
265 AERROR << "serialize to array failed.";
266 segment_->ReleaseWrittenBlock(wb);
267 return false;
268 }
269 wb.block->set_msg_size(msg_size);
270
271 char* msg_info_addr = reinterpret_cast<char*>(wb.buf) + msg_size;
272 if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) {
273 AERROR << "serialize message info failed.";
274 segment_->ReleaseWrittenBlock(wb);
275 return false;
276 }
277 wb.block->set_msg_info_size(MessageInfo::kSize);
278 segment_->ReleaseWrittenBlock(wb);
279 segment_->ReleaseArenaWrittenBlock(arena_wb);
280 readable_info.set_block_index(wb.index);
281 } else {
282 segment_->ReleaseArenaWrittenBlock(arena_wb);
283 }
284 } else {
285 std::size_t msg_size = message::ByteSize(msg);
286 if (!segment_->AcquireBlockToWrite(msg_size, &wb)) {
287 AERROR << "acquire block failed.";
288 return false;
289 }
290
291 ADEBUG << "block index: " << wb.index;
292 if (!message::SerializeToArray(msg, wb.buf, static_cast<int>(msg_size))) {
293 AERROR << "serialize to array failed.";
294 segment_->ReleaseWrittenBlock(wb);
295 return false;
296 }
297 wb.block->set_msg_size(msg_size);
298
299 char* msg_info_addr = reinterpret_cast<char*>(wb.buf) + msg_size;
300 if (!msg_info.SerializeTo(msg_info_addr, MessageInfo::kSize)) {
301 AERROR << "serialize message info failed.";
302 segment_->ReleaseWrittenBlock(wb);
303 return false;
304 }
305 wb.block->set_msg_info_size(MessageInfo::kSize);
306 segment_->ReleaseWrittenBlock(wb);
307 readable_info.set_block_index(wb.index);
308 }
309
310 ADEBUG << "Writing sharedmem message: "
312 << " to normal block: " << readable_info.block_index()
313 << " to arena block: " << readable_info.arena_block_index();
314 return notifier_->Notify(readable_info);
315}
316
317} // namespace transport
318} // namespace cyber
319} // namespace apollo
320
321#endif // CYBER_TRANSPORT_TRANSMITTER_SHM_TRANSMITTER_H_
static std::string GetChannelById(uint64_t id)
static const std::size_t kSize
bool SerializeTo(std::string *dst) const
static SegmentPtr CreateSegment(uint64_t channel_id)
ShmTransmitter(const RoleAttributes &attr)
bool Transmit(const MessagePtr &msg, const MessageInfo &msg_info) override
bool AcquireMessage(std::shared_ptr< M > &msg)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
std::size_t Hash(const std::string &key)
Definition util.h:27
std::enable_if< HasSerializeToArray< T >::value, bool >::type SerializeToArray(const T &message, void *data, int size)
std::enable_if< HasByteSize< T >::value, int >::type ByteSize(const T &message)
std::enable_if< HasSerializeToArenaMessageWrapper< T >::value, bool >::type SerializeToArenaMessageWrapper(const T &message, ArenaMessageWrapper *wrapper, T **message_ptr)
std::shared_ptr< Segment > SegmentPtr
Definition segment.h:34
class register implement