做家教网站资质,太原专业网站制作,网站框架有哪些,wordpress 父类 id初级代码游戏的专栏介绍与文章目录-CSDN博客
我的github#xff1a;codetoys#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C的#xff0c;可以在任何平台上使用。 共享内存里面不能用指针#…初级代码游戏的专栏介绍与文章目录-CSDN博客
我的githubcodetoys所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C的可以在任何平台上使用。 共享内存里面不能用指针只能用索引在windows上经常称之为句柄当然实际上句柄也并非索引而是个抽象ID我在这个系统里使用HANDLE这个名字因为我是windows出身。 但是我们真的要无指针编程吗那还要什么?
目录
一、索引如何转换为指针
二、句柄结构
三、代码解读 一、索引如何转换为指针 没有指针当然是很困难的不过我们是C啊我们可以把索引包装得跟指针差不多。 但是索引只有一个整数偏移量而转为指针必须知道起始地址怎么传递起始地址增加参数还能当指针使用吗这要怎么搞呢 但是我们是共享内存呀共享内存是公共资源不可能随意创建系统内的共享内存都是被管理的我们只需要给每个共享内存一个唯一的名字用全局变量保存其起始地址那么就可以把索引转换为指针而不需要额外的参数了。这算是一个花招吧 前面介绍共享内存管理接口的时候提到了共享内存的名字除了名字还有一个PI指针索引每个共享内存块都有预定义的唯一的名字和索引另外有一个全局数组存储共享内存入口地址。
二、句柄结构 templatetypename T, int PI_N struct T_HANDLE_ARRAY{T_SHM_SIZE handle;T_HANDLE_ARRAY(T_SHM_SIZE h -1) :handle(h) {}T_HANDLE_ARRAY(T_HANDLE_ARRAY const tmp) :handle(tmp.handle) {}typedef random_access_iterator_tag iterator_category;typedef T* pointer;typedef T element_type;typedef T value_type;typedef long difference_type;typedef long offset_type;typedef T reference;bool operator(T_HANDLE_ARRAY const tmp)const { return handle tmp.handle; }T_HANDLE_ARRAY operator (long n)const{T_HANDLE_ARRAY tmp;tmp.handle handle n;return tmp;}T_HANDLE_ARRAY operator - (long n)const{T_HANDLE_ARRAY tmp;tmp.handle handle - n;return tmp;}T_SHM_SIZE operator - (T_HANDLE_ARRAY const tmp)const { return handle - tmp.handle; }T_HANDLE_ARRAY operator (T_SHM_SIZE n) { handle n; return *this; }T_HANDLE_ARRAY operator () { handle; return *this; }T_HANDLE_ARRAY operator -- () { --handle; return *this; }T_HANDLE_ARRAY operator (T_HANDLE_ARRAY const tmp) { handle tmp.handle; return *this; }bool operator (T_HANDLE_ARRAY const tmp)const { return handle tmp.handle; }bool operator ! (T_HANDLE_ARRAY const tmp)const { return !((*this) tmp); }T operator * ()const{return *operator -();}T* operator - ()const{if (0 PI_N)throw SHM PI_N0;struct_T_ARRAY_VMAP_S* pvmap (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap GET_SHM_PRIVATE_DATA(PI_N);for (long i 0; i pvmap-size; i){if (pvmap-m_vmaps[i].handle_begin handle handle pvmap-m_vmaps[i].handle_end){if (pvmap-size paddrmap-addr_map_size){if (0 ! paddrmap-thread_mutex.lock())throw paddrmap-thread_mutex.lock error;if (pvmap-size paddrmap-addr_map_size){for (long j paddrmap-addr_map_size; j pvmap-size; j){char* p CShmMan::ConnectByID(pvmap-m_vmaps[j].shm_id, false);if (NULL p){thelog 连接共享内存失败 shmid pvmap-m_vmaps[j].shm_id 错误信息 strerror(errno) ende;throw 连接共享内存失败;}if (((unsigned long)p) % 8 ! 0){thelog 地址对齐错误 ende;throw 地址对齐错误;}char buf[256];sprintf(buf, 连接共享内存 %d %ld shm_id %d addr %p, PI_N, j, pvmap-m_vmaps[j].shm_id, p);thelog buf endi;paddrmap-AddShmMap(pvmap-m_vmaps[j].shm_id, p);}}else{thelog 已经被其它线程处理 endi;}if (0 ! paddrmap-thread_mutex.unlock())throw paddrmap-thread_mutex.unlock error;}return (T*)paddrmap-shm_addr_map[i].second handle - pvmap-m_vmaps[i].handle_begin;}if (i pvmap-size - 1 handle pvmap-m_vmaps[i].handle_end){thelog 刚好越过最后一个 handle (T*)paddrmap-shm_addr_map[i].second handle - pvmap-m_vmaps[i].handle_begin endi;//return (T *)paddrmap-shm_addr_map[i].secondhandle-pvmap-m_vmaps[i].handle_begin;}}char buf[2048];sprintf(buf, -无效的句柄 PI_N%d handle%ld, PI_N, handle);theLog shmArray.h T_HANDLE_ARRAY buf ende;ShowVMapPrivateData();abort();return NULL;}static T_SHM_SIZE _me(T const* p, bool not_throw false){char buf[256];struct_T_ARRAY_VMAP_S* pvmap (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap GET_SHM_PRIVATE_DATA(PI_N);for (long i 0; i pvmap-size; i){if ((T*)paddrmap-shm_addr_map[i].second p p (T*)paddrmap-shm_addr_map[i].second pvmap-m_vmaps[i].handle_end - pvmap-m_vmaps[i].handle_begin){return p - (T*)paddrmap-shm_addr_map[i].second pvmap-m_vmaps[i].handle_begin;}if (i pvmap-size - 1 p (T*)paddrmap-shm_addr_map[i].second pvmap-m_vmaps[i].handle_end - pvmap-m_vmaps[i].handle_begin){thelog 刚好越过最后一个 p p - (T*)paddrmap-shm_addr_map[i].second pvmap-m_vmaps[i].handle_begin endi;//return p-(T *)paddrmap-shm_addr_map[i].secondpvmap-m_vmaps[i].handle_begin;}}if (not_throw)return -1;else{sprintf(buf, _me无效的地址 %p, p);throw buf;}}static void ShowVMapPrivateData(){struct_T_ARRAY_VMAP_S* pvmap (struct_T_ARRAY_VMAP_S*)GET_PP_VMAP(PI_N);shm_private_data* paddrmap GET_SHM_PRIVATE_DATA(PI_N);long i, j;theLog endl;theLog pvmap-size pvmap-size endl;for (i 0; i pvmap-size; i){theLog i : begin pvmap-m_vmaps[i].handle_begin end pvmap-m_vmaps[i].handle_end endl;}theLog paddrmap-addr_map_size paddrmap-addr_map_size endl;for (j 0; j paddrmap-addr_map_size; j){theLog j : paddrmap-shm_addr_map[j].first - (long)paddrmap-shm_addr_map[j].second endl;}theLog endi;}};三、代码解读 这个代码是个模板参数是指向的类型和入口指针的索引。 主要部分是自定义的指针类符合随机迭代器概念要求可以用在STL算法里。 复杂的代码部分是在没有连接是自动去连接。由于每个共享内存结构其实是可扩展的是多个共享内存的串联因此代码比较复杂。数据的索引是连续的但不同分块的连接地址并不相同因此需要一个分块映射表。还要考虑多线程保护。如果没有分块问题操作会简单很多只需要根据PI_N获取入口地址判断是否需要连接然后就能转换为指针了。 这里是文档结束