libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
double_buffer.cpp
1#include "double_buffer.hpp"
2
3#include "libxr_mem.hpp"
4
5using namespace LibXR;
6
7// 构造过程委托给 `Init()`,这样直接构造和延迟初始化共用同一套校验路径。
8// Construction is delegated to `Init()` so the same validation path is shared
9// by direct construction and delayed initialization.
10DoubleBuffer::DoubleBuffer(const LibXR::RawData& raw_data) { Init(raw_data); }
11
12// `Reset()` 只清运行时状态,不会解绑两块 backing storage。
13// Reset only clears runtime state. The two backing blocks remain bound.
15{
16 active_ = 0;
17 pending_valid_ = false;
18 active_len_ = 0;
19 pending_len_ = 0;
20}
21
22// `Init()` 一次性校验 backing storage 契约,然后把连续内存永久对半切分。
23// `Init()` validates the backing-storage contract once, then permanently splits
24// the continuous block into two equal halves.
26{
27 constexpr size_t ALIGN = alignof(size_t);
28 const bool EMPTY_STORAGE = (raw_data.addr_ == nullptr) && (raw_data.size_ == 0U);
29
30 ASSERT(EMPTY_STORAGE || (raw_data.addr_ != nullptr));
31
32 if (!EMPTY_STORAGE)
33 {
34 ASSERT(raw_data.size_ > 0U);
35 ASSERT((reinterpret_cast<uintptr_t>(raw_data.addr_) % ALIGN) == 0U);
36 ASSERT((raw_data.size_ % (2U * ALIGN)) == 0U);
37 }
38
39 size_ = raw_data.size_ / 2U;
40 buffer_[0] = static_cast<uint8_t*>(raw_data.addr_);
41 buffer_[1] = EMPTY_STORAGE ? nullptr : (static_cast<uint8_t*>(raw_data.addr_) + size_);
42 Reset();
43}
44
45// `ActiveBuffer()` 只是对已绑定双半块的索引视图访问。
46// Active-buffer lookup is just an indexed view over the bound backing halves.
47uint8_t* DoubleBuffer::ActiveBuffer() const { return buffer_[active_]; }
48
49// `PendingBuffer()` 总是返回当前 active block 的另一半。
50// Pending-buffer lookup always returns the opposite half of the current active
51// block.
52uint8_t* DoubleBuffer::PendingBuffer() const { return buffer_[1 - active_]; }
53
54// 这个接口只提供只读块编号访问,给需要稳定 block 语义的上层状态机使用。
55// Direct block access is intentionally read-only metadata access for higher
56// level state machines that need stable block numbering.
57uint8_t* DoubleBuffer::Buffer(int block) const
58{
59 ASSERT((block == 0) || (block == 1));
60 return buffer_[block];
61}
62
63// 初始化完成后,两半缓冲区的大小始终固定且相等。
64// Each half always has the same fixed size after initialization.
65size_t DoubleBuffer::Size() const { return size_; }
66
67// 只有当生产侧标记 pending 有效后,`Switch()` 才会真正切换 active block。
68// `Switch()` only changes the active block after pending data has been marked
69// valid by the producer side.
71{
72 if (pending_valid_)
73 {
74 active_ ^= 1;
75 pending_valid_ = false;
76 }
77}
78
79// Pending 是否就绪由一个显式有效位表示。
80// Pending readiness is carried by one explicit validity bit.
81bool DoubleBuffer::HasPending() const { return pending_valid_; }
82
83// `FillPending()` 把 payload 拷进非活动半块,并把该半块标记为下次可切换。
84// `FillPending()` copies payload bytes into the non-active half and marks that
85// half ready for the next switch.
86bool DoubleBuffer::FillPending(const uint8_t* data, size_t len)
87{
88 if (pending_valid_ || len > size_)
89 {
90 return false;
91 }
92
94 pending_len_ = len;
95 pending_valid_ = true;
96 return true;
97}
98
99// `FillActive()` 只原地更新当前活动半块,不会触碰 pending 状态簿记。
100// `FillActive()` updates the currently active half in place without touching
101// pending-state bookkeeping.
102bool DoubleBuffer::FillActive(const uint8_t* data, size_t len)
103{
104 if (len > size_)
105 {
106 return false;
107 }
108
110 return true;
111}
112
113// 某些调用方会手动写入字节,因此这里只需要补 state-bit 迁移。
114// Some callers stage bytes manually and only need the state-bit transition.
115void DoubleBuffer::EnablePending() { pending_valid_ = true; }
116
117// 只有当生产侧宣布该半块有效后,pending length 才对外可见。
118// Pending length is only observable after the producer has declared that half
119// valid.
121{
122 return pending_valid_ ? pending_len_ : 0;
123}
DoubleBuffer()=default
默认构造一个未初始化的双缓冲对象 Constructs one uninitialized double buffer object
void Reset()
重置 active/pending 状态,但保留已绑定的 backing storage Resets active/pending state while keeping bound backing ...
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
size_t Size() const
获取每个缓冲区的大小(单位:字节) Gets the size of each buffer in bytes
uint8_t * Buffer(int block) const
获取指定编号缓冲区的指针 Returns the pointer of the specified block
bool FillActive(const uint8_t *data, size_t len)
向当前使用的缓冲区直接写入数据 Fills the active buffer directly
uint8_t * ActiveBuffer() const
获取当前正在使用的缓冲区指针 Returns the currently active buffer
void Init(const LibXR::RawData &raw_data)
绑定连续 backing storage 并重置双缓冲状态 Binds continuous backing storage and resets double-buffer state
uint8_t * PendingBuffer() const
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
size_t GetPendingLength() const
获取 pending 缓冲区中准备好的数据长度 Gets the size of valid data in pending buffer
bool FillPending(const uint8_t *data, size_t len)
向备用缓冲区写入数据(不可重入) Fills the pending buffer with data (non-reentrant)
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14