eis/TestProject/play_gruond/ipc_test.h

407 lines
12 KiB
C
Raw Permalink Normal View History

/************************************************
* Fixed element pointer position.
* The current pointer points to the latest element
* by means of a primary key value
*
* create zoufuzhou 20201001
* modify zoufuzhou 20251024 Initializable key memory
*
************************************************/
#ifndef _MEM_MAP_CACHE_HPP_
#define _MEM_MAP_CACHE_HPP_
#include <glob/GlobMem.h>
#include <mutex>
#include <shared_mutex>
#include <tuple>
#include <typeinfo>
#include <unordered_map>
#include <string_view>
#include <cstring>
#include <array>
const short KEY_LEN = 48;
template <typename TKey, typename TValue>
class CMemMap {
private:
// 使用固定大小的数组替代动态字符串
struct FixedKey {
char data[KEY_LEN];
FixedKey() {
std::memset(data, 0, KEY_LEN);
}
FixedKey(const std::string_view& str) {
std::memset(data, 0, KEY_LEN);
if (!str.empty()) {
size_t copy_len = std::min(str.size(), static_cast<size_t>(KEY_LEN - 1));
std::memcpy(data, str.data(), copy_len);
}
}
bool operator==(const FixedKey& other) const {
return std::memcmp(data, other.data, KEY_LEN) == 0;
}
bool operator==(const std::string_view& str) const {
if (str.size() >= KEY_LEN) return false;
return std::memcmp(data, str.data(), str.size()) == 0 &&
(str.size() == KEY_LEN - 1 || data[str.size()] == 0);
}
std::string_view toStringView() const {
return std::string_view(data, std::strlen(data));
}
struct Hasher {
std::size_t operator()(const FixedKey& key) const {
// 简单的哈希函数,针对固定长度数组优化
std::size_t hash = 5381;
for (size_t i = 0; i < KEY_LEN && key.data[i] != 0; ++i) {
hash = ((hash << 5) + hash) + key.data[i];
}
return hash;
}
};
};
typedef struct {
unsigned int maxsize;
unsigned int size;
unsigned int next;
} HEAD;
typedef struct {
FixedKey key; // 使用 FixedKey 替代 char[KEY_LEN]
TValue value;
} SM_DAT;
private:
HEAD* p_head = nullptr;
SM_DAT* p_ptr = nullptr;
// 使用共享锁提高读性能
mutable std::shared_mutex m_data_mutex;
// 使用 unordered_map 加速查找
std::unordered_map<FixedKey, unsigned int, FixedKey::Hasher> m_key_index;
mutable std::shared_mutex m_index_mutex;
// 线程本地缓存
struct ThreadCache {
FixedKey key;
unsigned int index = 0;
bool valid = false;
};
static thread_local ThreadCache s_thread_cache;
// 字符串转换优化
template<typename U = TKey>
typename std::enable_if<!std::is_same<U, std::string>::value, FixedKey>::type
toFixedKey(const TKey& tkey) const {
std::ostringstream oss;
oss << tkey;
return FixedKey(oss.str());
}
template<typename U = TKey>
typename std::enable_if<std::is_same<U, std::string>::value, FixedKey>::type
toFixedKey(const TKey& tkey) const {
return FixedKey(tkey);
}
// 初始化哈希索引
void buildIndex() {
std::unique_lock<std::shared_mutex> lock(m_index_mutex);
m_key_index.clear();
if (!p_ptr) return;
for (unsigned int i = 0; i < p_head->size; ++i) {
m_key_index[p_ptr[i].key] = i;
}
}
// 查找优化版本
int findIndexOptimized(const FixedKey& key) {
// 1. 检查线程本地缓存
if (s_thread_cache.valid && s_thread_cache.key == key) {
return static_cast<int>(s_thread_cache.index);
}
// 2. 在哈希表中查找
{
std::shared_lock<std::shared_mutex> lock(m_index_mutex);
auto it = m_key_index.find(key);
if (it != m_key_index.end()) {
s_thread_cache.key = key;
s_thread_cache.index = it->second;
s_thread_cache.valid = true;
return static_cast<int>(it->second);
}
}
return -1;
}
// 回退到线性查找
int findIndexFallback(const FixedKey& key) {
for (unsigned int i = 0; i < p_head->size; ++i) {
if (p_ptr[i].key == key) {
// 更新索引
{
std::unique_lock<std::shared_mutex> lock(m_index_mutex);
m_key_index[key] = i;
}
s_thread_cache.key = key;
s_thread_cache.index = i;
s_thread_cache.valid = true;
return static_cast<int>(i);
}
}
return -1;
}
void init(const std::string& tableName) {
char* ptr = static_cast<char*>(GlobMem::GetInstancePtr()->GetTablePtr(tableName));
if (ptr == nullptr) {
p_ptr = nullptr;
p_head = nullptr;
return;
}
p_head = reinterpret_cast<HEAD*>(ptr);
p_ptr = reinterpret_cast<SM_DAT*>(ptr + sizeof(HEAD));
// 构建索引
buildIndex();
}
public:
CMemMap(const std::string& tableName) {
this->init(tableName);
}
CMemMap(const std::string& tableName, unsigned int maxsize) {
this->init(tableName);
if (p_head) {
p_head->maxsize = maxsize;
if (p_head->size > p_head->maxsize) {
p_head->size = p_head->maxsize;
}
{
std::unique_lock<std::shared_mutex> lock(m_data_mutex);
if (p_head->next >= p_head->maxsize) {
p_head->next = p_head->maxsize;
}
p_head->next = p_head->next % p_head->maxsize;
}
// 重建索引
buildIndex();
}
}
~CMemMap() = default;
// 禁用复制
CMemMap(const CMemMap&) = delete;
CMemMap& operator=(const CMemMap&) = delete;
// 移动语义
CMemMap(CMemMap&& other) noexcept
: p_head(other.p_head)
, p_ptr(other.p_ptr)
, m_key_index(std::move(other.m_key_index)) {
other.p_head = nullptr;
other.p_ptr = nullptr;
}
CMemMap& operator=(CMemMap&& other) noexcept {
if (this != &other) {
p_head = other.p_head;
p_ptr = other.p_ptr;
m_key_index = std::move(other.m_key_index);
other.p_head = nullptr;
other.p_ptr = nullptr;
}
return *this;
}
// 查找键是否存在
bool find(const TKey& tkey) {
FixedKey key = toFixedKey(tkey);
if (!p_ptr) return false;
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
int idx = findIndexOptimized(key);
if (idx >= 0) return true;
// 哈希表中未找到,尝试线性查找
idx = findIndexFallback(key);
return idx >= 0;
}
// 通过键获取值
TValue* operator[](const TKey& tkey) {
FixedKey key = toFixedKey(tkey);
if (!p_ptr) return nullptr;
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
int idx = findIndexOptimized(key);
if (idx < 0) {
idx = findIndexFallback(key);
}
if (idx >= 0) {
return &p_ptr[idx].value;
}
return nullptr;
}
// 插入键值对
bool insert(const TKey& tkey, const TValue& tvalue) {
FixedKey key = toFixedKey(tkey);
if (!p_ptr) return false;
std::unique_lock<std::shared_mutex> lock(m_data_mutex);
// 查找键是否存在
int idx = findIndexOptimized(key);
if (idx < 0) {
idx = findIndexFallback(key);
}
if (idx >= 0) {
// 更新现有值
p_ptr[idx].value = tvalue;
// 更新线程缓存
s_thread_cache.key = key;
s_thread_cache.index = static_cast<unsigned int>(idx);
s_thread_cache.valid = true;
return true;
}
// 键不存在,需要插入
if (p_head->size >= p_head->maxsize) {
// 缓存已满,需要替换
unsigned int replace_index = p_head->next;
// 从哈希表中移除旧键
{
std::unique_lock<std::shared_mutex> index_lock(m_index_mutex);
m_key_index.erase(p_ptr[replace_index].key);
}
// 清除线程缓存
if (s_thread_cache.valid && s_thread_cache.index == replace_index) {
s_thread_cache.valid = false;
}
} else {
p_head->size++;
}
// 执行插入
unsigned int insert_index = p_head->next;
// 复制键值
p_ptr[insert_index].key = key;
p_ptr[insert_index].value = tvalue;
// 更新元数据
p_head->next = (p_head->next + 1) % p_head->maxsize;
// 更新哈希表
{
std::unique_lock<std::shared_mutex> index_lock(m_index_mutex);
m_key_index[key] = insert_index;
}
// 更新线程缓存
s_thread_cache.key = key;
s_thread_cache.index = insert_index;
s_thread_cache.valid = true;
return true;
}
// 指针版本
bool insert(const TKey& tkey, const TValue* tvalue) {
if (!tvalue) return false;
return insert(tkey, *tvalue);
}
// 其他接口保持不变,但使用数组下标语法提高性能
TValue* getCur(void) {
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
if (!p_ptr) return nullptr;
long idx = index_cur();
if (idx < 0) return nullptr;
return &p_ptr[idx].value;
}
long index_cur(void) const {
if (!p_head || p_head->maxsize == 0) return -1;
if (p_head->next == 0) {
return static_cast<long>(p_head->maxsize - 1);
} else {
return static_cast<long>((p_head->next - 1) % p_head->maxsize);
}
}
TValue* operator()(unsigned int i) {
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
if (!p_ptr || i >= p_head->size) return nullptr;
return &p_ptr[i].value;
}
std::string getKey(unsigned int i) {
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
if (!p_ptr || i >= p_head->size) return "";
return std::string(p_ptr[i].key.data);
}
bool empty(void) const {
if (!p_head) return true;
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
return p_head->size == 0;
}
unsigned int size(void) const {
if (!p_head) return 0;
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
return p_head->size;
}
void clear(void) {
if (!p_head) return;
std::unique_lock<std::shared_mutex> data_lock(m_data_mutex);
std::unique_lock<std::shared_mutex> index_lock(m_index_mutex);
p_head->size = 0;
p_head->next = 0;
m_key_index.clear();
s_thread_cache.valid = false;
}
// 批量操作优化
template<typename Func>
void forEach(Func func) {
std::shared_lock<std::shared_mutex> lock(m_data_mutex);
for (unsigned int i = 0; i < p_head->size; ++i) {
func(p_ptr[i].key.toStringView(), p_ptr[i].value);
}
}
};
// 初始化线程本地缓存
template<typename TKey, typename TValue>
thread_local typename CMemMap<TKey, TValue>::ThreadCache
CMemMap<TKey, TValue>::s_thread_cache;
#endif