221 lines
5.3 KiB
C++
221 lines
5.3 KiB
C++
|
|
/************************************************
|
||
|
|
* 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 <tuple>
|
||
|
|
#include <typeinfo>
|
||
|
|
|
||
|
|
const short KEY_LEN = 48;
|
||
|
|
// TValue requires a fixed length structure
|
||
|
|
template <typename TKey, typename TValue> class CMemMap {
|
||
|
|
typedef struct {
|
||
|
|
unsigned int maxsize;
|
||
|
|
unsigned int size;
|
||
|
|
unsigned int next;
|
||
|
|
} HEAD;
|
||
|
|
typedef struct {
|
||
|
|
char key[KEY_LEN];
|
||
|
|
TValue value;
|
||
|
|
} SM_DAT;
|
||
|
|
|
||
|
|
private:
|
||
|
|
std::tuple<string, unsigned int> mt_lastkey;
|
||
|
|
|
||
|
|
private:
|
||
|
|
HEAD *p_head;
|
||
|
|
SM_DAT *p_ptr;
|
||
|
|
|
||
|
|
private:
|
||
|
|
std::mutex m_mutex;
|
||
|
|
|
||
|
|
private:
|
||
|
|
// std::string toString(const TKey &key) {
|
||
|
|
// std::ostringstream ostream;
|
||
|
|
// ostream.unsetf(std::ios::skipws);
|
||
|
|
// ostream << key;
|
||
|
|
// if (typeid(TKey) == typeid(string)) {
|
||
|
|
// return ostream.str();
|
||
|
|
// }
|
||
|
|
// std::istringstream istream(ostream.str());
|
||
|
|
// std::string value;
|
||
|
|
// istream >> value;
|
||
|
|
// return value;
|
||
|
|
// }
|
||
|
|
std::string toString(const TKey &key) const {
|
||
|
|
return toStringImpl(key, std::is_same<TKey, std::string>());
|
||
|
|
}
|
||
|
|
|
||
|
|
void init(const string &tableName) {
|
||
|
|
char *ptr = (char *)GlobMem::GetInstancePtr()->GetTablePtr(tableName);
|
||
|
|
if (ptr == nullptr) {
|
||
|
|
p_ptr = nullptr;
|
||
|
|
p_head = nullptr;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
p_head = (HEAD *)(ptr);
|
||
|
|
p_ptr = (SM_DAT *)(ptr + sizeof(HEAD));
|
||
|
|
};
|
||
|
|
|
||
|
|
public:
|
||
|
|
// size does not need to be map get
|
||
|
|
CMemMap(const string &tableName) {
|
||
|
|
this->init(tableName);
|
||
|
|
// assert(p_head->maxsize>1);
|
||
|
|
};
|
||
|
|
|
||
|
|
// map insert need set cache maxsize
|
||
|
|
CMemMap(const string &tableName, unsigned int maxsize) {
|
||
|
|
// assert(maxsize>1);
|
||
|
|
this->init(tableName);
|
||
|
|
|
||
|
|
p_head->maxsize = maxsize;
|
||
|
|
if (p_head->size > p_head->maxsize) {
|
||
|
|
p_head->size = p_head->maxsize;
|
||
|
|
}
|
||
|
|
|
||
|
|
m_mutex.lock();
|
||
|
|
if (p_head->next > p_head->maxsize) {
|
||
|
|
p_head->next = p_head->maxsize;
|
||
|
|
}
|
||
|
|
p_head->next = p_head->next % p_head->maxsize;
|
||
|
|
m_mutex.unlock();
|
||
|
|
};
|
||
|
|
|
||
|
|
~CMemMap(){};
|
||
|
|
|
||
|
|
TValue *operator()(void) { return &p_ptr->value; };
|
||
|
|
|
||
|
|
TValue *getCur(void) { return &(p_ptr + this->index_cur())->value; };
|
||
|
|
|
||
|
|
long index_cur(void) {
|
||
|
|
if (p_head->next <= 0) {
|
||
|
|
return p_head->maxsize - 1;
|
||
|
|
} else {
|
||
|
|
return (p_head->next - 1) % p_head->maxsize;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
TValue *operator()(unsigned int i) {
|
||
|
|
if (p_ptr == nullptr)
|
||
|
|
return nullptr;
|
||
|
|
return &(p_ptr + i)->value;
|
||
|
|
};
|
||
|
|
|
||
|
|
string getKey(unsigned int i) {
|
||
|
|
if (p_ptr == nullptr)
|
||
|
|
return nullptr;
|
||
|
|
return (p_ptr + i)->key;
|
||
|
|
};
|
||
|
|
|
||
|
|
bool find(const TKey &tkey) {
|
||
|
|
string key = this->toString(tkey);
|
||
|
|
if (key == "")
|
||
|
|
return nullptr;
|
||
|
|
if (p_ptr == nullptr)
|
||
|
|
return nullptr;
|
||
|
|
|
||
|
|
if (std::get<0>(this->mt_lastkey) == key) {
|
||
|
|
return &(p_ptr + std::get<1>(this->mt_lastkey))->value;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < this->size(); i++) {
|
||
|
|
if (memcmp((p_ptr + i)->key, key.c_str(), key.length()) == 0 &&
|
||
|
|
key.length() < KEY_LEN && strlen((p_ptr + i)->key) == key.length()) {
|
||
|
|
this->mt_lastkey = std::make_tuple(key, i);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
|
||
|
|
TValue *operator[](const TKey &tkey) {
|
||
|
|
string key = this->toString(tkey);
|
||
|
|
if (key == "")
|
||
|
|
return nullptr;
|
||
|
|
if (p_ptr == nullptr)
|
||
|
|
return nullptr;
|
||
|
|
|
||
|
|
if (std::get<0>(this->mt_lastkey) == key) {
|
||
|
|
return &(p_ptr + std::get<1>(this->mt_lastkey))->value;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (unsigned int i = 0; i < this->size(); i++) {
|
||
|
|
if (memcmp((p_ptr + i)->key, key.c_str(), key.length()) == 0 &&
|
||
|
|
key.length() < KEY_LEN && strlen((p_ptr + i)->key) == key.length()) {
|
||
|
|
this->mt_lastkey = std::make_tuple(key, i);
|
||
|
|
return &(p_ptr + i)->value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nullptr;
|
||
|
|
};
|
||
|
|
|
||
|
|
void insert(const TKey &tkey, TValue *tvalue) {
|
||
|
|
string key = this->toString(tkey);
|
||
|
|
if (key == "")
|
||
|
|
return;
|
||
|
|
if (p_ptr == nullptr)
|
||
|
|
return;
|
||
|
|
|
||
|
|
m_mutex.lock();
|
||
|
|
TValue *tmp = this->operator[](tkey);
|
||
|
|
if (tmp != nullptr) {
|
||
|
|
memcpy(tmp, tvalue, sizeof(TValue));
|
||
|
|
} else {
|
||
|
|
if (p_head->size < p_head->maxsize) {
|
||
|
|
p_head->size++;
|
||
|
|
}
|
||
|
|
|
||
|
|
this->mt_lastkey = std::make_tuple(key, p_head->next);
|
||
|
|
memcpy(&(p_ptr + p_head->next)->value, tvalue, sizeof(TValue));
|
||
|
|
memset(&(p_ptr + p_head->next)->key, 0, sizeof(p_ptr->key));
|
||
|
|
int len = min(key.length(), sizeof(p_ptr->key));
|
||
|
|
memcpy(&(p_ptr + p_head->next)->key, key.c_str(), len);
|
||
|
|
p_head->next = (p_head->next + 1) % p_head->maxsize;
|
||
|
|
}
|
||
|
|
m_mutex.unlock();
|
||
|
|
};
|
||
|
|
|
||
|
|
bool empty(void) {
|
||
|
|
if (p_head == nullptr)
|
||
|
|
return 0;
|
||
|
|
return !p_head->size;
|
||
|
|
};
|
||
|
|
|
||
|
|
unsigned int size(void) {
|
||
|
|
if (p_head == nullptr)
|
||
|
|
return 0;
|
||
|
|
return p_head->size;
|
||
|
|
};
|
||
|
|
|
||
|
|
void clear(void) {
|
||
|
|
if (p_head == nullptr)
|
||
|
|
return;
|
||
|
|
p_head->size = 0;
|
||
|
|
p_head->next = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
private:
|
||
|
|
// 通用实现
|
||
|
|
std::string toStringImpl(const TKey &key, std::false_type) const {
|
||
|
|
std::ostringstream oss;
|
||
|
|
oss << key;
|
||
|
|
return oss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
// string特化实现
|
||
|
|
std::string toStringImpl(const std::string &key, std::true_type) const {
|
||
|
|
return key;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|