#include "mix_cc/exception.h" #include #include #include #include #include #include #include #include #include #include #include namespace { // 双缓冲区结构 struct DoubleBufferMaps { std::unordered_map read_map; // 读取用的map std::unordered_map write_map; // 写入用的map // std::atomic swapping{false}; // 交换标志,防止重复交换 // 交换缓冲区 void swap_buffers() { // swapping.store(true, std::memory_order_acquire); std::swap(read_map, write_map); // swapping.store(false, std::memory_order_release); } // 安全获取当前写入map的引用 std::unordered_map &get_write_map() { // 等待交换完成 // while (swapping.load(std::memory_order_acquire)) { // std::this_thread::yield(); // } return write_map; } }; DoubleBufferMaps buffer_maps; // 双缓冲区实例 std::shared_mutex buffer_mutex; // 保护缓冲区交换的互斥锁 } // namespace // 在类外定义并初始化静态成员变量(必须) int GlobaltemSharedMemory::instanceCount = 0; int GlobaltemSharedMemory::get_data_size() { return data_size_; } int GlobaltemSharedMemory::get_instanceCount() { return instanceCount; } GlobaltemSharedMemory::GlobaltemSharedMemory() { ++instanceCount; logger_ = std::make_unique("GlobaltemSharedMemory"); logger_->Debug() << "GlobaltemSharedMemory::GlobaltemSharedMemory()" << endl; } // 获取指定tag点数据 - 无锁读取 double GlobaltemSharedMemory::operator[](std::string tag_name) { // 直接读取前端缓冲区,无需加锁 const auto &read_map = buffer_maps.read_map; auto it = read_map.find(tag_name); if (it != read_map.end()) { return it->second; } return 0.0; // 或者返回默认值 } // 检查tag点是否存在 - 无锁读取 // bool GlobaltemSharedMemory::find_tag(std::string tag_name) { // const auto& read_map = buffer_maps.read_map; // return (read_map.find(tag_name) != read_map.end()); // } // 从共享内存缓存数据到写入缓冲区 int GlobaltemSharedMemory::cache_data() { try { // 获取写入缓冲区的引用 auto &write_map = buffer_maps.get_write_map(); // 清空写入缓冲区,准备新数据 // write_map.clear(); // 为共享内存中的数据添加机组号前缀 const auto prefix = string(CMemVar::Const()->UnitNo) + "_"; for (int i = CMemVar::Const()->event_eis_start; i <= CMemVar::Const()->event_eis_end; i++) { if (true) { if (m_mapfix.find(i) == m_mapfix.end()) { m_mapfix.insert( make_pair(i, new CMemFix(std::to_string(i)))); } PLC_DATA *pdata = m_mapfix[i]->getCur(); if (pdata == nullptr) { return -1 * i; } binary_tele.ReBuild(i, (char *)(pdata)); const auto size = binary_tele.size(); for (int j = 0; j < size; j++) { float value = binary_tele[j]; std::string name_without_plant_code = binary_tele[j].item; // 添加前缀 auto item_name = prefix + name_without_plant_code; write_map[item_name] = value; } } } // 数据准备完成,交换缓冲区 { std::unique_lock lock(buffer_mutex); buffer_maps.swap_buffers(); } data_size_ = buffer_maps.read_map.size(); // logger_->Debug() << "缓冲区交换完成,读取缓冲区大小: " // << buffer_maps.read_map.size() << endl; } catch (const std::exception &e) { std::throw_with_nested( mix_cc::Exception(-1, "shared mem load error", BOOST_CURRENT_LOCATION)); } return 0; } //获取数据JSON表示 - 无锁读取 std::string GlobaltemSharedMemory::get_data_json() { mix_cc::json js1; try { const auto &read_map = buffer_maps.read_map; if (!read_map.empty()) { js1 = read_map; return js1.dump(); } else { return "empty"; } } catch (std::exception &e) { return "ERROR"; } } // 获取缓冲区状态信息(调试用) // std::string GlobaltemSharedMemory::get_buffer_status() { // mix_cc::json status; // status["read_buffer_size"] = buffer_maps.read_map.size(); // status["write_buffer_size"] = buffer_maps.write_map.size(); // status["is_swapping"] = buffer_maps.swapping.load(); // return status.dump(); // } // // 线程安全的单个数据更新(如果需要实时更新单个值) // void GlobaltemSharedMemory::update_single_value(const std::string& tag_name, // double value) { // // 获取写入缓冲区的引用 // auto& write_map = buffer_maps.get_write_map(); // // 更新写入缓冲区 // write_map[tag_name] = value; // // 可以选择立即交换或者等待批量更新 // // 对于实时性要求高的场景,可以在这里调用交换 // } // // 手动触发缓冲区交换(用于特殊场景) // void GlobaltemSharedMemory::manual_swap_buffers() { // std::unique_lock lock(buffer_mutex); // buffer_maps.swap_buffers(); // logger_->Debug() << "手动交换缓冲区完成" << endl; // }