#include "SM_RingBuffer.h" #include "Core/Base/global_include.h" #include "Core/spdlog/export.h" #include "Core/transmit_protocol/Channel_Simulator/global.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(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(len); write_bytes(reinterpret_cast(&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(&msg_len), HEADER_SIZE); // 2. 检查包体是否已全部到达(流中可能只有半个包) if (used_space() < HEADER_SIZE + msg_len) return false; // 3. 正式读取 size_t dummy_header_len; read_bytes(reinterpret_cast(&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 // 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