我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
所有基础功能都集中在这个模板类里面:创建、连接、文件导入导出、基于索引的定位、自动增长,多种存储结构(如二叉树、字符串池、按key分组、链表等)则由子类实现,子类无需关注共享内存的底层实现。
一、定义模板T_ARRAY
template<typename T, int PI_N, typename T_USER_HEAD, int PART = 0, typename T_HANDLE = T_HANDLE_ARRAY<T, PI_N > >
class T_ARRAY : public IShmActiveObject
{
//子类型
public:
typedef T_HANDLE HANDLE;
typedef T value_type;
public:
//旧版数组头
struct array_head_old
{
CMeta meta;
sstring<32> name;
T_SHM_SIZE capacity;
T_SHM_SIZE size;
T_USER_HEAD userhead;
struct_T_ARRAY_VMAP_S vmaps;//分块影射表
long ____;//用来确保array_head用8字节对齐
};
//新版数组头
struct array_head_new
{
CMeta meta;
sstring<64> name;
T_SHM_SIZE capacity;
T_SHM_SIZE size;
struct_T_ARRAY_VMAP_S vmaps;//分块影射表
long ____;//用来确保array_head用8字节对齐
T_USER_HEAD userhead;
};
//当前使用的数组头
typedef array_head_new array_head;
private:
array_head* pHead;
T* pData;
bool isPrivate;
bool m_isReadOnly;
int shmid;
string name;
long version;
。。。。。
模板的使用相当的晦涩,不过编写模板有一个技巧:先按照类来写,然后把某个类型改为模板参数。
目前可以把这个模板的参数用上一篇介绍的类直接代替。user_data是用户提供的头结构,不用关心,handle就是之前介绍的T_HANDLE_ARRAY(5、在共享内存无指针编程:句柄HANDLE转换为指针-CSDN博客)。
二、区分多个共享内存对象
这个模板最关键的参数是PI_N和PART,这两个的组合唯一确定一个共享内存对象(一组共享内存块构成的虚拟的连续数组结构)。PART用来分组,一般用hash方法映射,每个分块可以单独互斥,从而可以通过多进程、多线程来提高并发速度(互斥控制由子类的互斥层实现)。
T是用户的数据结构,对于理解这个模板类是无关紧要的。
三、指向共享内存
两个指针指向共享内存,pHead指向头结构,头位于第一个块起始处,pData则指向第一个数据,紧随头结构的结束处。pData可能用处不大,因为主要是通过handle来操作的(而handle是通过映射表来定位的),为什么保留这个pData呢?可能是遗留问题。
已经强调过,一定要清楚哪些数据是放在共享内存的、哪些是放在私有内存的。
这个模板本身是放在私有内存的,通过指针访问共享内存。其余几个变量都是私有内存的,提供了操作时需要的参数,比如连接时要比对名字和版本,防止破坏数据。
其余几个私有变量比较显而易见。m_isReadOnly控制是否以只读方式连接。
里面定义了两个头结构,因为后来改过了,但是又要兼容旧的。
(待续)