CARLA
 
载入中...
搜索中...
未找到
carla/Buffer.h
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8// 确保此头文件只被包含一次
9
10#include "carla/Debug.h"
11// 包含Carla的调试相关的头文件
12#include "carla/Exception.h"
13// 包含Carla的异常处理相关的头文件
14#include "carla/Logging.h"
15// 包含Carla的日志记录相关的头文件
16
17#include <boost/asio/buffer.hpp>
18// 包含Boost.Asio的缓冲区相关的头文件,用于处理缓冲区操作
19
20#include <cstdint>
21// 包含标准整数类型头文件,用于定义固定宽度的整数类型
22#include <limits>
23// 包含数值极限相关的头文件,用于获取数据类型的极限值
24#include <memory>
25// 包含内存管理相关的头文件,如智能指针
26#include <type_traits>
27// 包含类型特征相关的头文件,用于在编译时获取类型信息
28
29#ifdef LIBCARLA_INCLUDED_FROM_UE4
30// 如果是从UE4中包含此库
32// 包含启用UE4宏的头文件
33#include "Containers/Array.h"
34// 包含UE4的数组容器相关的头文件
36// 包含禁用UE4宏的头文件
37#endif // 结束预处理器条件编译块
38
39namespace carla {
40
41 class BufferPool;
42 class BufferView;
43
44 /// 一块原始数据。
45 /// 请注意,如果需要更多容量,则会分配一个新的内存块,并
46 /// 删除旧的内存块。这意味着默认情况下,缓冲区只能增长。要释放内存,使用 `clear` 或 `pop`。
47
48 /// 这是一个仅可移动的类型,设计为按值传递时成本较低。如果缓冲区
49 /// 从BufferPool中检索,则在销毁时内存会自动推回到池中。
50
51 /// @warning创建一个大于max_size() 的缓冲区是未定义的。
52 class Buffer {
53
54 // =========================================================================
55 ///@name 成员类型
56 // =========================================================================
57 /// @{
58
59 public:
60
61 using value_type = unsigned char;
62 // 定义缓冲区的值类型为无符号字符类型
63 using size_type = uint32_t;
64 // 定义缓冲区的大小类型为32位无符号整数
66 // 定义迭代器类型为指向值类型的指针,用于遍历缓冲区内容
67 using const_iterator = const value_type *;
68 // 定义常量迭代器类型为指向常量值类型的指针,用于常量遍历缓冲区内容
69 /// @}
70 // =========================================================================
71 /// @name 构造与析构
72 // =========================================================================
73 /// @{
74
75 public:
76
77 /// 创建一个空的缓冲区。
78 Buffer() = default;
79 // 使用默认构造函数创建一个空的Buffer对象,默认初始化成员变量
80
81 /// 创建一个分配了 @a size字节的缓冲区。
83 : _size(size),
85 _data(std::make_unique<value_type[]>(size)) {}
86 // 显式构造函数,接受一个size_type类型的参数size
87 // 初始化_size和_capacity为size,表示缓冲区的大小和容量
88 // 使用std::make_unique动态分配一块大小为size的value_type类型的数组,并将指针赋给_data
89
90 /// @copydoc Buffer(size_type)
91 explicit Buffer(uint64_t size)
92 : Buffer([size]() {
93 if (size > max_size()) {
94 throw_exception(std::invalid_argument("message size too big"));
95 }
96 return static_cast<size_type>(size);
97 }()) {}
98 // 显式构造函数,接受一个64位无符号整数类型的参数size
99 // 先检查size是否大于max_size(),如果是则抛出异常
100 // 然后将size转换为size_type类型并调用Buffer(size_type)构造函数
101
102 /// 将 @a source复制到此缓冲区中。分配所需的内存。
103 template <typename T>
104 explicit Buffer(const T &source) {
105 copy_from(source);
106 }
107 // 模板构造函数,接受一个任意类型T的参数source
108 // 调用copy_from函数将source的内容复制到缓冲区,内部会分配所需内存
109
110 explicit Buffer(const value_type *data, size_type size) {
112 }
113 // 显式构造函数,接受一个指向value_type类型的指针data和size_type类型的参数size
114 // 调用copy_from函数将data指向的内存内容复制到缓冲区,内部会分配所需内存
115
116 /// @copydoc Buffer(size_type)
117 explicit Buffer(const value_type *data, uint64_t size)
118 : Buffer(data, [size]() {
119 if (size > max_size()) {
120 throw_exception(std::invalid_argument("message size too big"));
121 }
122 return static_cast<size_type>(size);
123 }()) {}
124 // 显式构造函数,接受一个指向value_type类型的指针data和64位无符号整数类型的参数size
125 // 先检查size是否大于max_size(),如果是则抛出异常
126 // 然后将size转换为size_type类型并调用Buffer(const value_type *, size_type)构造函数
127
128 Buffer(const Buffer &) = delete;
129 // 禁用拷贝构造函数,表明此对象不支持拷贝构造
130
131 Buffer(Buffer &&rhs) noexcept
132 : _parent_pool(std::move(rhs._parent_pool)),
133 _size(rhs._size),
134 _capacity(rhs._capacity),
135 _data(rhs.pop()) {}
136 // 移动构造函数,接受一个右值引用rhs
137 // 将rhs的_parent_pool通过std::move移动给当前对象的_parent_pool
138 // 将rhs的_size和_capacity赋值给当前对象的_size和_capacity
139 // 调用rhs的pop函数获取rhs中的数据指针并赋给当前对象的_data
140
142 if (_capacity > 0u) {
144 }
145 }
146 // 析构函数,当_capacity大于0时调用ReuseThisBuffer函数进行缓冲区资源的处理
147
148 /// @}
149 // =========================================================================
150 /// @name 任务赋值
151 // =========================================================================
152 /// @{
153
154 public:
155
156 Buffer &operator=(const Buffer &) = delete;
157 // 禁用拷贝赋值运算符,表明此对象不支持拷贝赋值
158
159 Buffer &operator=(Buffer &&rhs) noexcept {
160 _parent_pool = std::move(rhs._parent_pool);
161 _size = rhs._size;
162 _capacity = rhs._capacity;
163 _data = rhs.pop();
164 return *this;
165 }
166 // 移动赋值运算符,接受一个右值引用rhs
167 // 将rhs的_parent_pool通过std::move移动给当前对象的_parent_pool
168 // 将rhs的_size和_capacity赋值给当前对象的_size和_capacity
169 // 调用rhs的pop函数获取rhs中的数据指针并赋给当前对象的_data
170 // 返回当前对象的引用
171
172 /// @}
173 // =========================================================================
174 /// @name 数据访问
175 // =========================================================================
176 /// @{
177
178 public:
179
180 /// 访问位置 @a i处的字节
181 const value_type &operator[](size_t i) const {
182 return _data[i];
183 }
184 // 重载常量下标运算符,返回位置i处的常量字节引用
185
186 /// Access the byte at position @a i.
188 return _data[i];
189 }
190 // 重载下标运算符,返回位置i处的字节引用
191
192 /// 直接访问分配的内存,如果没有分配内存则返回 nullptr。
193 const value_type *data() const noexcept {
194 return _data.get();
195 }
196 // 返回常量的指向分配内存的指针,如果_data为空则返回nullptr
197
198 /// Direct access to the allocated memory or nullptr if no memory is
199 /// allocated.
200 value_type *data() noexcept {
201 return _data.get();
202 }
203 // 返回指向分配内存的指针,如果_data为空则返回nullptr
204
205 /// 从这个缓冲区创建一个boost::asio::buffer。
206 /// @warning Boost.Asio缓冲区不拥有数据的所有权。调用者必须确保使用Asio缓冲区时不能删除此缓冲区所持有的内存。
207 boost::asio::const_buffer cbuffer() const noexcept {
208 return {data(), size()};
209 }
210 // 创建一个常量的Boost.Asio缓冲区,包含当前缓冲区的数据和大小
211
212 /// @copydoc cbuffer()
213 boost::asio::const_buffer buffer() const noexcept {
214 return cbuffer();
215 }
216 // 创建一个常量的Boost.Asio缓冲区,调用cbuffer函数
217
218 /// @copydoc cbuffer()
219 boost::asio::mutable_buffer buffer() noexcept {
220 return {data(), size()};
221 }
222 // 创建一个可修改的Boost.Asio缓冲区,包含当前缓冲区的数据和大小
223
224 /// @}
225 // =========================================================================
226 /// @name 容量
227 // =========================================================================
228 /// @{
229
230 public:
231
232 bool empty() const noexcept {
233 return _size == 0u;
234 }
235 // 判断缓冲区是否为空,即_size是否为0
236
237 size_type size() const noexcept {
238 return _size;
239 }
240 // 返回缓冲区的大小,即当前存储的数据量
241
242 static constexpr size_type max_size() noexcept {
243 return (std::numeric_limits<size_type>::max)();
244 }
245 // 返回缓冲区大小类型的最大值,为常量表达式
246
247 size_type capacity() const noexcept {
248 return _capacity;
249 }
250 // 返回缓冲区的容量,即分配的内存大小
251
252 /// @}
253 // =========================================================================
254 /// @name 迭代器
255 // =========================================================================
256 /// @{
257
258 public:
259
260 const_iterator cbegin() const noexcept {
261 return _data.get();
262 }
263 // 返回常量迭代器的起始位置,即_data指向的内存起始位置
264
265 const_iterator begin() const noexcept {
266 return cbegin();
267 }
268 // 返回常量迭代器的起始位置,调用cbegin函数
269
270 iterator begin() noexcept {
271 return _data.get();
272 }
273 // 返回迭代器的起始位置,即_data指向的内存起始位置
274
275 const_iterator cend() const noexcept {
276 return cbegin() + size();
277 }
278 // 返回常量迭代器的结束位置,即起始位置加上缓冲区大小
279
280 const_iterator end() const noexcept {
281 return cend();
282 }
283 // 返回常量迭代器的结束位置,调用cend函数
284
285 iterator end() noexcept {
286 return begin() + size();
287 }
288 // 返回迭代器的结束位置,即起始位置加上缓冲区大小
289
290 /// @}
291 // =========================================================================
292 /// @name 修改器
293 // =========================================================================
294 /// @{
295
296 public:
297
298 /// 重置缓冲区的大小。如果容量不足,当前内存将被丢弃,并分配一个新的大小为 @a size的内存块。
299 /// allocated.
301 if (_capacity < size) {
302 log_debug("allocating buffer of", size, "bytes");
303 _data = std::make_unique<value_type[]>(size);
304 _capacity = size;
305 }
306 _size = size;
307 }
308 // 如果传入的size大于当前容量_capacity
309 // 则打印调试信息,表示正在分配指定大小的缓冲区
310 // 然后重新分配一块大小为size的内存,更新_capacity为size
311 // 最后将_size设置为size,表示缓冲区的新大小
312
313 /// @copydoc reset(size_type)
314 void reset(uint64_t size) {
315 if (size > max_size()) {
316 throw_exception(std::invalid_argument("message size too big"));
317 }
318 reset(static_cast<size_type>(size));
319 }
320 // 如果传入的64位无符号整数size大于max_size()
321 // 则抛出异常,表示消息大小太大
322 // 否则将size转换为size_type类型并调用reset(size_type)函数
323
324 /// 调整缓冲区的大小。如果容量不足,将分配一个新的大小为 @a size的内存块,并复制数据。
325 void resize(uint64_t size) {
326 if (_capacity < size) {
327 std::unique_ptr<value_type[]> data = std::move(_data);
328 uint64_t old_size = size;
329 reset(size);
330 copy_from(data.get(), static_cast<size_type>(old_size));
331 }
332 _size = static_cast<size_type>(size);
333 }
334 // 如果传入的size大于当前容量_capacity
335 // 则先将当前_data保存到临时变量data中
336 // 记录旧的size
337 // 调用reset函数重新分配一块大小为size的内存
338 // 然后调用copy_from函数将旧数据复制到新的缓冲区中
339 // 最后将_size设置为转换后的size
340
341 /// 释放此缓冲区的内容,并将其大小和容量设置为零。
342 std::unique_ptr<value_type[]> pop() noexcept {
343 _size = 0u;
344 _capacity = 0u;
345 return std::move(_data);
346 }
347 // 将_size和_capacity设置为0,表示缓冲区为空
348 // 通过std::move返回_data,释放对原数据的所有权
349
350 /// 清除此缓冲区的内容,并将其大小和容量设置为零。
351 /// 删除已分配的内存。
352 void clear() noexcept {
353 pop();
354 }
355 // 调用pop函数清除缓冲区内容,释放内存并设置大小和容量为0
356
357 /// @}
358 // =========================================================================
359 /// @name copy_from
360 // =========================================================================
361 /// @{
362
363 public:
364
365 /// 将 @a source复制到此缓冲区。如果需要,则分配内存。
366 template <typename T>
367 void copy_from(const T &source) {
368 copy_from(0u, source);
369 }
370 // 模板函数,接受一个任意类型T的参数source
371 // 调用copy_from的另一个重载函数,偏移量为0
372
373 /// Copy @a size bytes of the memory pointed by @a data into this buffer.
374 /// Allocates memory if necessary.
376 copy_from(0u, data, size);
377 }
378 // 函数接受一个指向value_type类型的指针data和size_type类型的参数size
379 // 调用copy_from的另一个重载函数,偏移量为0
380
381 /// 将 @a source复制到此缓冲区,在前面留出 @a offset字节未初始化的空间。
382 /// 如果需要,则分配内存。
383 void copy_from(size_type offset, const Buffer &rhs) {
384 copy_from(offset, rhs.buffer());
385 }
386 // 函数接受一个size_type类型的偏移量offset和一个常量Buffer引用rhs
387 // 调用copy_from的另一个重载函数,将rhs转换为缓冲区类型
388
389 /// @copydoc copy_from(size_type, const Buffer &)
390 template <typename T>
391 typename std::enable_if<boost::asio::is_const_buffer_sequence<T>::value>::type
392 copy_from(size_type offset, const T &source) {
393 reset(boost::asio::buffer_size(source) + offset);
394 DEBUG_ASSERT(boost::asio::buffer_size(source) == size() - offset);
395 DEBUG_ONLY(auto bytes_copied = )
396 boost::asio::buffer_copy(buffer() + offset, source);
397 DEBUG_ASSERT(bytes_copied == size() - offset);
398 }
399 // 如果类型T是常量缓冲区序列类型
400 // 先根据source的大小和偏移量重置缓冲区大小
401 // 调试断言source的大小等于缓冲区剩余大小(总大小减去偏移量)
402 // 调试时记录复制的字节数
403 // 调试断言复制的字节数等于缓冲区剩余大小
404
405 /// @copydoc copy_from(size_type, const Buffer &)
406 template <typename T>
407 typename std::enable_if<!boost::asio::is_const_buffer_sequence<T>::value>::type
408 copy_from(size_type offset, const T &source) {
409 copy_from(offset, boost::asio::buffer(source));
410 }
411 // 如果类型T不是常量缓冲区序列类型
412 // 则将source转换为缓冲区类型并调用copy_from的另一个重载函数
413
414#ifdef LIBCARLA_INCLUDED_FROM_UE4
415 /// @copydoc copy_from(size_type, const Buffer &)
416 template <typename T>
417 void copy_from(size_type offset, const TArray<T> &source) {
418 copy_from(
419 offset,
420 reinterpret_cast<const value_type *>(source.GetData()),
421 sizeof(T) * source.Num());
422 }
423#endif // LIBCARLA_INCLUDED_FROM_UE4
424 // 如果是从UE4中包含此库,当类型T是TArray类型时
425 // 根据source的内容和大小调用copy_from的另一个重载函数
426
427 /// 将 @a data指向的内存中的 @a size字节复制到此缓冲区,
428 /// 在前面留出 @a offset字节未初始化的空间。
429 /// 如果需要,则分配内存。
431 copy_from(offset, boost::asio::buffer(data, size));
432 }
433 // 函数接受一个size_type类型的偏移量offset、一个指向value_type类型的指针data和size_type类型的参数size
434 // 将data和size转换为缓冲区类型并调用copy_from的另一个重载函数
435
436 /// @}
437
438 private:
439
440 void ReuseThisBuffer();
441 // 私有函数,用于重新使用此缓冲区资源,具体实现未给出
442
443
444 friend class BufferPool;
445// 声明BufferPool类为友元类,这意味着BufferPool类可以访问Buffer类的私有和保护成员
446
447friend class BufferView;
448// 声明BufferView类为友元类,BufferView类可以访问Buffer类的私有和保护成员
449
450std::weak_ptr<BufferPool> _parent_pool;
451// 定义一个弱智能指针 _parent_pool,类型为指向BufferPool类的智能指针。
452// 用于关联此缓冲区与某个BufferPool(可能是缓冲区的来源池),弱指针不会增加所指向对象的引用计数
453
455// 定义一个size_type类型(前面定义为uint32_t)的成员变量_size,并初始化为0,表示缓冲区当前存储的数据量为0字节
456
458// 定义一个size_type类型的成员变量_capacity,并初始化为0,表示缓冲区当前的容量为0字节
459
460std::unique_ptr<value_type[]> _data = nullptr;
461// 定义一个独占智能指针 _data,指向一个value_type类型(前面定义为unsigned char)的数组。
462// 初始化为nullptr,表示当前没有分配用于存储数据的内存块。
463// 这个指针将用于存储缓冲区中的实际数据内容
464};
465
466} // namespace carla
#define DEBUG_ASSERT(predicate)
Definition Debug.h:68
#define DEBUG_ONLY(code)
Definition Debug.h:55
一个缓冲区池。 从这个池中弹出的缓冲区在销毁时会自动返回到池中, 这样分配的内存可以被重用。
Definition BufferPool.h:29
从现有缓冲区创建一个常量视图
Definition BufferView.h:33
一块原始数据。 请注意,如果需要更多容量,则会分配一个新的内存块,并 删除旧的内存块。这意味着默认情况下,缓冲区只能增长。要释放内存,使用 clear 或 pop。
std::unique_ptr< value_type[]> _data
Buffer & operator=(const Buffer &)=delete
const_iterator begin() const noexcept
const value_type * data() const noexcept
直接访问分配的内存,如果没有分配内存则返回 nullptr。
size_type _size
static constexpr size_type max_size() noexcept
std::enable_if<!boost::asio::is_const_buffer_sequence< T >::value >::type copy_from(size_type offset, const T &source)
将 source复制到此缓冲区,在前面留出 offset字节未初始化的空间。 如果需要,则分配内存。
void reset(size_type size)
重置缓冲区的大小。如果容量不足,当前内存将被丢弃,并分配一个新的大小为 size的内存块。 allocated.
size_type size() const noexcept
const_iterator cend() const noexcept
Buffer()=default
创建一个空的缓冲区。
void copy_from(size_type offset, const Buffer &rhs)
将 source复制到此缓冲区,在前面留出 offset字节未初始化的空间。 如果需要,则分配内存。
std::unique_ptr< value_type[]> pop() noexcept
释放此缓冲区的内容,并将其大小和容量设置为零。
value_type & operator[](size_t i)
Access the byte at position i.
void copy_from(const T &source)
将 source复制到此缓冲区。如果需要,则分配内存。
void resize(uint64_t size)
调整缓冲区的大小。如果容量不足,将分配一个新的大小为 size的内存块,并复制数据。
void ReuseThisBuffer()
boost::asio::const_buffer buffer() const noexcept
从这个缓冲区创建一个boost::asio::buffer。
Buffer(size_type size)
创建一个分配了 size字节的缓冲区。
size_type capacity() const noexcept
uint32_t size_type
size_type _capacity
Buffer & operator=(Buffer &&rhs) noexcept
void copy_from(const value_type *data, size_type size)
Copy size bytes of the memory pointed by data into this buffer.
std::weak_ptr< BufferPool > _parent_pool
boost::asio::mutable_buffer buffer() noexcept
从这个缓冲区创建一个boost::asio::buffer。
std::enable_if< boost::asio::is_const_buffer_sequence< T >::value >::type copy_from(size_type offset, const T &source)
将 source复制到此缓冲区,在前面留出 offset字节未初始化的空间。 如果需要,则分配内存。
bool empty() const noexcept
Buffer(const value_type *data, size_type size)
Buffer(const T &source)
将 source复制到此缓冲区中。分配所需的内存。
const value_type * const_iterator
void copy_from(size_type offset, const value_type *data, size_type size)
将 data指向的内存中的 size字节复制到此缓冲区, 在前面留出 offset字节未初始化的空间。 如果需要,则分配内存。
Buffer(const value_type *data, uint64_t size)
创建一个分配了 size字节的缓冲区。
iterator begin() noexcept
const_iterator cbegin() const noexcept
const_iterator end() const noexcept
value_type * data() noexcept
Direct access to the allocated memory or nullptr if no memory is allocated.
value_type * iterator
Buffer(Buffer &&rhs) noexcept
boost::asio::const_buffer cbuffer() const noexcept
从这个缓冲区创建一个boost::asio::buffer。
void reset(uint64_t size)
重置缓冲区的大小。如果容量不足,当前内存将被丢弃,并分配一个新的大小为 size的内存块。 allocated.
void clear() noexcept
清除此缓冲区的内容,并将其大小和容量设置为零。 删除已分配的内存。
iterator end() noexcept
Buffer(uint64_t size)
创建一个分配了 size字节的缓冲区。
Buffer(const Buffer &)=delete
unsigned char value_type
const value_type & operator[](size_t i) const
访问位置 i处的字节
CARLA模拟器的主命名空间。
Definition Carla.cpp:139
void throw_exception(const std::exception &e)
Definition Carla.cpp:142
static void log_debug(Args &&... args)
Definition Logging.h:71