libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
double_buffer.cpp
1#include "double_buffer.hpp"
2
3#include "libxr_mem.hpp"
4
5using namespace LibXR;
6
7// Construction is delegated to `Init()` so the same validation path is shared
8// by direct construction and delayed initialization.
9// 构造过程委托给 `Init()`,这样直接构造和延迟初始化共用同一套校验路径。
10DoubleBuffer::DoubleBuffer(const LibXR::RawData& raw_data) { Init(raw_data); }
11
12// Reset only clears runtime state. The two backing blocks remain bound.
13// `Reset()` 只清运行时状态,不会解绑两块 backing storage。
15{
16 active_ = 0;
17 pending_valid_ = false;
18 active_len_ = 0;
19 pending_len_ = 0;
20}
21
22// `Init()` validates the backing-storage contract once, then permanently splits
23// the continuous block into two equal halves.
24// `Init()` 一次性校验 backing storage 契约,然后把连续内存永久对半切分。
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// Active-buffer lookup is just an indexed view over the bound backing halves.
46// `ActiveBuffer()` 只是对已绑定双半块的索引视图访问。
47uint8_t* DoubleBuffer::ActiveBuffer() const { return buffer_[active_]; }
48
49// Pending-buffer lookup always returns the opposite half of the current active
50// block.
51// `PendingBuffer()` 总是返回当前 active block 的另一半。
52uint8_t* DoubleBuffer::PendingBuffer() const { return buffer_[1 - active_]; }
53
54// Direct block access is intentionally read-only metadata access for higher
55// level state machines that need stable block numbering.
56// 这个接口只提供只读块编号访问,给需要稳定 block 语义的上层状态机使用。
57uint8_t* DoubleBuffer::Buffer(int block) const
58{
59 ASSERT((block == 0) || (block == 1));
60 return buffer_[block];
61}
62
63// Each half always has the same fixed size after initialization.
64// 初始化完成后,两半缓冲区的大小始终固定且相等。
65size_t DoubleBuffer::Size() const { return size_; }
66
67// `Switch()` only changes the active block after pending data has been marked
68// valid by the producer side.
69// 只有当生产侧标记 pending 有效后,`Switch()` 才会真正切换 active block。
71{
73 {
74 active_ ^= 1;
75 pending_valid_ = false;
76 }
77}
78
79// Pending readiness is carried by one explicit validity bit.
80// Pending 是否就绪由一个显式有效位表示。
82
83// `FillPending()` copies payload bytes into the non-active half and marks that
84// half ready for the next switch.
85// `FillPending()` 把 payload 拷进非活动半块,并把该半块标记为下次可切换。
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()` updates the currently active half in place without touching
100// pending-state bookkeeping.
101// `FillActive()` 只原地更新当前活动半块,不会触碰 pending 状态簿记。
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// Some callers stage bytes manually and only need the state-bit transition.
114// 某些调用方会手动写入字节,因此这里只需要补 state-bit 迁移。
116
117// Pending length is only observable after the producer has declared that half
118// valid.
119// 只有当生产侧宣布该半块有效后,pending length 才对外可见。
121{
122 return pending_valid_ ? pending_len_ : 0;
123}
int active_
当前活动缓冲区编号 / Index of active buffer
size_t active_len_
当前活动缓冲区有效数据长度 / Length of active data
DoubleBuffer()=default
默认构造一个未初始化的双缓冲对象 Constructs one uninitialized double buffer object
void Reset()
重置 active/pending 状态,但保留已绑定的 backing storage Resets active/pending state while keeping bound backing ...
size_t size_
单个缓冲区大小 / Size of each buffer
bool pending_valid_
标记备用区是否准备好 / Whether pending buffer is ready
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
size_t pending_len_
备用缓冲区有效数据长度 / Length of pending data
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
uint8_t * buffer_[2]
双缓冲区指针 / Double buffer pointers
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 命名空间
Definition ch32_can.hpp:14