eis/eqpalg/gb_item_memory.cc

146 lines
4.3 KiB
C++

#include <eqpalg/gb_item_memory.h>
#include <eqpalg/table_struct/t_rule_cfg.h>
#include <mix_cc/sql.h>
#include <mix_cc/sql/database/db2_t.h>
#include <array>
#include <atomic>
#include <chrono>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <tuple>
#include <vector>
#include "mix_cc/exception.h"
namespace {
// 双缓冲区结构
const size_t ArrayMax = 10000;
struct DoubleBufferArrays {
std::vector<double> read_array; // 读取用的数组
std::vector<double> write_array; // 写入用的数组
void resize(size_t size) {
read_array.resize(size);
write_array.resize(size);
}
// 交换缓冲区
void swap_buffers() { std::swap(read_array, write_array); }
// 安全获取当前写入map的引用
std::vector<double>& get_write_array() { return write_array; }
};
bool data_updated = false;
DoubleBufferArrays buffer_arrays;
std::unordered_map<std::string, size_t> index_map;
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;
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<LOG>("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<PLC_DATA>(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<std::shared_mutex> 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";
}
}