#include #include #include #include #include #include #include #include #include #include #include #include #include "mix_cc/exception.h" namespace { // 双缓冲区结构 const size_t ArrayMax = 10000; struct DoubleBufferArrays { std::vector read_array; // 读取用的数组 std::vector write_array; // 写入用的数组 void resize(size_t size) { read_array.resize(size); write_array.resize(size); } void swap_buffers() { std::swap(read_array, write_array); } std::vector& get_write_array() { return write_array; } }; bool data_updated = false; DoubleBufferArrays buffer_arrays; std::unordered_map index_map; std::shared_mutex buffer_mutex; // 保护缓冲区交换的互斥锁 } // 在类外定义并初始化静态成员变量(必须) int GlobaltemSharedMemory::instanceCount = 0; int GlobaltemSharedMemory::get_data_size() { return data_size_; } int GlobaltemSharedMemory::get_instanceCount() { return instanceCount; } GlobaltemSharedMemory::GlobaltemSharedMemory() { ++instanceCount; size_t index_value = 0; const auto prefix = string(CMemVar::Const()->UnitNo) + "_"; for (int i = CMemVar::Const()->event_eis_start; i <= CMemVar::Const()->event_eis_end; i++) { binary_tele.ReBuild(i); const auto size = binary_tele.size(); for (int j = 0; j < size; j++) { std::string name_without_plant_code = binary_tele[j].item; // 添加前缀 auto item_name = prefix + name_without_plant_code; index_map[item_name] = index_value; index_value++; } } // 2. 初始化数组大小 buffer_arrays.resize(index_value); logger_ = std::make_unique("GlobaltemSharedMemory"); logger_->Debug() << "GlobaltemSharedMemory::GlobaltemSharedMemory(),MaxIndex:" << index_value << endl; } // 获取指定tag点数据 - 无锁读取 double GlobaltemSharedMemory::operator[](std::string tag_name) { // 直接读取前端缓冲区,无需加锁 if (!data_updated) { return 0.0; } const auto& read_array = buffer_arrays.read_array; auto it = index_map.find(tag_name); if (it != index_map.end()) { size_t index_value = it->second; return index_value < data_size_ ? read_array[index_value] : 0; } return 0.0; } // 从共享内存缓存数据到写入缓冲区 int GlobaltemSharedMemory::cache_data() { try { auto& write_array = buffer_arrays.get_write_array(); // 为共享内存中的数据添加机组号前缀 size_t index_value = 0; 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]; write_array[index_value] = value; index_value++; } } } // 数据准备完成,交换缓冲区 { std::unique_lock lock(buffer_mutex); buffer_arrays.swap_buffers(); data_updated = true; } data_size_ = index_value; } 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_array = buffer_arrays.read_array; if (!index_map.empty()) { for (auto iter : index_map) { size_t index_value = iter.second; js1[iter.first] = index_value < data_size_ ? read_array[index_value] : 0; } return js1.dump(); } else { return "empty"; } } catch (std::exception& e) { return "ERROR"; } }