Apollo 9.0
自动驾驶开放平台
protobuf_arena_manager.h
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2024 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#ifndef CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_
17#define CYBER_TRANSPORT_SHM_PROTOBUF_ARENA_MANAGER_H_
18
19#include <vector>
20#include <memory>
21#include <unordered_map>
22#include <functional>
23
24#include <google/protobuf/arena.h>
25
27#include "cyber/common/macros.h"
33
34namespace apollo {
35namespace cyber {
36namespace transport {
37
39 struct {
40 std::atomic<uint64_t> ref_count_;
41 std::atomic<bool> auto_extended_;
42 std::atomic<uint64_t> message_size_;
43 std::atomic<uint64_t> block_num_;
44 std::atomic<uint64_t> message_seq_;
45 std::mutex mutex_;
47 uint8_t bytes_[128];
48};
49
51 struct {
52 uint64_t size_;
53 std::atomic<uint64_t> writing_ref_count_;
54 std::atomic<uint64_t> reading_ref_count_;
57 uint8_t bytes_[128];
58};
59
61 uint64_t size_;
62 // std::atomic<uint64_t> writing_ref_count_;
63 // std::atomic<uint64_t> reading_ref_count_;
64 // base::PthreadRWLock read_write_mutex_;
65 static const int32_t kRWLockFree;
66 static const int32_t kWriteExclusive;
67 static const int32_t kMaxTryLockTimes;
68 std::atomic<int32_t> lock_num_ = {0};
69};
70
76
78 public:
80 explicit ArenaSegment(uint64_t channel_id);
81 ArenaSegment(uint64_t channel_id, void* base_address);
82 ArenaSegment(uint64_t channel_id, uint64_t message_size, uint64_t block_num,
83 void* base_address);
85
86 bool Init(uint64_t message_size, uint64_t block_num);
87 // bool Create(uint64_t message_size, uint64_t block_num);
88 bool Open(uint64_t message_size, uint64_t block_num);
89 bool OpenOrCreate(uint64_t message_size, uint64_t block_num);
90
91 void* GetShmAddress();
92
94 bool AddBlockWriteLock(uint64_t block_index);
95 void RemoveBlockWriteLock(uint64_t block_index);
96 bool AddBlockReadLock(uint64_t block_index);
97 void RemoveBlockReadLock(uint64_t block_index);
98
99 bool AcquireBlockToWrite(uint64_t size, ArenaSegmentBlockInfo* block_info);
100 void ReleaseWrittenBlock(const ArenaSegmentBlockInfo& block_info);
101
103 void ReleaseReadBlock(const ArenaSegmentBlockInfo& block_info);
104
105 // uint64_t GetCapicity();
106
107 public:
110 std::vector<std::shared_ptr<google::protobuf::Arena>> arenas_;
111 std::vector<uint64_t> arena_block_address_;
112 uint64_t channel_id_;
113 uint64_t key_id_;
116
118};
119
121 struct {
122 uint64_t channel_id_;
124 uint64_t related_blocks_[4];
127 uint8_t bytes_[256];
128};
129
131 struct {
132 uint64_t version_;
135 uint64_t block_size_;
136 uint64_t block_num_;
138 uint64_t message_num_;
139 uint64_t message_seq_;
144 uint8_t bytes_[256];
145};
146
148 public:
149 using ArenaAllocCallback = std::function<void*(uint64_t)>;
150
152
153 uint64_t GetBaseAddress(const message::ArenaMessageWrapper* wrapper) override;
154
155 bool Enable();
156 bool EnableSegment(uint64_t channel_id);
157 bool Destroy();
158 // bool Shutdown();
159
161 uint64_t channel_id);
164 uint64_t offset);
166 std::vector<uint64_t> GetMessageRelatedBlocks(
170 uint64_t block_index);
171
172 std::shared_ptr<ArenaSegment> GetSegment(uint64_t channel_id);
173
175 const void* message) override;
176 void* GetMessage(message::ArenaMessageWrapper* wrapper) override;
177
178 template<typename M,
179 typename std::enable_if<
180 google::protobuf::Arena::is_arena_constructable<M>::value,
181 M>::type* = nullptr>
182 void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr<M>& ret_msg) {
183 auto arena_conf =
184 cyber::common::GlobalData::Instance()->GetChannelArenaConf(channel_id);
185 google::protobuf::ArenaOptions options;
186 options.start_block_size = arena_conf.max_msg_size();
187 options.max_block_size = arena_conf.max_msg_size();
188
189 auto segment = GetSegment(channel_id);
190 if (!segment) {
191 return;
192 }
193
195 // TODO(All): size should be send to
196 // AcquireBlockToWrite for dynamic adjust block size
197 // auto size = input_msg->ByteSizeLong();
198 uint64_t size = 0;
199 if (!segment->AcquireBlockToWrite(size, &wb)) {
200 return;
201 }
202 options.initial_block = reinterpret_cast<char*>(
203 segment->arena_block_address_[wb.block_index_]);
204 options.initial_block_size = segment->message_capacity_;
205 if (segment->arenas_[wb.block_index_] != nullptr) {
206 segment->arenas_[wb.block_index_] = nullptr;
207 }
208 segment->arenas_[wb.block_index_] = \
209 std::make_shared<google::protobuf::Arena>(options);
210
211 // deconstructor do nothing to avoid proto
212 // instance deconstructed before arena allocator
213 ret_msg = std::shared_ptr<M>(google::protobuf::Arena::CreateMessage<M>(
214 segment->arenas_[wb.block_index_].get()), [segment, wb](M* ptr){
215 int32_t lock_num = segment->blocks_[
216 wb.block_index_].lock_num_.load();
217 if (lock_num < ArenaSegmentBlock::kRWLockFree) {
218 segment->ReleaseWrittenBlock(wb);
219 }
220 });
221 return;
222 }
223
224 template<typename M,
225 typename std::enable_if<
226 !google::protobuf::Arena::is_arena_constructable<M>::value,
227 M>::type* = nullptr>
228 void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr<M>& ret_msg) {
229 return;
230 }
231
232 private:
233 bool init_;
234 std::unordered_map<uint64_t, std::shared_ptr<ArenaSegment>> segments_;
235 std::mutex segments_mutex_;
236
237 std::shared_ptr<ArenaAddressAllocator> address_allocator_;
238
239 static ArenaAllocCallback arena_alloc_cb_;
240 static void* ArenaAlloc(uint64_t size);
241 static void ArenaDealloc(void* addr, uint64_t size);
242
243 std::mutex arena_alloc_cb_mutex_;
244
245 std::unordered_map<uint64_t, uint64_t> managed_wrappers_;
246
248};
249
250// template <typename MessageT>
251// std::shared_ptr<MessageT> ProtobufArenaManager::CreateMessage(
252// message::ArenaMessageWrapper* wrapper, const MessageT& message) {}
253
254// template <typename MessageT>
255// std::shared_ptr<MessageT> ProtobufArenaManager::LoadMessage(
256// message::ArenaMessageWrapper* wrapper) {}
257
258} // namespace transport
259} // namespace cyber
260} // namespace apollo
261
262#endif
bool Init(uint64_t message_size, uint64_t block_num)
bool Open(uint64_t message_size, uint64_t block_num)
std::vector< std::shared_ptr< google::protobuf::Arena > > arenas_
bool OpenOrCreate(uint64_t message_size, uint64_t block_num)
bool AcquireBlockToRead(ArenaSegmentBlockInfo *block_info)
void ReleaseReadBlock(const ArenaSegmentBlockInfo &block_info)
void ReleaseWrittenBlock(const ArenaSegmentBlockInfo &block_info)
bool AcquireBlockToWrite(uint64_t size, ArenaSegmentBlockInfo *block_info)
uint64_t GetBaseAddress(const message::ArenaMessageWrapper *wrapper) override
std::shared_ptr< ArenaSegment > GetSegment(uint64_t channel_id)
void ResetMessageRelatedBlocks(message::ArenaMessageWrapper *wrapper)
void AcquireArenaMessage(uint64_t channel_id, std::shared_ptr< M > &ret_msg)
void * GetMessage(message::ArenaMessageWrapper *wrapper) override
void SetMessageAddressOffset(message::ArenaMessageWrapper *wrapper, uint64_t offset)
uint64_t GetMessageAddressOffset(message::ArenaMessageWrapper *wrapper)
void SetMessageChannelId(message::ArenaMessageWrapper *wrapper, uint64_t channel_id)
uint64_t GetMessageChannelId(message::ArenaMessageWrapper *wrapper)
void * SetMessage(message::ArenaMessageWrapper *wrapper, const void *message) override
void AddMessageRelatedBlock(message::ArenaMessageWrapper *wrapper, uint64_t block_index)
std::vector< uint64_t > GetMessageRelatedBlocks(message::ArenaMessageWrapper *wrapper)
#define DECLARE_SINGLETON(classname)
Definition macros.h:52
int message_size
class register implement
struct apollo::cyber::transport::ArenaSegmentBlockDescriptor::@4 struct_
struct apollo::cyber::transport::ArenaSegmentState::@3 struct_
struct apollo::cyber::transport::ExtendedStruct::@5 meta_
struct apollo::cyber::transport::ProtobufArenaManagerMeta::@6 struct_