Files
CPP_Core/Core/Base/SM_RingBuffer.cpp
T
2026-06-16 10:56:40 +08:00

262 lines
8.7 KiB
C++

#include "SM_RingBuffer.h"
#include "Core/spdlog/export.h"
#include "Core/transmit_protocol/Channel_Simulator/global.h"
#include "Core/Base/global_include.h"
namespace Psc {
// 1. used_space 简化:利用无符号溢出特性或 mask
size_t SM_Base_RingBuffer::used_space() const {
// 统一使用 mask 处理回绕,消除 if 判断
return (state->tail - state->head) & mask;
}
// 2. free_space:保持浪费一个字节的策略,确保 tail 永远不会追上 head 导致重合
size_t SM_Base_RingBuffer::free_space() const {
// 逻辑容量是 capacity - 1
return (state->capacity - 1) - used_space();
}
// 3. 判定函数
[[nodiscard]] bool SM_Base_RingBuffer::empty() const {
return state->head == state->tail;
}
[[nodiscard]] bool SM_Base_RingBuffer::full() const {
// 如果 tail 的下一个位置是 head,则为满
return ((state->tail + 1) & mask) == state->head;
}
// 4. rollback 优化:同样使用 mask 替代 %
void SM_Base_RingBuffer::rollback(size_t n) {
// (head - n) 可能产生负数溢出,但在无符号下配合 mask 是正确的
state->head = (state->head - n) & mask;
}
SM_Base_RingBuffer::SM_Base_RingBuffer(const std::string &name, size_t size) {
init(name, size);
}
void SM_Base_RingBuffer::init(const std::string &name, size_t size) {
data_mutex.init(name + "_data_mutex");
create_mutex.init(name + "_create_mutex");
std::lock_guard lock(create_mutex);
// --- 修改点 1: 确保数据区本身是 2 的幂 ---
size_t data_size_pow2 = ceilToPow2(size + 1);
size_t total_alloc_size = sizeof(SharedMemoryState) + data_size_pow2;
bool ok;
std::ostringstream oss;
bool open = check_if_shared_memory_exists(name);
if (open) {
// 注意:打开时也要使用计算出的 total_alloc_size
oss << "【打开共享内存】" << VAR_STR_3(name, total_alloc_size, size) << std::endl;
ok = shm.open(name, total_alloc_size);
create = false;
} else {
oss << "【创建共享内存】" << VAR_STR_3(name, total_alloc_size, size) << std::endl;
ok = shm.create(name, total_alloc_size);
create = true;
}
if (!ok) {
std::cerr << oss.str() << "无法创建或打开共享内存!" << std::endl;
Psc::fail_fast();
}
state = reinterpret_cast<SharedMemoryState *>(shm.data());
uint8_t *raw = shm.data();
if (!open) {
// --- 修改点 2: 直接存储 2 的幂 ---
state->capacity = data_size_pow2;
state->head = 0;
state->tail = 0;
} else {
if (state->capacity == 0 || (state->capacity & mask) != 0) {
std::cerr << "致命错误:共享内存容量非法,必须为 2 的幂!" << std::endl;
Psc::fail_fast();
}
}
// --- 修改点 3: 这里的 mask 赋值必须在获取 state 之后,无论 open 还是 create 都要执行 ---
mask = state->capacity - 1;
buffer = raw + sizeof(SharedMemoryState);
// 打印调试信息
oss.str(""); // 清空
oss << "\t实际分配容量 (2^n): " << state->capacity << std::endl;
oss << "\tMask: " << std::hex << mask << std::dec << std::endl;
std::cout << oss.str();
}
SM_Base_RingBuffer::SM_Base_RingBuffer() = default;
SM_Base_RingBuffer::~SM_Base_RingBuffer() {
// 尤其注意不要删除共享内存删除会导致共享内存很奇怪
shm.close(); // 关闭共享内存
}
std::string SM_Base_RingBuffer::state_str() {
return std::to_string(state->head) + "," + std::to_string(state->tail) + "," + std::to_string(state->capacity);
}
void SM_Base_RingBuffer::write_bytes(const uint8_t *data, size_t len) {
// 计算到缓冲区末尾的距离
size_t end = std::min(len, state->capacity - state->tail);
std::memcpy(buffer + state->tail, data, end);
std::memcpy(buffer, data + end, len - end);
// 优化点:使用 & 代替 %
state->tail = (state->tail + len) & mask;
}
void SM_Base_RingBuffer::read_bytes(uint8_t *data, size_t len) {
size_t end = std::min(len, state->capacity - state->head);
std::memcpy(data, buffer + state->head, end);
std::memcpy(data + end, buffer, len - end);
// 优化点:使用 & 代替 %
state->head = (state->head + len) & mask;
}
void SM_Base_RingBuffer::peek_bytes(uint8_t *data, size_t len) const {
size_t end = std::min(len, state->capacity - state->head);
std::memcpy(data, buffer + state->head, end);
std::memcpy(data + end, buffer, len - end);
// 不更新 state->head
}
bool SM_RingBuffer::write(const uint8_t *src, size_t len) {
std::lock_guard lock(data_mutex);
size_t need = HEADER_SIZE + len;
// 包模式:空间不够直接返回 false,不能拆分写入
if (free_space() < need) return false;
auto header = static_cast<uint32_t>(len);
write_bytes(reinterpret_cast<const uint8_t*>(&header), HEADER_SIZE);
write_bytes(src, len);
return true;
}
bool SM_RingBuffer::read(uint8_t *out, size_t &out_len) {
std::lock_guard lock(data_mutex);
if (empty()) return false;
uint32_t msg_len;
// 1. 尝试读包头
peek_bytes(reinterpret_cast<uint8_t*>(&msg_len), HEADER_SIZE);
// 2. 检查包体是否已全部到达(流中可能只有半个包)
if (used_space() < HEADER_SIZE + msg_len) return false;
// 3. 正式读取
size_t dummy_header_len;
read_bytes(reinterpret_cast<uint8_t*>(&dummy_header_len), HEADER_SIZE); // 移动 head 指针过 Header
read_bytes(out, msg_len); // 读取 Body
out_len = msg_len;
return true;
}
bool SM_Stream_RingBuffer::write(const uint8_t *src, size_t len) {
if (len == 0) return true;
std::lock_guard lock(data_mutex);
if (free_space() < len) return false;
write_bytes(src, len);
return true;
}
bool SM_Stream_RingBuffer::read(uint8_t *out, size_t &out_len) {
if (out_len == 0) return true;
std::lock_guard lock(data_mutex);
if (used_space() < out_len) {
out_len = 0;
return false;
}
read_bytes(out, out_len);
return true;
}
// --- Best Effort 读写:尽可能操作,返回实际处理的字节数 ---
size_t SM_Stream_RingBuffer::write_best_effort(const uint8_t *src, size_t len) {
if (len == 0) return 0;
std::lock_guard lock(data_mutex);
size_t can_write = free_space();
size_t actual_len = std::min(len, can_write);
if (actual_len > 0) {
write_bytes(src, actual_len);
}
return actual_len;
}
size_t SM_Stream_RingBuffer::read_best_effort(uint8_t *out, size_t max_len) {
if (max_len == 0) return 0;
std::lock_guard lock(data_mutex);
size_t can_read = used_space();
size_t actual_len = std::min(max_len, can_read);
if (actual_len > 0) {
read_bytes(out, actual_len);
}
return actual_len;
}
} // namespace Psc
#ifdef _USE_GTEST
#include <gtest/gtest.h>
// TEST(Shared_Memory_Test, Normal_Shared_Memory) {
// std::cout << "共享内存测试开始!" << std::endl;
//
//
// int n = 1000;
// std::thread t1([&]() {
// Psc::SM_RingBuffer sm;
// sm.init("test", 1000);
// int i = 0;
// while (i++ < n) {
// auto size = generate_random_size(15, 20);
// auto data2 = generate_random_string(size);
// auto data = std::to_string(i) + "______123456789____" + data2;
// sm.write((const uint8_t *)data.data(), data.size());
// // std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// }
// });
//
// std::thread t2([&]() {
// Psc::SM_RingBuffer sm;
// sm.init("test", 1000);
// int i = 1;
// while (true) {
// uint8_t buf[4096];
// size_t len;
// auto ok = sm.read(buf, len);
// while (ok) {
// std::cout << VAR_STR_1(len) << std::string((char*)buf, len) << std::endl;
// ok = sm.read(buf, len);
// if (++i == n) break;
// }
// // std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// }
// });
//
// t1.join();
// t2.join();
//
//
// }
#endif