├── example ├── shm_obj_test │ ├── shm_path_file │ ├── CMakeLists.txt │ ├── shm_obj_test.h │ └── main.cpp ├── shm_pointer_test │ ├── CMakeLists.txt │ ├── shm_obj_test.h │ └── main.cpp └── shm_pointer_v2_test │ ├── CMakeLists.txt │ ├── shm_obj_test.h │ └── main.cpp ├── src └── shm_obj │ ├── system.cpp │ ├── obj_creator_mgr.cpp │ ├── CMakeLists.txt │ └── shm_pool.cpp ├── inc ├── shm_obj │ ├── system.h │ ├── shm_obj_mgr.h │ ├── shm_pool.h │ ├── obj_creator_mgr.h │ └── shm_obj.h ├── singleton.h ├── log.h ├── shm_pointer │ ├── enable_shm_pointer_from_this.h │ ├── weak_shm_pointer.h │ ├── shm_pointer.h │ └── shm_pointer_count.h └── shm_pointer_v2 │ ├── enable_shm_pointer_from_this.h │ ├── weak_shm_pointer.h │ └── shm_pointer.h ├── CMakeLists.txt ├── LICENSE └── README.md /example/shm_obj_test/shm_path_file: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/shm_obj/system.cpp: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | 3 | bool System::resume_= false; -------------------------------------------------------------------------------- /src/shm_obj/obj_creator_mgr.cpp: -------------------------------------------------------------------------------- 1 | #include "obj_creator_mgr.h" 2 | 3 | using namespace shm_obj; 4 | 5 | ClassId ClassIdGenerator::class_id_ = 0; 6 | -------------------------------------------------------------------------------- /example/shm_obj_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/inc) 2 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_obj) 3 | 4 | set(APP_SRC 5 | main.cpp) 6 | 7 | add_executable(shm_obj_test ${APP_SRC}) 8 | target_link_libraries(shm_obj_test shm_obj) -------------------------------------------------------------------------------- /src/shm_obj/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/inc) 2 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_obj) 3 | 4 | set(LIB_SRC 5 | shm_pool.cpp 6 | obj_creator_mgr.cpp 7 | system.cpp) 8 | 9 | set(LIBRARY_OUTPUT_PATH lib) 10 | add_library(shm_obj STATIC ${LIB_SRC}) -------------------------------------------------------------------------------- /example/shm_pointer_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/inc) 2 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_obj) 3 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_pointer) 4 | 5 | set(APP_SRC 6 | main.cpp) 7 | 8 | add_executable(shm_pointer_test ${APP_SRC}) 9 | 10 | target_link_libraries(shm_pointer_test shm_obj) 11 | -------------------------------------------------------------------------------- /inc/shm_obj/system.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSTEM_H_ 2 | #define SYSTEM_H_ 3 | 4 | class System { 5 | public: 6 | static void SetSystemResume(bool flag) { 7 | resume_ = flag; 8 | } 9 | 10 | static bool IsResume() { 11 | return resume_; 12 | } 13 | private: 14 | static bool resume_; 15 | private: 16 | System(); 17 | ~System(); 18 | }; 19 | 20 | #endif //SYSTEM_H_ -------------------------------------------------------------------------------- /example/shm_pointer_v2_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/inc) 2 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_obj) 3 | include_directories(${PROJECT_SOURCE_DIR}/inc/shm_pointer_v2) 4 | 5 | set(APP_SRC 6 | main.cpp) 7 | 8 | add_executable(shm_pointer_v2_test ${APP_SRC}) 9 | 10 | target_link_libraries(shm_pointer_v2_test shm_obj) -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(ShmObj CXX) 4 | 5 | set(CMAKE_CXX_FLAGS "-g -Wall") 6 | 7 | set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 8 | set (LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) 9 | 10 | add_subdirectory(example/shm_obj_test) 11 | add_subdirectory(example/shm_pointer_test) 12 | add_subdirectory(example/shm_pointer_v2_test) 13 | add_subdirectory(src/shm_obj) 14 | -------------------------------------------------------------------------------- /inc/singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLETON_H_ 2 | #define SINGLETON_H_ 3 | 4 | template 5 | class Singleton { 6 | public: 7 | static T& Instance() { 8 | return instance; 9 | } 10 | 11 | static T* InstancePtr() { 12 | return &instance; 13 | } 14 | 15 | protected: 16 | static T instance; 17 | Singleton() {}; 18 | 19 | Singleton(const Singleton&); 20 | const Singleton & operator=(const Singleton&); 21 | }; 22 | 23 | template 24 | T Singleton::instance; 25 | 26 | #define DeclareSingleton(ClassName) public: friend class Singleton 27 | 28 | #endif //SHM_SINGLETON_H_ 29 | -------------------------------------------------------------------------------- /inc/log.h: -------------------------------------------------------------------------------- 1 | #ifndef LOG_H_ 2 | #define LOG_H_ 3 | 4 | #include 5 | 6 | enum LogLevel { 7 | LOG_LEVEL_DEBUG, 8 | LOG_LEVEL_INFO, 9 | LOG_LEVEL_ERROR, 10 | }; 11 | 12 | static const LogLevel cur_log_level = LOG_LEVEL_ERROR; 13 | 14 | #define LOG(log_level, format, ...) \ 15 | do { \ 16 | if (log_level >= cur_log_level) { \ 17 | printf(format, ##__VA_ARGS__); \ 18 | } \ 19 | } while(0) 20 | 21 | #define LOG_ERROR(format, ...) LOG(LOG_LEVEL_ERROR, "File:%s| Line:%05d|Fun:%s|"format"\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) 22 | #define LOG_INFO(format, ...) LOG(LOG_LEVEL_INFO, "File:%s| Line:%05d|Fun:%s|"format"\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) 23 | #define LOG_DEBUG(format, ...) LOG(LOG_LEVEL_DEBUG, "File:%s| Line:%05d|Fun:%s|"format"\n", __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__) 24 | //#define LOG_INFO(format, ...) LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__) 25 | //#define LOG_DEBUG(format, ...) LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) 26 | 27 | #endif //LOG_H_ 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 binnywang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /inc/shm_pointer/enable_shm_pointer_from_this.h: -------------------------------------------------------------------------------- 1 | #ifndef ENABLE_SHM_POINTER_FROM_THIS_H_ 2 | #define ENABLE_SHM_POINTER_FROM_THIS_H_ 3 | 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | 7 | #include 8 | 9 | namespace shm_obj { 10 | 11 | template 12 | class EnableShmPointerFromThis { 13 | public: 14 | EnableShmPointerFromThis() {} 15 | ~EnableShmPointerFromThis() {} 16 | 17 | public: 18 | ShmPointer ShmPointerFromThis() { 19 | ShmPointer p(weak_this_); 20 | assert(p.Get() == this); 21 | return p; 22 | } 23 | 24 | ShmPointer ShmPointerFromThis() const { 25 | ShmPointer p(weak_this_); 26 | assert(p.Get() == this); 27 | return p; 28 | } 29 | 30 | WeakShmPointer WeakShmPointerFromThis() { 31 | return weak_this_; 32 | } 33 | 34 | WeakShmPointer WeakShmPointerFromThis() const { 35 | return weak_this_; 36 | } 37 | 38 | virtual void Recover() { 39 | weak_this_.Recover(); 40 | } 41 | 42 | public: 43 | template 44 | void _internal_accept_owner(ShmPointer const *ppx, ShmObjPtr const *py) const { 45 | if (weak_this_.Expired()) { 46 | weak_this_ = ShmPointer(*ppx, *py); 47 | } 48 | } 49 | 50 | private: 51 | mutable WeakShmPointer weak_this_; 52 | }; 53 | 54 | } //namespace 55 | 56 | #endif //ENABLE_SHM_PTR_FROM_THIS_H_ -------------------------------------------------------------------------------- /inc/shm_pointer_v2/enable_shm_pointer_from_this.h: -------------------------------------------------------------------------------- 1 | #ifndef ENABLE_SHM_POINTER_FROM_THIS_H_ 2 | #define ENABLE_SHM_POINTER_FROM_THIS_H_ 3 | 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | 7 | #include 8 | 9 | namespace shm_obj { 10 | 11 | template 12 | class EnableShmPointerFromThis { 13 | public: 14 | EnableShmPointerFromThis() {} 15 | ~EnableShmPointerFromThis() {} 16 | 17 | public: 18 | ShmPointer ShmPointerFromThis() { 19 | ShmPointer p(weak_this_); 20 | assert(p.Get() == this); 21 | return p; 22 | } 23 | 24 | ShmPointer ShmPointerFromThis() const { 25 | ShmPointer p(weak_this_); 26 | assert(p.Get() == this); 27 | return p; 28 | } 29 | 30 | WeakShmPointer WeakShmPointerFromThis() { 31 | return weak_this_; 32 | } 33 | 34 | WeakShmPointer WeakShmPointerFromThis() const { 35 | return weak_this_; 36 | } 37 | 38 | virtual void Recover() { 39 | weak_this_.Recover(); 40 | } 41 | 42 | public: 43 | template 44 | void _internal_accept_owner(ShmPointer const *ppx, ShmObjPtr const *py) const { 45 | if (weak_this_.Expired()) { 46 | weak_this_ = ShmPointer(*ppx, *py); 47 | } 48 | } 49 | 50 | private: 51 | mutable WeakShmPointer weak_this_; 52 | }; 53 | 54 | } //namespace 55 | 56 | #endif //ENABLE_SHM_PTR_FROM_THIS_H_ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShmObjMgr 共享内存对象管理器 2 | ## 主要特性 3 | - 一种通用的对象池实现 4 | 5 | - 支持存放在共享内存中,支持系统重启后热加载,支持对象中有原始指针,虚函数,重启会进行恢复。 6 | 7 | - 可选的智能指针封装,实现参考boost/shared_ptr,**智能指针不支持和共享内存一起使用。(如果程序core掉,可能会出现智能指针析构函数没有调用,导致系统重启后,共享内存中的对象引用计数错误,对象不能释放给对象池)** 8 | ## 对象池设计 9 | - 首先给类分配uint8_t的class_id,在分配和释放对象时,需要通过class_id来调用类的构造和析构函数。 10 | - 对类进行group, 采用uint8_t 的group_id来标示,同一个group中的类对象共享相同的单个内存块大小和内存块个数 11 | - 注册类到group中, 注册时需要提供{class_id, class_size, class_obj_count}三元组,如分别注册{class_a_id, class_a_size, class_a_obj_count}, {class_b_id, class_b_size, class_b_obj_count}, 最终group占用总的内存大小为 max(class_a_size, class_b_size) * max(max_a_obj_count, max_b_obj_count) 12 | 13 | - 每个对象由一个uint64_t的obj_id标示,由group_id, class_id, index, seq四部分组成。如果不使用智能指针,每次访问对象指针obj_ptr时,必须通过obj_id去查找对应的obj_ptr, 防止野指针访问。 14 | 15 | - 每个类必须继承ShmObj类,有个Recover接口,在热加载的时候会被调用,放在共享内存的类成员变量里面有原始指针,可以在该接口里面对原始指针进行重置。 16 | 17 | ## 智能指针设计 18 | ### 版本一 19 | 20 | 完全按照boost/shared_ptr, boost/weak_ptr, boost/enable_from_shared_ptr来设计,计数器对象也分配在对象池上,强引用计数为零时,释放对象本身,弱引用计数为零时,释放引用计数器对象。 21 | 22 | ### 版本二 23 | 24 | 计数器直接存在对象身上,只有强引用计数,没有弱引用计数,当强引用计数器为零时,释放对象,由于每个对象每次被分配都会产生一个唯一的id, 通过唯一id来避免野指针,因此弱指针不会出现野指针。 25 | 26 | 27 | ## Example 28 | - 不使用智能指针, 参考example/shm_obj_test 29 | 30 | - 使用智能指针v1, 参考example/shm_pointer_test 31 | 32 | - 使用智能指针v2,参考example/shm_pointer_test_v2 33 | 34 | ## ISSUE 35 | 36 | - 如果使用智能指针v1版,智能指针的计数器个数该分配多少个? 37 | -------------------------------------------------------------------------------- /inc/shm_obj/shm_obj_mgr.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_OBJ_MGR_H_ 2 | #define SHM_OBJ_MGR_H_ 3 | 4 | #include "shm_pool.h" 5 | #include "singleton.h" 6 | #include "log.h" 7 | 8 | #include "shm_obj.h" 9 | 10 | namespace shm_obj { 11 | 12 | class ShmObjMgr : public Singleton { 13 | public: 14 | DeclareSingleton(ShmObjMgr); 15 | public: 16 | 17 | int NewClassGroup(GroupId& group_id) { 18 | return shm_pool_.NewClassGroup(group_id); 19 | } 20 | 21 | template 22 | int AddClassToGroup(GroupId& group_id, size_t max_obj_count) { 23 | return shm_pool_.AddClassToGroup(group_id, T::TYPE, sizeof(T), max_obj_count); 24 | } 25 | 26 | size_t TotalSize() const { 27 | return shm_pool_.TotalSize(); 28 | } 29 | 30 | int Init(void* mem, size_t max_size, bool fresh = true) { 31 | return shm_pool_.Init(mem, max_size, fresh); 32 | } 33 | 34 | template 35 | ShmObjPtr CreateObject() { 36 | ObjId obj_id; 37 | void* obj = shm_pool_.NewObject(T::TYPE, obj_id); 38 | if (obj == NULL) { 39 | return ShmObjPtr(); 40 | } 41 | return ShmObjPtr(reinterpret_cast(obj), obj_id); 42 | } 43 | 44 | template 45 | void FreeObject(const ShmObjPtr& p) { 46 | shm_pool_.FreeObject(p.obj_id()); 47 | } 48 | 49 | template 50 | int Recover(ShmObjPtr& p) { 51 | void* obj = shm_pool_.GetObject(p.obj_id()); 52 | if (obj == NULL) { 53 | LOG_ERROR("recovery pointer error|obj_id[%zu]\n", p.obj_id().id); 54 | return -1; 55 | } 56 | 57 | p.obj_ptr_ = static_cast(reinterpret_cast(obj)); 58 | return 0; 59 | } 60 | 61 | private: 62 | ShmPool shm_pool_; 63 | }; 64 | 65 | /// FIXME: 如何解决模板类循环引用? 66 | template 67 | ShmObjPtr::operator bool() const { 68 | if (obj_id_.id == 0) { 69 | return false; 70 | } 71 | int ret = ShmObjMgr::Instance().Recover(*const_cast *>(this)); 72 | if (ret != 0) { 73 | return false; 74 | } 75 | return true; 76 | } 77 | 78 | } //namespace 79 | 80 | #endif // SHM_OBJ_MGR_H_ 81 | 82 | 83 | -------------------------------------------------------------------------------- /inc/shm_obj/shm_pool.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_POOL_H_ 2 | #define SHM_POOL_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "shm_obj.h" 10 | 11 | 12 | namespace shm_obj { 13 | 14 | class ShmPool { 15 | public: 16 | static const int MAX_CLASS_PER_GROUP = 255; 17 | static const int MAX_CLASS_GROUP_NUM = 255; 18 | 19 | /// 每一组对象的信息 20 | struct ObjIndex { 21 | ObjId obj_id; 22 | int32_t next; 23 | int32_t prev; 24 | }; 25 | 26 | typedef char ObjNode; 27 | 28 | struct ObjGroup { 29 | GroupId group_id; 30 | size_t group_size; 31 | size_t max_class_size; 32 | unsigned int max_obj_count; 33 | unsigned int used_obj_count; 34 | int class_id_num; 35 | ClassId class_id[MAX_CLASS_PER_GROUP]; 36 | ObjIndex* obj_index_; 37 | ObjNode* obj_node_; 38 | int free_index_head; 39 | int used_index_head; 40 | uint16_t seq; 41 | }; 42 | 43 | /// 共享内存头,包含所有的分组信息 44 | struct ClassGroupUnit { 45 | GroupId group_id; 46 | int class_id_num; 47 | ClassId class_id[MAX_CLASS_PER_GROUP]; 48 | size_t max_class_size; 49 | unsigned int max_obj_count; 50 | ObjGroup* obj_group; 51 | }; 52 | 53 | struct ClassGroupInfo { 54 | int group_num; 55 | ClassGroupUnit group[MAX_CLASS_GROUP_NUM]; 56 | }; 57 | 58 | struct ShmPoolHeader { 59 | size_t max_size; 60 | ClassGroupInfo group_info; 61 | }; 62 | 63 | public: 64 | ShmPool(); 65 | public: 66 | int NewClassGroup(GroupId& group_id); 67 | int AddClassToGroup(GroupId& group_id, ClassId class_id, size_t class_size, size_t obj_count); 68 | size_t TotalSize() const; 69 | int Init(void* mem, size_t max_size, bool fresh = true); 70 | void* NewObject(ClassId class_id, ObjId& obj_id); 71 | void* GetObject(const ObjId& obj_id); 72 | void FreeObject(const ObjId& obj_id); 73 | std::string DumpObj(); 74 | 75 | private: 76 | void InitObjGroup(ObjGroup* obj_group); 77 | std::string DumpObjGroup(ObjGroup* obj_group); 78 | 79 | ObjGroup* FindGroupByClassId(ClassId class_id); 80 | ObjGroup* FindGroupByGroupId(GroupId group_id); 81 | void* NewObject(ObjGroup* obj_group, ClassId class_id, ObjId & obj_id); 82 | void* GetObject(ObjGroup* obj_group, const ObjId & obj_id); 83 | void FreeObject(ObjGroup* obj_group, const ObjId & obj_id); 84 | 85 | ClassGroupInfo tmp_group_info_; 86 | ShmPoolHeader* shm_pool_header_; 87 | }; 88 | 89 | } //namespace 90 | 91 | #endif // SHM_POOL_H_ 92 | -------------------------------------------------------------------------------- /example/shm_obj_test/shm_obj_test.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_OBJ_TEST_H_ 2 | #define SHM_OBJ_TEST_H_ 3 | 4 | #include "shm_obj_mgr.h" 5 | 6 | using namespace shm_obj; 7 | 8 | /// 普通类 9 | class XXManager { 10 | public: 11 | void Update() { 12 | std::cout << "XXManager update" << std::endl; 13 | } 14 | }; 15 | 16 | XXManager globalXXManager; 17 | 18 | class Base: public ShmObj { 19 | public: 20 | DeclareTypeName(Base); 21 | virtual void Update() { 22 | std::cout << "base update" << std::endl; 23 | } 24 | }; 25 | 26 | class ClassB; 27 | 28 | class ClassA : public Base { 29 | public: 30 | DeclareTypeName(ClassA); 31 | 32 | ClassA() { 33 | std::cout << "ClassA()" << std::endl; 34 | if (System::IsResume()) { 35 | return; 36 | } 37 | member_ = 0; 38 | } 39 | 40 | /// 41 | virtual void Recover() { 42 | xx_manager_ = &globalXXManager; 43 | if (xx_manager_) { 44 | xx_manager_->Update(); 45 | } 46 | } 47 | 48 | virtual void Update(); 49 | 50 | void SetMember(int member) { 51 | member_ = member; 52 | } 53 | 54 | void SetXXManager(XXManager* xx_manager) { 55 | xx_manager_ = xx_manager; 56 | } 57 | 58 | ~ClassA() { 59 | std::cout << "~ClassA()" << std::endl; 60 | } 61 | 62 | private: 63 | int member_; 64 | private: 65 | XXManager* xx_manager_; 66 | }; 67 | 68 | class ClassB: public Base { 69 | public: 70 | 71 | DeclareTypeName(ClassB); 72 | 73 | ClassB() { 74 | std::cout << "ClassB()" << std::endl; 75 | if (System::IsResume()) { 76 | return; 77 | } 78 | member_ = 0; 79 | } 80 | 81 | ~ClassB() { 82 | std::cout << "~ClassB()" << std::endl; 83 | } 84 | 85 | virtual void Update(); 86 | 87 | void SetClassAObjPtr(const ShmObjPtr &a_ptr) { 88 | a_ptr_ = a_ptr; 89 | } 90 | 91 | void SetMember(int member) { 92 | member_ = member; 93 | } 94 | 95 | private: 96 | int member_; 97 | ShmObjPtr a_ptr_; 98 | }; 99 | 100 | 101 | void ClassA::Update() { 102 | std::cout << "class A update with member_ = " << member_ << std::endl; 103 | if (xx_manager_) { 104 | xx_manager_->Update(); 105 | } 106 | } 107 | 108 | void ClassB::Update() { 109 | std::cout << "class B update with member_ = " << member_ << std::endl; 110 | if (a_ptr_) { 111 | a_ptr_->Update(); 112 | } 113 | } 114 | 115 | ImplmentTypeName(Base); 116 | ImplmentTypeName(ClassA); 117 | ImplmentTypeName(ClassB); 118 | #endif 119 | -------------------------------------------------------------------------------- /inc/shm_pointer/weak_shm_pointer.h: -------------------------------------------------------------------------------- 1 | #ifndef WEAK_SHM_POINTER_H_ 2 | #define WEAK_SHM_POINTER_H_ 3 | 4 | #include "shm_pointer_count.h" 5 | #include "shm_obj_mgr.h" 6 | 7 | namespace shm_obj { 8 | 9 | template class ShmPointer; 10 | template class WeakShmPointer; 11 | 12 | template 13 | class WeakShmPointer { 14 | public: 15 | WeakShmPointer() {} 16 | virtual ~WeakShmPointer() {} 17 | 18 | template 19 | //WeakShmPointer(const WeakShmPointer& r) : ShmPointerBase(r.Lock().obj_ptr_, r.Lock().obj_id_) { 20 | WeakShmPointer(const WeakShmPointer& r) : count_ptr_(r.count_ptr_) { 21 | shm_pointer_assert_convertible(); 22 | obj_ptr_ = r.obj_ptr_; 23 | } 24 | 25 | template 26 | explicit WeakShmPointer(const ShmPointer& r) : count_ptr_(r.count_ptr_) { 27 | shm_pointer_assert_convertible(); 28 | obj_ptr_ = r.obj_ptr_; 29 | } 30 | 31 | template 32 | WeakShmPointer& operator=(const WeakShmPointer& r) { 33 | shm_pointer_assert_convertible(); 34 | count_ptr_ = r.count_ptr_; 35 | obj_ptr_ = r.obj_ptr_; 36 | return *this; 37 | } 38 | 39 | template 40 | WeakShmPointer& operator=(const ShmPointer& r) { 41 | shm_pointer_assert_convertible(); 42 | count_ptr_ = r.count_ptr_; 43 | obj_ptr_ = r.obj_ptr_; 44 | return *this; 45 | } 46 | 47 | bool Expired() const { 48 | return count_ptr_.UseCount() == 0; 49 | } 50 | 51 | ShmPointer Lock() const { 52 | return Expired() ? ShmPointer() : ShmPointer(*this); 53 | } 54 | 55 | int Recover() { 56 | int ret = ShmObjMgr::Instance().Recover(obj_ptr_); 57 | if (ret != 0) { 58 | Reset(); 59 | } 60 | return count_ptr_.Recover(); 61 | } 62 | 63 | void Reset() { 64 | obj_ptr_.Reset(); 65 | count_ptr_.Reset(); 66 | } 67 | 68 | private: 69 | WeakShmObjCountPtr count_ptr_; 70 | ShmObjPtr obj_ptr_; 71 | private: 72 | template friend class WeakShmPointer; 73 | template friend class ShmPointer; 74 | 75 | }; 76 | 77 | template inline bool operator==(WeakShmPointer const & a, WeakShmPointer const & b) { 78 | return ShmPointer(a) == ShmPointer(b); 79 | } 80 | 81 | template inline bool operator!=(WeakShmPointer const & a, WeakShmPointer const & b) { 82 | return ShmPointer(a) != ShmPointer(b); 83 | } 84 | 85 | } 86 | #endif //WEAK_SHM_POINTER_H_ 87 | -------------------------------------------------------------------------------- /inc/shm_pointer_v2/weak_shm_pointer.h: -------------------------------------------------------------------------------- 1 | #ifndef WEAK_SHM_POINTER_H_ 2 | #define WEAK_SHM_POINTER_H_ 3 | 4 | #include "shm_obj_mgr.h" 5 | 6 | namespace shm_obj { 7 | 8 | template class ShmPointer; 9 | template class WeakShmPointer; 10 | 11 | template 12 | class WeakShmPointer { 13 | public: 14 | WeakShmPointer() {} 15 | virtual ~WeakShmPointer() {Reset();} 16 | 17 | template 18 | //WeakShmPointer(const WeakShmPointer& r) : ShmPointerBase(r.Lock().obj_ptr_, r.Lock().obj_id_) { 19 | WeakShmPointer(const WeakShmPointer& r) : count_ptr_(r.count_ptr_) { 20 | shm_pointer_assert_convertible(); 21 | obj_ptr_ = r.obj_ptr_; 22 | } 23 | 24 | template 25 | explicit WeakShmPointer(const ShmPointer& r) : count_ptr_(r.count_ptr_) { 26 | shm_pointer_assert_convertible(); 27 | obj_ptr_ = r.obj_ptr_; 28 | } 29 | 30 | template 31 | WeakShmPointer& operator=(const WeakShmPointer& r) { 32 | shm_pointer_assert_convertible(); 33 | count_ptr_ = r.count_ptr_; 34 | obj_ptr_ = r.obj_ptr_; 35 | return *this; 36 | } 37 | 38 | template 39 | WeakShmPointer& operator=(const ShmPointer& r) { 40 | shm_pointer_assert_convertible(); 41 | count_ptr_ = r.count_ptr_; 42 | obj_ptr_ = r.obj_ptr_; 43 | return *this; 44 | } 45 | 46 | bool Expired() const { 47 | if (count_ptr_ && count_ptr_->UseCount() != 0) { 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | ShmPointer Lock() const { 54 | return Expired() ? ShmPointer() : ShmPointer(*this); 55 | } 56 | 57 | int Recover() { 58 | int ret = ShmObjMgr::Instance().Recover(obj_ptr_); 59 | if (ret) { 60 | count_ptr_.Reset(); 61 | obj_ptr_.Reset(); 62 | return ret; 63 | } 64 | count_ptr_ = obj_ptr_; 65 | return 0; 66 | } 67 | 68 | void Reset() { 69 | obj_ptr_.Reset(); 70 | count_ptr_.Reset(); 71 | } 72 | 73 | private: 74 | ShmObjPtr count_ptr_; 75 | ShmObjPtr obj_ptr_; 76 | private: 77 | template friend class WeakShmPointer; 78 | template friend class ShmPointer; 79 | 80 | }; 81 | 82 | template inline bool operator==(WeakShmPointer const & a, WeakShmPointer const & b) { 83 | return ShmPointer(a) == ShmPointer(b); 84 | } 85 | 86 | template inline bool operator!=(WeakShmPointer const & a, WeakShmPointer const & b) { 87 | return ShmPointer(a) != ShmPointer(b); 88 | } 89 | 90 | } 91 | #endif //WEAK_SHM_POINTER_H_ 92 | -------------------------------------------------------------------------------- /inc/shm_obj/obj_creator_mgr.h: -------------------------------------------------------------------------------- 1 | #ifndef OBJ_CREATOR_MGR_H_ 2 | #define OBJ_CREATOR_MGR_H_ 3 | 4 | #include 5 | #include 6 | #include "singleton.h" 7 | #include "shm_obj.h" 8 | 9 | namespace shm_obj { 10 | 11 | class IObjectCreator { 12 | public: 13 | virtual void* ReplacementNew(void* addr) = 0; 14 | virtual void* New() = 0; 15 | virtual void Deconstructor(void* addr) = 0; 16 | }; 17 | 18 | template 19 | class ObjectCreator: public IObjectCreator, public Singleton > { 20 | public: 21 | DeclareSingleton(ObjectCreator); 22 | 23 | virtual void* New() { 24 | return new T(); 25 | } 26 | 27 | virtual void* ReplacementNew(void * addr) { 28 | return new(addr) T; 29 | } 30 | 31 | virtual void Deconstructor(void* addr) { 32 | T* obj = reinterpret_cast(addr); 33 | obj->~T(); 34 | } 35 | }; 36 | 37 | 38 | class ObjectCreatorMgr : public Singleton { 39 | public: 40 | DeclareSingleton(ObjectCreatorMgr); 41 | public: 42 | static const int MAX_CLASS_ID = 0xff; 43 | public: 44 | template 45 | T* CreateObject(void* addr) { 46 | IObjectCreator* creator = obj_creator_[T::TYPE]; 47 | void* obj = creator->ReplacementNew(addr); 48 | return reinterpret_cast(obj); 49 | } 50 | 51 | template 52 | int RegisterObjectCreator() { 53 | obj_creator_[T::TYPE] = ObjectCreator::InstancePtr(); 54 | return 0; 55 | } 56 | 57 | template 58 | int RegisterObjectCreator(ClassId class_id) { 59 | if (class_id >= MAX_CLASS_ID) { 60 | return -1; 61 | } 62 | 63 | obj_creator_[class_id] = ObjectCreator::InstancePtr(); 64 | return 0; 65 | } 66 | 67 | void* CreateObject(void* addr, ClassId class_id) { 68 | IObjectCreator* creator = obj_creator_[class_id]; 69 | void* obj = creator->ReplacementNew(addr); 70 | return obj; 71 | } 72 | 73 | void FreeObject(void* addr, ClassId class_id) { 74 | IObjectCreator* creator = obj_creator_[class_id]; 75 | creator->Deconstructor(addr); 76 | } 77 | private: 78 | IObjectCreator* obj_creator_[MAX_CLASS_ID]; 79 | }; 80 | 81 | 82 | /// class id 必须大于零 83 | class ClassIdGenerator { 84 | public: 85 | static const ClassId INVALID_CLASS_ID = 0; 86 | static ClassId NewClassId() { 87 | return ++class_id_; 88 | }; 89 | private: 90 | static ClassId class_id_; 91 | }; 92 | 93 | template 94 | ClassId RegisterClass() { 95 | ClassId class_id = ClassIdGenerator::NewClassId(); 96 | assert(class_id != ClassIdGenerator::INVALID_CLASS_ID); 97 | assert(0 == ObjectCreatorMgr::Instance().RegisterObjectCreator(class_id)); 98 | return class_id; 99 | } 100 | 101 | #define DeclareTypeName(ClassName) static ClassId TYPE 102 | #define ImplmentTypeName(ClassName) ClassId ClassName::TYPE = RegisterClass() 103 | 104 | 105 | } //namespace 106 | 107 | #endif //OBJ_CREATOR_MGR_H_ 108 | -------------------------------------------------------------------------------- /example/shm_pointer_v2_test/shm_obj_test.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_OBJ_TEST_H_ 2 | #define SHM_OBJ_TEST_H_ 3 | 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | #include "enable_shm_pointer_from_this.h" 7 | 8 | using namespace shm_obj; 9 | 10 | class Base: public ShmObj { 11 | public: 12 | DeclareTypeName(Base); 13 | virtual void Update() { 14 | std::cout << "base update" << std::endl; 15 | } 16 | }; 17 | 18 | class ClassB; 19 | 20 | class ClassA : public Base { 21 | public: 22 | 23 | DeclareTypeName(ClassA); 24 | ClassA() { 25 | std::cout << "ClassA()" << std::endl; 26 | } 27 | 28 | virtual void Recover() { 29 | weak_shm_poiner_.Recover(); 30 | } 31 | 32 | virtual void Update(); 33 | 34 | void SetMember(int member) {member_ = member;} 35 | 36 | void SetWeakShmPointerOfClassB(const WeakShmPointer &weak_shm_poiner) { 37 | weak_shm_poiner_ = weak_shm_poiner; 38 | } 39 | 40 | ~ClassA() { 41 | std::cout << "~ClassA()" << std::endl; 42 | } 43 | 44 | private: 45 | WeakShmPointer weak_shm_poiner_; 46 | private: 47 | int member_; 48 | 49 | }; 50 | 51 | 52 | class ClassB; 53 | 54 | class Foo { 55 | public: 56 | void SetOwner(const WeakShmPointer& owner) { 57 | owner_ = owner; 58 | } 59 | 60 | virtual void Update(); 61 | 62 | virtual void Recover() { 63 | owner_.Recover(); 64 | 65 | } 66 | private: 67 | WeakShmPointer owner_; 68 | }; 69 | 70 | 71 | class ClassB: public Base, public EnableShmPointerFromThis { 72 | public: 73 | DeclareTypeName(ClassB); 74 | 75 | ClassB() { 76 | std::cout << "ClassB()" << std::endl; 77 | } 78 | 79 | ~ClassB() { 80 | std::cout << "~ClassB()" << std::endl; 81 | } 82 | 83 | virtual void Recover() { 84 | EnableShmPointerFromThis::Recover(); 85 | shm_poiner_.Recover(); 86 | foo_.Recover(); 87 | } 88 | 89 | void Callback() { 90 | std::cout << "ClassB Callback()" << std::endl; 91 | } 92 | 93 | virtual void Update(); 94 | 95 | void SetMember(int member) {member_ = member;} 96 | 97 | void SetShmPointerOfClassA(const ShmPointer &shm_poiner) { 98 | shm_poiner_ = shm_poiner; 99 | } 100 | 101 | private: 102 | ShmPointer shm_poiner_; 103 | Foo foo_; 104 | private: 105 | int member_; 106 | }; 107 | 108 | void Foo::Update() { 109 | if (! owner_.Expired()) { 110 | owner_.Lock()->Callback(); 111 | } 112 | } 113 | 114 | void ClassA::Update() { 115 | std::cout << "class A update with member_" << std::dec << member_ << std::endl; 116 | if (!weak_shm_poiner_.Expired()) { 117 | weak_shm_poiner_.Lock()->Update(); 118 | } 119 | } 120 | 121 | void ClassB::Update() { 122 | std::cout << "class B update with member_" << std::dec << member_ << std::endl; 123 | foo_.SetOwner(WeakShmPointer(ShmPointerFromThis())); 124 | foo_.Update(); 125 | } 126 | 127 | ImplmentTypeName(Base); 128 | ImplmentTypeName(ClassA); 129 | ImplmentTypeName(ClassB); 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /example/shm_pointer_test/shm_obj_test.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_OBJ_TEST_H_ 2 | #define SHM_OBJ_TEST_H_ 3 | 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | #include "enable_shm_pointer_from_this.h" 7 | 8 | using namespace shm_obj; 9 | 10 | class Base: public ShmObj { 11 | public: 12 | DeclareTypeName(Base); 13 | virtual void Update() { 14 | std::cout << "base update" << std::endl; 15 | } 16 | }; 17 | 18 | class ClassB; 19 | 20 | class ClassA : public Base { 21 | public: 22 | 23 | DeclareTypeName(ClassA); 24 | ClassA() { 25 | std::cout << "ClassA()" << std::endl; 26 | } 27 | 28 | virtual void Recover() { 29 | weak_shm_poiner_.Recover(); 30 | } 31 | 32 | virtual void Update(); 33 | 34 | void SetMember(int member) {member_ = member;} 35 | 36 | void SetWeakShmPointerOfClassB(const WeakShmPointer &weak_shm_poiner) { 37 | weak_shm_poiner_ = weak_shm_poiner; 38 | } 39 | 40 | ~ClassA() { 41 | std::cout << "~ClassA()" << std::endl; 42 | } 43 | 44 | private: 45 | WeakShmPointer weak_shm_poiner_; 46 | private: 47 | int member_; 48 | 49 | }; 50 | 51 | 52 | class ClassB; 53 | 54 | class Foo { 55 | public: 56 | void SetOwner(const WeakShmPointer& owner) { 57 | owner_ = owner; 58 | } 59 | 60 | virtual void Update(); 61 | 62 | virtual void Recover() { 63 | owner_.Recover(); 64 | 65 | } 66 | private: 67 | WeakShmPointer owner_; 68 | }; 69 | 70 | 71 | class ClassB: public Base, public EnableShmPointerFromThis { 72 | public: 73 | DeclareTypeName(ClassB); 74 | 75 | ClassB() { 76 | std::cout << "ClassB()" << std::endl; 77 | } 78 | 79 | ~ClassB() { 80 | std::cout << "~ClassB()" << std::endl; 81 | } 82 | 83 | virtual void Recover() { 84 | EnableShmPointerFromThis::Recover(); 85 | shm_poiner_.Recover(); 86 | foo_.Recover(); 87 | } 88 | 89 | void Callback() { 90 | std::cout << "ClassB Callback()" << std::endl; 91 | } 92 | 93 | virtual void Update(); 94 | 95 | void SetMember(int member) {member_ = member;} 96 | 97 | void SetShmPointerOfClassA(const ShmPointer &shm_poiner) { 98 | shm_poiner_ = shm_poiner; 99 | } 100 | 101 | private: 102 | ShmPointer shm_poiner_; 103 | Foo foo_; 104 | private: 105 | int member_; 106 | }; 107 | 108 | void Foo::Update() { 109 | if (! owner_.Expired()) { 110 | owner_.Lock()->Callback(); 111 | } 112 | } 113 | 114 | void ClassA::Update() { 115 | std::cout << "class A update with member_" << std::dec << member_ << std::endl; 116 | if (!weak_shm_poiner_.Expired()) { 117 | weak_shm_poiner_.Lock()->Update(); 118 | } 119 | } 120 | 121 | void ClassB::Update() { 122 | std::cout << "class B update with member_" << std::dec << member_ << std::endl; 123 | foo_.SetOwner(WeakShmPointer(ShmPointerFromThis())); 124 | foo_.Update(); 125 | } 126 | 127 | 128 | ImplmentTypeName(Base); 129 | ImplmentTypeName(ClassA); 130 | ImplmentTypeName(ClassB); 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /inc/shm_obj/shm_obj.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_OBJ_H_ 2 | #define SHM_OBJ_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "system.h" 8 | #include "log.h" 9 | 10 | namespace shm_obj { 11 | 12 | /// 共享内存对象基类 13 | class ShmObj { 14 | public: 15 | ShmObj() { 16 | if (System::IsResume()) { 17 | return; 18 | } 19 | use_count_ = 0; 20 | } 21 | 22 | virtual void Recover() {} 23 | 24 | virtual ~ShmObj() { LOG_DEBUG("~ShmObj"); use_count_ = 0; } 25 | 26 | inline size_t IncUseCount() { 27 | return ++use_count_; 28 | } 29 | 30 | inline size_t DecUseCount() { 31 | return --use_count_; 32 | } 33 | 34 | inline size_t UseCount() { 35 | return use_count_; 36 | } 37 | private: 38 | size_t use_count_; 39 | }; 40 | 41 | typedef uint8_t GroupId; 42 | typedef uint8_t ClassId; 43 | 44 | /// 共享内存对象Id 45 | typedef union ObjId { 46 | uint64_t id; 47 | struct { 48 | GroupId group_id; 49 | ClassId class_id; 50 | uint16_t seq; 51 | int32_t index; 52 | }; 53 | } ObjId; 54 | 55 | /// Y类型是否可以隐试转换为T类型 56 | template inline void shm_pointer_assert_convertible() { 57 | T *p = static_cast(0); 58 | (void)p; 59 | } 60 | 61 | /// 共享内存指针封装 62 | template class ShmObjPtr; 63 | class ShmObjMgr; 64 | 65 | template 66 | class ShmObjPtr { 67 | public: 68 | ShmObjPtr() { 69 | if(System::IsResume()) { 70 | return; 71 | } else { 72 | Reset(); 73 | } 74 | } 75 | 76 | ShmObjPtr(T *obj_ptr, ObjId obj_id) : obj_ptr_(obj_ptr), obj_id_(obj_id) {} 77 | 78 | ~ShmObjPtr() { 79 | Reset(); 80 | } 81 | 82 | template ShmObjPtr(const ShmObjPtr & r) { 83 | shm_pointer_assert_convertible(); 84 | obj_ptr_ = r.obj_ptr_; 85 | obj_id_ = r.obj_id_; 86 | } 87 | 88 | template const ShmObjPtr& operator=(const ShmObjPtr & r) { 89 | shm_pointer_assert_convertible(); 90 | obj_ptr_ = r.obj_ptr_; 91 | obj_id_ = r.obj_id_; 92 | return *this; 93 | } 94 | 95 | void Reset() { 96 | obj_ptr_ = 0; 97 | obj_id_.id = 0; 98 | } 99 | 100 | const ObjId& obj_id() const { return obj_id_;} 101 | 102 | /// only for debug 103 | void set_obj_id(const ObjId& obj_id) { obj_id_ = obj_id;} 104 | 105 | T* Get() const { return obj_ptr_; } 106 | 107 | operator bool() const; 108 | 109 | T* operator->() const { return static_cast(this->obj_ptr_); } 110 | 111 | T& operator*() const { return *static_cast(this->obj_ptr_); } 112 | 113 | private: 114 | mutable T* obj_ptr_; 115 | ObjId obj_id_; 116 | 117 | friend class ShmObjMgr; 118 | 119 | template friend class ShmObjPtr; 120 | }; 121 | 122 | template inline bool operator==(ShmObjPtr const & a, ShmObjPtr const & b) { 123 | return a.obj_id() == b.obj_id(); 124 | } 125 | 126 | template inline bool operator!=(ShmObjPtr const & a, ShmObjPtr const & b) { 127 | return a.obj_id() != b.obj_id(); 128 | } 129 | 130 | template ShmObjPtr static_obj_ptr_cast( ShmObjPtr const & r ) { 131 | (void) static_cast< T* >( static_cast< U* >( 0 ) ); 132 | 133 | return ShmObjPtr(static_cast< T* >( r.Get()) , r.obj_id()); 134 | } 135 | 136 | template ShmObjPtr const_obj_ptr_cast( ShmObjPtr const & r ) { 137 | (void) const_cast< T* >( static_cast< U* >( 0 ) ); 138 | 139 | return ShmObjPtr(const_cast< T* >( r.Get()), r.obj_id()); 140 | } 141 | 142 | template ShmObjPtr dynamic_obj_ptr_cast( ShmObjPtr const & r ) { 143 | (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); 144 | 145 | return ShmObjPtr(dynamic_cast< T* >( r.Get()), r.obj_id()); 146 | } 147 | 148 | template ShmObjPtr reinterpret_obj_ptr_cast( ShmObjPtr const & r ) { 149 | (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); 150 | 151 | return ShmObjPtr(reinterpret_cast< T* >( r.Get()), r.obj_id()); 152 | } 153 | 154 | 155 | } // namespace 156 | 157 | #endif // SHM_OBJ_H_ -------------------------------------------------------------------------------- /example/shm_obj_test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shm_obj_mgr.h" 3 | #include "obj_creator_mgr.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include "shm_obj_test.h" 16 | 17 | size_t InitShmPool() { 18 | GroupId group_id; 19 | ShmObjMgr::Instance().NewClassGroup(group_id); 20 | 21 | ShmObjMgr::Instance().AddClassToGroup(group_id, 10); 22 | ShmObjMgr::Instance().AddClassToGroup(group_id, 20); 23 | return ShmObjMgr::Instance().TotalSize(); 24 | } 25 | 26 | void* GetShm(const char* path_name, size_t max_size, bool & is_fresh) { 27 | if (path_name == NULL) { 28 | return NULL; 29 | } 30 | 31 | int fd = open(path_name, O_CREAT | O_RDONLY, 0644); 32 | if (fd < 0) { 33 | std::cout << "create error " << path_name << strerror(errno) << std::endl; 34 | return NULL; 35 | } 36 | 37 | struct stat buf; 38 | int ret = stat(path_name, &buf); 39 | if (ret != 0) { 40 | std::cout << "stat error" << errno << strerror(errno) << std::endl; 41 | return NULL; 42 | } 43 | key_t key = buf.st_ino; 44 | 45 | std::cout << "shmkey = " << std::hex << key << std::endl; 46 | int shmid = shmget(key, max_size, 0666 & (~IPC_CREAT)); 47 | if (shmid < 0) { 48 | shmid = shmget(key, max_size, 0666 | IPC_CREAT); 49 | if (shmid < 0) { 50 | std::cout << "create shm error" << errno << strerror(errno) << std::endl; 51 | return NULL; 52 | } else { 53 | is_fresh = true; 54 | } 55 | } else { 56 | is_fresh = false; 57 | std::cout << "is not fresh" << std::endl; 58 | } 59 | 60 | std::cout << "shmid = " << std::dec << shmid << std::endl; 61 | return shmat(shmid, NULL, 0); 62 | } 63 | 64 | template inline void static_cast_test() { 65 | T *p = static_cast(0); 66 | (void)p; 67 | } 68 | 69 | int main(int argc, char* argv[]) { 70 | 71 | size_t total_size = InitShmPool(); 72 | bool fresh = true; 73 | void* addr = GetShm("./shm_path_file", total_size, fresh); 74 | if (addr == (void*)-1) { 75 | std::cout << "Get Shm Error:" << errno << strerror(errno) << std::endl; 76 | return -1; 77 | } 78 | 79 | int ret = ShmObjMgr::Instance().Init(addr, total_size, fresh); 80 | if (ret != 0) { 81 | std::cout << "ShmObjMgr Init Error : " << ret << std::endl; 82 | return -1; 83 | } 84 | 85 | std::cout <<"shm address = " << std::hex << addr << std::endl; 86 | 87 | if (fresh) { 88 | std::cout << "shm is fresh:" << std::endl; 89 | 90 | /// 创建对象 91 | ShmObjPtr a_pointer = ShmObjMgr::Instance().CreateObject(); 92 | if (! a_pointer) { 93 | std::cout << "Create ClassA Error: " << ret << std::endl; 94 | return -1; 95 | } 96 | 97 | /// 派生类指针可以隐士转换为基类 98 | ShmObjPtr base_pointer = a_pointer; 99 | 100 | /// 创建B对象 101 | ShmObjPtr b_pointer = ShmObjMgr::Instance().CreateObject(); 102 | if (! b_pointer) { 103 | std::cout << "Create ClassB Error: " << ret << std::endl; 104 | return -1; 105 | } 106 | 107 | 108 | std::cout << std::dec; 109 | 110 | /// 基类指针指向派生类 111 | base_pointer->Update(); 112 | 113 | /// 对象中存储普通的指针 114 | a_pointer->SetXXManager(&globalXXManager); 115 | a_pointer->SetMember(111); 116 | a_pointer->Update(); 117 | 118 | b_pointer->SetClassAObjPtr(a_pointer); 119 | b_pointer->SetMember(222); 120 | b_pointer->Update(); 121 | 122 | std::cout <<"output pointer:" << std::endl; 123 | std::cout << "a_pointer.obj_id = " << std::dec << a_pointer.obj_id().id << std::endl; 124 | std::cout << "b_pointer.obj_id = " << std::dec << b_pointer.obj_id().id << std::endl; 125 | 126 | int a = 1/0; 127 | 128 | ShmObjMgr::Instance().FreeObject(a_pointer); 129 | ShmObjMgr::Instance().FreeObject(b_pointer); 130 | 131 | } else { 132 | std::cout << std::dec; 133 | std::cout << "shm is recovery: "<< std::endl; 134 | std::cout << "input a_pointer.obj_id" << std::endl; 135 | 136 | uint64_t id_a; 137 | std::cin >> id_a; 138 | ObjId obj_id_a; 139 | obj_id_a.id = id_a; 140 | ShmObjPtr a_pointer; 141 | a_pointer.set_obj_id(obj_id_a); 142 | 143 | std::cout << "input b_pointer.obj_id" << std::endl; 144 | 145 | uint64_t id_b; 146 | std::cin >> id_b; 147 | ObjId obj_id_b; 148 | obj_id_b.id = id_b; 149 | ShmObjPtr b_pointer; 150 | b_pointer.set_obj_id(obj_id_b); 151 | 152 | if(a_pointer) { 153 | a_pointer->Update(); 154 | } 155 | 156 | if(b_pointer) { 157 | b_pointer->Update(); 158 | } 159 | 160 | /// 释放对象 161 | ShmObjMgr::Instance().FreeObject(a_pointer); 162 | ShmObjMgr::Instance().FreeObject(b_pointer); 163 | } 164 | 165 | return 0; 166 | } 167 | -------------------------------------------------------------------------------- /inc/shm_pointer/shm_pointer.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_POINTER_H_ 2 | #define SHM_POINTER_H_ 3 | 4 | #include "shm_pointer_count.h" 5 | 6 | namespace shm_obj { 7 | 8 | template class WeakShmPointer; 9 | template class ShmPointer; 10 | template class EnableShmPointerFromThis; 11 | 12 | template inline void enable_shm_pointer_from_this( ShmPointer const * ppx, ShmObjPtr const* p, const EnableShmPointerFromThis * pe ) { 13 | if( pe != 0 ) { 14 | pe->_internal_accept_owner(ppx, p); 15 | } 16 | } 17 | 18 | inline void enable_shm_pointer_from_this(...) { 19 | 20 | } 21 | 22 | template inline void shm_pointer_construct( ShmPointer * const ppx, ShmObjPtr const *p) { 23 | enable_shm_pointer_from_this(ppx, p, p->Get()); 24 | } 25 | 26 | 27 | template 28 | class ShmPointer { 29 | public: 30 | ShmPointer() {} 31 | virtual ~ShmPointer() {} 32 | 33 | template 34 | explicit ShmPointer(const ShmObjPtr& p) { 35 | shm_pointer_assert_convertible(); 36 | int ret = count_ptr_.Init(p); 37 | if (ret) { 38 | ShmObjMgr::Instance().FreeObject(p); /// 分配计数器对象失败 39 | } else { 40 | obj_ptr_ = p; 41 | shm_pointer_construct(this, &obj_ptr_); 42 | } 43 | } 44 | 45 | /// for debug 46 | template 47 | ShmPointer(const ShmObjPtr& p, const ShmObjCountPtr& count) { 48 | shm_pointer_assert_convertible(); 49 | obj_ptr_ = p; 50 | count_ptr_ = count; 51 | } 52 | 53 | template 54 | explicit ShmPointer(const WeakShmPointer& r) : count_ptr_(r.count_ptr_) { 55 | shm_pointer_assert_convertible(); 56 | obj_ptr_ = r.obj_ptr_; 57 | } 58 | 59 | template 60 | ShmPointer(const ShmPointer& r) : count_ptr_(r.count_ptr_) { 61 | shm_pointer_assert_convertible(); 62 | obj_ptr_ = r.obj_ptr_; 63 | } 64 | 65 | ///aliasing 66 | template 67 | ShmPointer(const ShmPointer& r, const ShmObjPtr& p) : count_ptr_(r.count_ptr_) { 68 | shm_pointer_assert_convertible(); 69 | obj_ptr_ = p; 70 | } 71 | 72 | template 73 | ShmPointer& operator=(const ShmPointer& r) { 74 | shm_pointer_assert_convertible(); 75 | count_ptr_ = r.count_ptr_; 76 | obj_ptr_ = r.obj_ptr_; 77 | return *this; 78 | } 79 | 80 | void Reset() { 81 | obj_ptr_.Reset(); 82 | count_ptr_.Reset(); 83 | } 84 | 85 | int Recover() { 86 | int ret = ShmObjMgr::Instance().Recover(obj_ptr_); 87 | if (ret != 0) { 88 | Reset(); 89 | } 90 | return count_ptr_.Recover(); 91 | } 92 | 93 | size_t UseCount() const { return count_ptr_.UseCount(); } 94 | 95 | operator bool() const { return obj_ptr_; } 96 | 97 | T* operator->() const { return obj_ptr_.operator->(); } 98 | 99 | T& operator*() const { return obj_ptr_.operator*(); } 100 | 101 | T* Get() const { return obj_ptr_.Get(); } 102 | 103 | /// for debug 104 | const ShmObjCountPtr & GetObjCountPtr() const { return count_ptr_; } 105 | 106 | const ShmObjPtr & GetObjPtr() const { return obj_ptr_;} 107 | 108 | private: 109 | ShmObjCountPtr count_ptr_; 110 | ShmObjPtr obj_ptr_; 111 | private: 112 | template friend class WeakShmPointer; 113 | template friend class ShmPointer; 114 | }; 115 | 116 | 117 | template inline bool operator==(ShmPointer const & a, ShmPointer const & b) { 118 | return a.Get() == b.Get(); 119 | } 120 | 121 | template inline bool operator!=(ShmPointer const & a, ShmPointer const & b) { 122 | return a.Get() != b.Get(); 123 | } 124 | 125 | template ShmPointer static_pointer_cast( ShmPointer const & r ) { 126 | (void) static_cast< ShmObjPtr * >( static_cast< ShmObjPtr * >( 0 ) ); 127 | 128 | ShmObjPtr p = static_obj_ptr_cast(r.GetObjPtr()); 129 | return ShmPointer( r, p); 130 | } 131 | 132 | template ShmPointer const_pointer_cast( ShmPointer const & r ) { 133 | (void) const_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 134 | 135 | ShmObjPtr p = const_obj_ptr_cast(r.GetObjPtr()); 136 | 137 | return ShmPointer( r, p ); 138 | } 139 | 140 | template ShmPointer dynamic_pointer_cast( ShmPointer const & r ) { 141 | (void) dynamic_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 142 | 143 | ShmObjPtr p = dynamic_obj_ptr_cast(r.GetObjPtr()); 144 | return p? ShmPointer( r, p ): ShmPointer(); 145 | } 146 | 147 | template ShmPointer reinterpret_pointer_cast( ShmPointer const & r ) { 148 | (void) reinterpret_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 149 | 150 | ShmObjPtr p = reinterpret_obj_ptr_cast(r.GetObjPtr()); 151 | return ShmPointer( r, p ); 152 | } 153 | 154 | } //namespace 155 | #endif /// SHM_POINTER_H_ 156 | -------------------------------------------------------------------------------- /example/shm_pointer_v2_test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shm_obj_mgr.h" 3 | #include "obj_creator_mgr.h" 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "shm_obj_test.h" 17 | 18 | size_t InitShmPool() { 19 | GroupId group_id; 20 | ShmObjMgr::Instance().NewClassGroup(group_id); 21 | 22 | ShmObjMgr::Instance().AddClassToGroup(group_id, 10); 23 | ShmObjMgr::Instance().AddClassToGroup(group_id, 20); 24 | return ShmObjMgr::Instance().TotalSize(); 25 | } 26 | 27 | void* GetShm(const char* path_name, size_t max_size, bool & is_fresh) { 28 | if (path_name == NULL) { 29 | return NULL; 30 | } 31 | 32 | int fd = open(path_name, O_CREAT | O_RDONLY, 0644); 33 | if (fd < 0) { 34 | std::cout << "create error " << path_name << strerror(errno) << std::endl; 35 | return NULL; 36 | } 37 | 38 | struct stat buf; 39 | int ret = stat(path_name, &buf); 40 | if (ret != 0) { 41 | std::cout << "stat error" << errno << strerror(errno) << std::endl; 42 | return NULL; 43 | } 44 | key_t key = buf.st_ino; 45 | 46 | std::cout << "shmkey = " << std::hex << key << std::endl; 47 | int shmid = shmget(key, max_size, 0666 & (~IPC_CREAT)); 48 | if (shmid < 0) { 49 | shmid = shmget(key, max_size, 0666 | IPC_CREAT); 50 | if (shmid < 0) { 51 | std::cout << "create shm error" << errno << strerror(errno) << std::endl; 52 | return NULL; 53 | } else { 54 | is_fresh = true; 55 | } 56 | } else { 57 | is_fresh = false; 58 | std::cout << "is not fresh" << std::endl; 59 | } 60 | 61 | std::cout << "shmid = " << std::hex << shmid << std::endl; 62 | return shmat(shmid, NULL, 0); 63 | } 64 | 65 | template inline void static_cast_test() { 66 | T *p = static_cast(0); 67 | (void)p; 68 | } 69 | 70 | int main(int argc, char* argv[]) { 71 | 72 | size_t total_size = InitShmPool(); 73 | bool fresh = true; 74 | void* addr = GetShm("./shm_pointer_v2_file", total_size, fresh); 75 | if (addr == (void*)-1) { 76 | std::cout << "Get Shm Error:" << errno << strerror(errno) << std::endl; 77 | return -1; 78 | } 79 | 80 | int ret = ShmObjMgr::Instance().Init(addr, total_size, fresh); 81 | if (ret != 0) { 82 | std::cout << "ShmObjMgr Init Error : " << ret << std::endl; 83 | return -1; 84 | } 85 | 86 | std::cout <<"mem address = " << std::hex << addr << std::endl; 87 | 88 | if (fresh) { 89 | std::cout << "fresh info:" << std::endl; 90 | ShmObjPtr ptr_obj_a = ShmObjMgr::Instance().CreateObject(); 91 | ShmPointer a_pointer = ShmPointer(ptr_obj_a); 92 | if (! a_pointer) { 93 | std::cout << "Create ClassA Error: " << ret << std::endl; 94 | return -1; 95 | } 96 | 97 | ShmObjPtr ptr_obj_b = ShmObjMgr::Instance().CreateObject(); 98 | ShmPointer b_pointer = ShmPointer(ptr_obj_b); 99 | 100 | if (! b_pointer) { 101 | std::cout << "Create ClassB Error: " << ret << std::endl; 102 | return -1; 103 | } 104 | 105 | 106 | std::cout << std::dec; 107 | 108 | /// 测试基类指针调用派生类 109 | /// ShmPointer base_pointer_a = a_pointer; 110 | /// base_pointer_a->Update(); 111 | 112 | /// 测试WeakShmPointer析构函数没有被调用的情况 113 | WeakShmPointer weak_pointer_b = WeakShmPointer(b_pointer); 114 | 115 | a_pointer->SetWeakShmPointerOfClassB(WeakShmPointer(b_pointer)); 116 | a_pointer->SetMember(111); 117 | a_pointer->Update(); 118 | 119 | b_pointer->SetShmPointerOfClassA(a_pointer); 120 | b_pointer->SetMember(222); 121 | 122 | 123 | 124 | b_pointer->Update(); 125 | 126 | std::cout <<"output pointer" << std::endl; 127 | /// save pointer to file 128 | std::cout << "a_pointer.obj_id = " << std::dec << ptr_obj_a.obj_id().id << std::endl; 129 | 130 | std::cout << "b_pointer.obj_id = " << std::dec << ptr_obj_b.obj_id().id << std::endl; 131 | 132 | 133 | int a = 1/0; 134 | 135 | } else { 136 | 137 | std::cout << "recovery info: "<< std::endl; 138 | 139 | std::cout << "input a_pointer.obj_id" << std::endl; 140 | uint64_t id_a; 141 | std::cin >> id_a; 142 | ObjId obj_id_a; 143 | obj_id_a.id = id_a; 144 | ShmObjPtr obj_ptr_a; 145 | obj_ptr_a.set_obj_id(obj_id_a); 146 | 147 | ShmPointer a_pointer; 148 | a_pointer.SetObjPtr(obj_ptr_a); 149 | 150 | std::cout << "input b_pointer.obj_id" << std::endl; 151 | 152 | uint64_t id_b; 153 | std::cin >> id_b; 154 | ObjId obj_id_b; 155 | obj_id_b.id = id_b; 156 | ShmObjPtr obj_ptr_b; 157 | obj_ptr_b.set_obj_id(obj_id_b); 158 | 159 | 160 | ShmPointer b_pointer; 161 | b_pointer.SetObjPtr(obj_ptr_b); 162 | 163 | if (a_pointer) { 164 | a_pointer->Update(); 165 | } 166 | 167 | if (b_pointer) { 168 | b_pointer->Update(); 169 | } 170 | } 171 | 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /inc/shm_pointer_v2/shm_pointer.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_POINTER_H_ 2 | #define SHM_POINTER_H_ 3 | 4 | #include "shm_obj_mgr.h" 5 | 6 | namespace shm_obj { 7 | 8 | template class WeakShmPointer; 9 | template class ShmPointer; 10 | template class EnableShmPointerFromThis; 11 | 12 | template inline void enable_shm_pointer_from_this( ShmPointer const * ppx, ShmObjPtr const* p, const EnableShmPointerFromThis * pe ) { 13 | if( pe != 0 ) { 14 | pe->_internal_accept_owner(ppx, p); 15 | } 16 | } 17 | 18 | inline void enable_shm_pointer_from_this(...) { 19 | 20 | } 21 | 22 | template inline void shm_pointer_construct( ShmPointer * const ppx, ShmObjPtr const *p) { 23 | enable_shm_pointer_from_this(ppx, p, p->Get()); 24 | } 25 | 26 | 27 | template 28 | class ShmPointer { 29 | public: 30 | ShmPointer() {} 31 | virtual ~ShmPointer() { Reset();} 32 | 33 | template 34 | explicit ShmPointer(const ShmObjPtr& p) { 35 | shm_pointer_assert_convertible(); 36 | obj_ptr_ = p; 37 | count_ptr_ = p; 38 | if (count_ptr_) { 39 | count_ptr_->IncUseCount(); 40 | } 41 | shm_pointer_construct(this, &obj_ptr_); 42 | } 43 | 44 | template 45 | explicit ShmPointer(const WeakShmPointer& r) : count_ptr_(r.count_ptr_) { 46 | shm_pointer_assert_convertible(); 47 | obj_ptr_ = r.obj_ptr_; 48 | if (count_ptr_) { 49 | count_ptr_->IncUseCount(); 50 | } 51 | } 52 | 53 | template 54 | explicit ShmPointer(const ShmPointer& r) { 55 | shm_pointer_assert_convertible(); 56 | obj_ptr_ = r.obj_ptr_; 57 | count_ptr_ = r.count_pt_; 58 | if (count_ptr_) { 59 | count_ptr_->IncUseCount(); 60 | } 61 | } 62 | 63 | ///aliasing 64 | template 65 | ShmPointer(const ShmPointer& r, const ShmObjPtr& p) { 66 | shm_pointer_assert_convertible(); 67 | obj_ptr_ = p; 68 | count_ptr_ = r.count_ptr_; 69 | if (count_ptr_) { 70 | count_ptr_->IncUseCount(); 71 | } 72 | } 73 | 74 | template 75 | ShmPointer& operator=(const ShmPointer& r) { 76 | shm_pointer_assert_convertible(); 77 | obj_ptr_ = r.obj_ptr_; 78 | 79 | if (r.count_ptr_) { 80 | r.count_ptr_->IncUseCount(); 81 | } 82 | 83 | if (count_ptr_) { 84 | count_ptr_->DecUseCount(); 85 | if (count_ptr_->UseCount() == 0) { 86 | ShmObjMgr::Instance().FreeObject(count_ptr_); 87 | } 88 | } 89 | 90 | count_ptr_ = r.count_ptr_; 91 | return *this; 92 | } 93 | 94 | void Reset() { 95 | if (count_ptr_) { 96 | count_ptr_->DecUseCount(); 97 | if (count_ptr_->UseCount() == 0) { 98 | ShmObjMgr::Instance().FreeObject(count_ptr_); 99 | } 100 | } 101 | obj_ptr_.Reset(); 102 | count_ptr_.Reset(); 103 | } 104 | 105 | int Recover() { 106 | int ret = ShmObjMgr::Instance().Recover(obj_ptr_); 107 | if (ret) { 108 | count_ptr_.Reset(); 109 | obj_ptr_.Reset(); 110 | return ret; 111 | } 112 | count_ptr_ = obj_ptr_; 113 | return 0; 114 | } 115 | 116 | size_t UseCount() const { return count_ptr_ ? count_ptr_->UseCount() : 0; } 117 | 118 | operator bool() const { return obj_ptr_; } 119 | 120 | T* operator->() const { return obj_ptr_.operator->(); } 121 | 122 | T& operator*() const { return obj_ptr_.operator*(); } 123 | 124 | T* Get() const { return obj_ptr_.Get(); } 125 | 126 | const ShmObjPtr & GetObjPtr() const { return obj_ptr_;} 127 | 128 | /// for debug 129 | template 130 | void SetObjPtr(const ShmObjPtr& p) { 131 | shm_pointer_assert_convertible(); 132 | obj_ptr_ = p; 133 | count_ptr_ = obj_ptr_; 134 | } 135 | 136 | private: 137 | ShmObjPtr count_ptr_; /// 计数器类 138 | ShmObjPtr obj_ptr_; 139 | private: 140 | template friend class WeakShmPointer; 141 | template friend class ShmPointer; 142 | }; 143 | 144 | 145 | template inline bool operator==(ShmPointer const & a, ShmPointer const & b) { 146 | return a.Get() == b.Get(); 147 | } 148 | 149 | template inline bool operator!=(ShmPointer const & a, ShmPointer const & b) { 150 | return a.Get() != b.Get(); 151 | } 152 | 153 | template ShmPointer static_pointer_cast( ShmPointer const & r ) { 154 | (void) static_cast< ShmObjPtr * >( static_cast< ShmObjPtr * >( 0 ) ); 155 | 156 | ShmObjPtr p = static_obj_ptr_cast(r.GetObjPtr()); 157 | return ShmPointer( r, p); 158 | } 159 | 160 | template ShmPointer const_pointer_cast( ShmPointer const & r ) { 161 | (void) const_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 162 | 163 | ShmObjPtr p = const_obj_ptr_cast(r.GetObjPtr()); 164 | 165 | return ShmPointer( r, p ); 166 | } 167 | 168 | template ShmPointer dynamic_pointer_cast( ShmPointer const & r ) { 169 | (void) dynamic_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 170 | 171 | ShmObjPtr p = dynamic_obj_ptr_cast(r.GetObjPtr()); 172 | return p? ShmPointer( r, p ): ShmPointer(); 173 | } 174 | 175 | template ShmPointer reinterpret_pointer_cast( ShmPointer const & r ) { 176 | (void) reinterpret_cast< ShmObjPtr* >( static_cast< ShmObjPtr* >( 0 ) ); 177 | 178 | ShmObjPtr p = reinterpret_obj_ptr_cast(r.GetObjPtr()); 179 | return ShmPointer( r, p ); 180 | } 181 | 182 | } //namespace 183 | #endif /// SHM_POINTER_H_ 184 | -------------------------------------------------------------------------------- /example/shm_pointer_test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "shm_obj_mgr.h" 3 | #include "obj_creator_mgr.h" 4 | #include "shm_pointer.h" 5 | #include "weak_shm_pointer.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "shm_obj_test.h" 17 | 18 | size_t InitShmPool() { 19 | GroupId group_id; 20 | ShmObjMgr::Instance().NewClassGroup(group_id); 21 | 22 | ShmObjMgr::Instance().AddClassToGroup(group_id, 1000); ///注册多少合适呢? 23 | ShmObjMgr::Instance().AddClassToGroup(group_id, 10); 24 | ShmObjMgr::Instance().AddClassToGroup(group_id, 20); 25 | return ShmObjMgr::Instance().TotalSize(); 26 | } 27 | 28 | void* GetShm(const char* path_name, size_t max_size, bool & is_fresh) { 29 | if (path_name == NULL) { 30 | return NULL; 31 | } 32 | 33 | int fd = open(path_name, O_CREAT | O_RDONLY, 0644); 34 | if (fd < 0) { 35 | std::cout << "create error " << path_name << strerror(errno) << std::endl; 36 | return NULL; 37 | } 38 | 39 | struct stat buf; 40 | int ret = stat(path_name, &buf); 41 | if (ret != 0) { 42 | std::cout << "stat error" << errno << strerror(errno) << std::endl; 43 | return NULL; 44 | } 45 | key_t key = buf.st_ino; 46 | 47 | std::cout << "shmkey = " << std::hex << key << std::endl; 48 | int shmid = shmget(key, max_size, 0666 & (~IPC_CREAT)); 49 | if (shmid < 0) { 50 | shmid = shmget(key, max_size, 0666 | IPC_CREAT); 51 | if (shmid < 0) { 52 | std::cout << "create shm error" << errno << strerror(errno) << std::endl; 53 | return NULL; 54 | } else { 55 | is_fresh = true; 56 | } 57 | } else { 58 | is_fresh = false; 59 | std::cout << "is not fresh" << std::endl; 60 | } 61 | 62 | std::cout << "shmid = " << std::hex << shmid << std::endl; 63 | return shmat(shmid, NULL, 0); 64 | } 65 | 66 | template inline void static_cast_test() { 67 | T *p = static_cast(0); 68 | (void)p; 69 | } 70 | 71 | int main(int argc, char* argv[]) { 72 | 73 | size_t total_size = InitShmPool(); 74 | bool fresh = true; 75 | void* addr = GetShm("./shm_pointer_path_file", total_size, fresh); 76 | if (addr == (void*)-1) { 77 | std::cout << "Get Shm Error:" << errno << strerror(errno) << std::endl; 78 | return -1; 79 | } 80 | 81 | int ret = ShmObjMgr::Instance().Init(addr, total_size, fresh); 82 | if (ret != 0) { 83 | std::cout << "ShmObjMgr Init Error : " << ret << std::endl; 84 | return -1; 85 | } 86 | 87 | std::cout <<"mem address = " << std::hex << addr << std::endl; 88 | 89 | if (fresh) { 90 | std::cout << "fresh info:" << std::endl; 91 | ShmObjPtr ptr_obj_a = ShmObjMgr::Instance().CreateObject(); 92 | ShmPointer a_pointer = ShmPointer(ptr_obj_a); 93 | if (! a_pointer) { 94 | std::cout << "Create ClassA Error: " << ret << std::endl; 95 | return -1; 96 | } 97 | 98 | ShmObjPtr ptr_obj_b = ShmObjMgr::Instance().CreateObject(); 99 | ShmPointer b_pointer = ShmPointer(ptr_obj_b); 100 | 101 | if (! b_pointer) { 102 | std::cout << "Create ClassB Error: " << ret << std::endl; 103 | return -1; 104 | } 105 | 106 | 107 | std::cout << std::dec; 108 | 109 | /// 测试基类指针调用派生类 110 | /// ShmPointer base_pointer_a = a_pointer; 111 | /// base_pointer_a->Update(); 112 | 113 | /// 测试WeakShmPointer析构函数没有被调用的情况 114 | WeakShmPointer weak_pointer_b = WeakShmPointer(b_pointer); 115 | 116 | a_pointer->SetWeakShmPointerOfClassB(WeakShmPointer(b_pointer)); 117 | a_pointer->SetMember(111); 118 | a_pointer->Update(); 119 | 120 | b_pointer->SetShmPointerOfClassA(a_pointer); 121 | b_pointer->SetMember(222); 122 | b_pointer->Update(); 123 | 124 | std::cout <<"output pointer" << std::endl; 125 | /// save pointer to file 126 | std::cout << "a_pointer.obj_id = " << std::dec << ptr_obj_a.obj_id().id << std::endl; 127 | std::cout << "a_pointer.count_id = " << std::dec << a_pointer.GetObjCountPtr().GetObjCountPtr().obj_id().id << std::endl; 128 | std::cout << "b_pointer.obj_id = " << std::dec << ptr_obj_b.obj_id().id << std::endl; 129 | std::cout << "a_pointer.count_id = " << std::dec << b_pointer.GetObjCountPtr().GetObjCountPtr().obj_id().id << std::endl; 130 | 131 | int a = 1/0; 132 | 133 | } else { 134 | 135 | std::cout << "recovery info: "<< std::endl; 136 | 137 | std::cout << "input a_pointer.obj_id" << std::endl; 138 | uint64_t id_a; 139 | std::cin >> id_a; 140 | ObjId obj_id_a; 141 | obj_id_a.id = id_a; 142 | ShmObjPtr obj_ptr_a; 143 | obj_ptr_a.set_obj_id(obj_id_a); 144 | 145 | std::cout << "input a_pointer.count_id" <> count_id_a; 148 | ObjId obj_count_id_a; 149 | obj_count_id_a.id = count_id_a; 150 | ShmObjPtr obj_count_ptr_a; 151 | obj_count_ptr_a.set_obj_id(obj_count_id_a); 152 | 153 | ShmObjCountPtr shm_obj_count_ptr_a; 154 | shm_obj_count_ptr_a.SetObjCountPtr(obj_count_ptr_a); 155 | ShmPointer a_pointer = ShmPointer(obj_ptr_a, shm_obj_count_ptr_a); 156 | 157 | std::cout << "input b_pointer.obj_id" << std::endl; 158 | 159 | uint64_t id_b; 160 | std::cin >> id_b; 161 | ObjId obj_id_b; 162 | obj_id_b.id = id_b; 163 | ShmObjPtr obj_ptr_b; 164 | obj_ptr_b.set_obj_id(obj_id_b); 165 | 166 | 167 | std::cout << "input b_pointer.count_id" <> count_id_b; 170 | ObjId obj_count_id_b; 171 | obj_count_id_b.id = count_id_b; 172 | ShmObjPtr obj_count_ptr_b; 173 | obj_count_ptr_b.set_obj_id(obj_count_id_b); 174 | 175 | ShmObjCountPtr shm_obj_count_ptr_b; 176 | shm_obj_count_ptr_b.SetObjCountPtr(obj_count_ptr_b); 177 | ShmPointer b_pointer = ShmPointer(obj_ptr_b, shm_obj_count_ptr_b); 178 | 179 | if (a_pointer) { 180 | a_pointer->Update(); 181 | } 182 | 183 | if (b_pointer) { 184 | b_pointer->Update(); 185 | } 186 | } 187 | 188 | return 0; 189 | } 190 | -------------------------------------------------------------------------------- /inc/shm_pointer/shm_pointer_count.h: -------------------------------------------------------------------------------- 1 | #ifndef SHM_POINTER_COUNT_H_ 2 | #define SHM_POINTER_COUNT_H_ 3 | 4 | #include "log.h" 5 | #include "shm_obj.h" 6 | #include "obj_creator_mgr.h" 7 | #include "shm_obj_mgr.h" 8 | 9 | #include 10 | 11 | namespace shm_obj { 12 | 13 | class ShmObjMgr; 14 | 15 | class ShmObjCount : public ShmObj { 16 | public: 17 | DeclareTypeName(ShmObjCount); 18 | public: 19 | ShmObjCount() { 20 | if(System::IsResume()) { 21 | return; 22 | } else { 23 | use_count_ = 1; 24 | weak_count_ = 1; 25 | } 26 | } 27 | 28 | ~ShmObjCount() {} 29 | 30 | private: 31 | inline size_t IncUseCount() { 32 | return ++use_count_; 33 | } 34 | 35 | inline size_t DecUseCount() { 36 | return --use_count_; 37 | } 38 | 39 | inline size_t IncWeakCount() { 40 | return ++weak_count_; 41 | } 42 | 43 | inline size_t DecWeakCount() { 44 | return --weak_count_; 45 | } 46 | 47 | inline size_t WeakCount() { 48 | return weak_count_; 49 | } 50 | 51 | public: 52 | void SetShmObjPtr(const ShmObjPtr & obj_ptr) { 53 | shm_obj_ptr_ = obj_ptr; 54 | } 55 | 56 | void SetSelfPtr(const ShmObjPtr & self_ptr) { 57 | self_ptr_ = self_ptr; 58 | } 59 | private: 60 | /// 释放对象 61 | void Dispose() { 62 | ShmObjMgr::Instance().FreeObject(shm_obj_ptr_); 63 | } 64 | 65 | /// 释放自身 66 | void Destroy() { 67 | ShmObjMgr::Instance().FreeObject(self_ptr_); 68 | } 69 | 70 | public: 71 | 72 | inline size_t UseCount() { 73 | return use_count_; 74 | } 75 | 76 | void AddRef() { 77 | IncUseCount(); 78 | } 79 | 80 | void Release() { 81 | DecUseCount(); 82 | if(UseCount() == 0) { 83 | Dispose(); 84 | WeakRelease(); 85 | } 86 | } 87 | 88 | void WeakAddRef() { 89 | IncWeakCount(); 90 | } 91 | 92 | void WeakRelease() { 93 | DecWeakCount(); 94 | if (WeakCount() == 0) { 95 | Destroy(); 96 | } 97 | } 98 | 99 | virtual void Recover() { 100 | } 101 | 102 | void Reset() { 103 | shm_obj_ptr_.Reset(); 104 | } 105 | 106 | private: 107 | size_t use_count_; 108 | size_t weak_count_; 109 | 110 | private: 111 | ShmObjPtr shm_obj_ptr_; 112 | ShmObjPtr self_ptr_; /// for free self 113 | }; 114 | 115 | ImplmentTypeName(ShmObjCount); 116 | 117 | class WeakShmObjCountPtr; 118 | 119 | class ShmObjCountPtr { 120 | public: 121 | 122 | friend class WeakShmObjCountPtr; 123 | 124 | ShmObjCountPtr() {} 125 | virtual ~ShmObjCountPtr() { Reset(); } 126 | 127 | template 128 | ShmObjCountPtr(const ShmObjPtr& p) { 129 | obj_count_ptr_ = ShmObjMgr::Instance().CreateObject(); 130 | if (! obj_count_ptr_) { 131 | LOG_ERROR("Create ShmObjCount Error, Free ShmObj[%zu]", p.obj_id().id); 132 | ShmObjMgr::Instance().FreeObject(p); 133 | assert(obj_count_ptr_); 134 | } 135 | 136 | obj_count_ptr_->SetShmObjPtr(p); 137 | obj_count_ptr_->SetSelfPtr(obj_count_ptr_); 138 | } 139 | 140 | template 141 | int Init(const ShmObjPtr &p) { 142 | obj_count_ptr_ = ShmObjMgr::Instance().CreateObject(); 143 | if (! obj_count_ptr_) { 144 | LOG_ERROR("Create ShmObjCount Error, Free ShmObj[%zu]", p.obj_id().id); 145 | return -1; 146 | } else { 147 | obj_count_ptr_->SetShmObjPtr(p); 148 | obj_count_ptr_->SetSelfPtr(obj_count_ptr_); 149 | } 150 | return 0; 151 | } 152 | 153 | explicit ShmObjCountPtr(const ShmObjCountPtr& r) : obj_count_ptr_(r.obj_count_ptr_) { 154 | if (obj_count_ptr_) { 155 | obj_count_ptr_->AddRef(); 156 | } 157 | } 158 | 159 | explicit ShmObjCountPtr(const WeakShmObjCountPtr& r); 160 | 161 | ShmObjCountPtr& operator=(const ShmObjCountPtr& r) { 162 | if (r.obj_count_ptr_) { 163 | r.obj_count_ptr_->AddRef(); 164 | } 165 | 166 | if (obj_count_ptr_) { 167 | obj_count_ptr_->Release(); 168 | } 169 | 170 | obj_count_ptr_ = r.obj_count_ptr_; 171 | return *this; 172 | 173 | } 174 | 175 | /// recover ob_ptr_ by obj_id_ when system resume 176 | int Recover() { 177 | int ret = ShmObjMgr::Instance().Recover(obj_count_ptr_); 178 | if (ret != 0) { 179 | LOG_ERROR("ShmObjCountPtr Recovery Error| obj_count_ptr[%zu]", obj_count_ptr_.obj_id().id); 180 | obj_count_ptr_.Reset(); 181 | } 182 | return ret; 183 | } 184 | 185 | void Reset() { 186 | if (obj_count_ptr_) { 187 | obj_count_ptr_->Release(); 188 | obj_count_ptr_.Reset(); 189 | } 190 | } 191 | 192 | size_t UseCount() const { 193 | return obj_count_ptr_ ? obj_count_ptr_->UseCount() : 0; 194 | } 195 | 196 | /// for debug 197 | const ShmObjPtr & GetObjCountPtr() const { 198 | return obj_count_ptr_; 199 | } 200 | 201 | void SetObjCountPtr(const ShmObjPtr & count_ptr) { 202 | obj_count_ptr_ = count_ptr; 203 | } 204 | 205 | private: 206 | ShmObjPtr obj_count_ptr_; 207 | }; 208 | 209 | 210 | class WeakShmObjCountPtr { 211 | public: 212 | 213 | friend class ShmObjCountPtr; 214 | 215 | WeakShmObjCountPtr() {} 216 | 217 | ~WeakShmObjCountPtr() { Reset(); } 218 | 219 | explicit WeakShmObjCountPtr(const WeakShmObjCountPtr & r) : obj_count_ptr_(r.obj_count_ptr_) { 220 | if (obj_count_ptr_) { 221 | obj_count_ptr_->WeakAddRef(); 222 | } 223 | } 224 | 225 | explicit WeakShmObjCountPtr(const ShmObjCountPtr & r) : obj_count_ptr_(r.obj_count_ptr_) { 226 | if (obj_count_ptr_) { 227 | obj_count_ptr_->WeakAddRef(); 228 | } 229 | } 230 | 231 | WeakShmObjCountPtr& operator=(const ShmObjCountPtr& r) { 232 | if (r.obj_count_ptr_) { 233 | r.obj_count_ptr_->WeakAddRef(); 234 | } 235 | 236 | if (obj_count_ptr_) { 237 | obj_count_ptr_->WeakRelease(); 238 | } 239 | 240 | obj_count_ptr_ = r.obj_count_ptr_; 241 | 242 | return *this; 243 | } 244 | 245 | WeakShmObjCountPtr& operator=(const WeakShmObjCountPtr& r) { 246 | if (r.obj_count_ptr_) { 247 | r.obj_count_ptr_->WeakAddRef(); 248 | } 249 | 250 | if (obj_count_ptr_) { 251 | obj_count_ptr_->WeakRelease(); 252 | } 253 | 254 | obj_count_ptr_ = r.obj_count_ptr_; 255 | return *this; 256 | } 257 | 258 | /// recover ob_ptr_ by obj_id_ when system resume 259 | int Recover() { 260 | int ret = ShmObjMgr::Instance().Recover(obj_count_ptr_); 261 | if (ret != 0) { 262 | LOG_ERROR("WeakShmObjCountPtr Recovery Error|obj_count_ptr[%zu]", obj_count_ptr_.obj_id().id); 263 | obj_count_ptr_.Reset(); 264 | } 265 | return ret; 266 | } 267 | 268 | size_t UseCount() const { 269 | return obj_count_ptr_ ? obj_count_ptr_->UseCount() : 0; 270 | } 271 | 272 | void Reset() { 273 | if (obj_count_ptr_) { 274 | obj_count_ptr_->WeakRelease(); 275 | obj_count_ptr_.Reset(); 276 | } 277 | } 278 | 279 | private: 280 | ShmObjPtr obj_count_ptr_; 281 | }; 282 | 283 | ShmObjCountPtr::ShmObjCountPtr(const WeakShmObjCountPtr& r): obj_count_ptr_(r.obj_count_ptr_) { 284 | if (obj_count_ptr_) { 285 | obj_count_ptr_->AddRef(); 286 | } 287 | } 288 | 289 | } //namespace 290 | 291 | #endif /// SHM_POINTER_BASE_H_ -------------------------------------------------------------------------------- /src/shm_obj/shm_pool.cpp: -------------------------------------------------------------------------------- 1 | #include "shm_pool.h" 2 | #include "log.h" 3 | #include "system.h" 4 | #include "obj_creator_mgr.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace shm_obj { 10 | 11 | ShmPool::ShmPool() { 12 | memset(&tmp_group_info_, 0, sizeof(tmp_group_info_)); 13 | shm_pool_header_ = NULL; 14 | } 15 | 16 | int ShmPool::NewClassGroup(GroupId & group_id) { 17 | if (tmp_group_info_.group_num >= MAX_CLASS_GROUP_NUM) { 18 | return -1; 19 | } 20 | 21 | /// 直接用数组下标作为索引, 加快查找 22 | group_id = tmp_group_info_.group_num; 23 | tmp_group_info_.group[tmp_group_info_.group_num].group_id = group_id; 24 | tmp_group_info_.group_num++; 25 | return 0; 26 | } 27 | 28 | int ShmPool::AddClassToGroup(GroupId & group_id,ClassId class_id,size_t class_size,size_t obj_count) { 29 | if (group_id < 0 || group_id >= tmp_group_info_.group_num) { 30 | LOG_ERROR("cannot find group| group_id[%d]", group_id); 31 | return -1; 32 | } 33 | 34 | if (tmp_group_info_.group[group_id].class_id_num >= MAX_CLASS_PER_GROUP) { 35 | LOG_ERROR("group is full| group_id[%d]", group_id); 36 | return -2; 37 | } 38 | 39 | tmp_group_info_.group[group_id].class_id[tmp_group_info_.group[group_id].class_id_num] = class_id; 40 | tmp_group_info_.group[group_id].class_id_num++; 41 | tmp_group_info_.group[group_id].max_obj_count = tmp_group_info_.group[group_id].max_obj_count >= obj_count ? tmp_group_info_.group[group_id].max_obj_count : obj_count; 42 | tmp_group_info_.group[group_id].max_class_size = tmp_group_info_.group[group_id].max_class_size >= class_size ? tmp_group_info_.group[group_id].max_class_size : class_size; 43 | return 0; 44 | } 45 | 46 | 47 | size_t ShmPool::TotalSize() const { 48 | size_t total_size = 0; 49 | for (int i = 0; i < tmp_group_info_.group_num; i++) { 50 | total_size += sizeof(ObjGroup) + tmp_group_info_.group[i].max_obj_count * (sizeof(ObjIndex) + tmp_group_info_.group[i].max_class_size); 51 | } 52 | 53 | total_size += sizeof(ShmPoolHeader); 54 | return total_size; 55 | } 56 | 57 | 58 | int ShmPool::Init(void * mem,size_t max_size,bool fresh) { 59 | if (mem == NULL || max_size < TotalSize()) { 60 | LOG_ERROR("invalid param|mem[%p], max_size[%zu]", mem, max_size); 61 | return -1; 62 | } 63 | 64 | if (fresh) { 65 | LOG_INFO("Shm Pool Is Fresh\n"); 66 | shm_pool_header_ = reinterpret_cast(mem); 67 | shm_pool_header_->max_size = TotalSize(); 68 | shm_pool_header_->group_info = tmp_group_info_; 69 | 70 | ObjGroup* obj_group = reinterpret_cast((char*)mem + sizeof(ShmPoolHeader)); 71 | for(int i = 0; i < shm_pool_header_->group_info.group_num; i++) { 72 | obj_group->group_id = shm_pool_header_->group_info.group[i].group_id; 73 | obj_group->max_obj_count = shm_pool_header_->group_info.group[i].max_obj_count; 74 | obj_group->max_class_size = shm_pool_header_->group_info.group[i].max_class_size; 75 | obj_group->group_size = sizeof(ObjGroup) + shm_pool_header_->group_info.group[i].max_obj_count * (shm_pool_header_->group_info.group[i].max_class_size + sizeof(ObjIndex)); 76 | obj_group->class_id_num = shm_pool_header_->group_info.group[i].class_id_num; 77 | for (int j = 0; j < shm_pool_header_->group_info.group[i].class_id_num; j++) { 78 | obj_group->class_id[j] = shm_pool_header_->group_info.group[i].class_id[j]; 79 | } 80 | shm_pool_header_->group_info.group[i].obj_group = obj_group; 81 | 82 | InitObjGroup(obj_group); 83 | obj_group = reinterpret_cast((char*)obj_group + obj_group->group_size); 84 | } 85 | } else { 86 | LOG_INFO("Shm Pool Is Not Fresh, Begin Recover Set System Resume = true ================"); 87 | System::SetSystemResume(true); 88 | /// recover 89 | shm_pool_header_ = reinterpret_cast(mem); 90 | if (shm_pool_header_->max_size != max_size) { 91 | LOG_ERROR("ShmPoolHeader MISMATCH|max_size [%zu, %zu] mismatch", shm_pool_header_->max_size, max_size); 92 | return -1; 93 | } 94 | 95 | ObjGroup* obj_group = reinterpret_cast(((char*)mem + sizeof(ShmPoolHeader))); 96 | for (int i = 0; i < shm_pool_header_->group_info.group_num; i++) { 97 | shm_pool_header_->group_info.group[i].obj_group = obj_group; 98 | 99 | if (obj_group->class_id_num != shm_pool_header_->group_info.group[i].class_id_num) { 100 | LOG_ERROR("ObjGroup[%d] MISMATCH|class_id_num[%d, %d] mismatch", i, obj_group->class_id_num, shm_pool_header_->group_info.group[i].class_id_num); 101 | return -1; 102 | } 103 | 104 | for (int j = 0; j < obj_group->class_id_num; j++) { 105 | if (obj_group->class_id[j] != shm_pool_header_->group_info.group[i].class_id[j]) { 106 | LOG_ERROR("ObjGroup[%d] MISMATCH|class_id[%d] [%d, %d] mismatch", i, j, obj_group->class_id[j], shm_pool_header_->group_info.group[i].class_id[j]); 107 | return -1; 108 | } 109 | } 110 | 111 | if (obj_group->group_id != shm_pool_header_->group_info.group[i].group_id) { 112 | LOG_ERROR("ObjGroup[%d] MISMATCH|group_id[%d, %d] mismatch", i, obj_group->group_id, shm_pool_header_->group_info.group[i].group_id); 113 | return -1; 114 | } 115 | 116 | if (obj_group->max_class_size != shm_pool_header_->group_info.group[i].max_class_size) { 117 | LOG_ERROR("ObjGroup[%d] MISMATCH|max_class_size[%zu, %zu] mismatch", i, obj_group->max_class_size, shm_pool_header_->group_info.group[i].max_class_size); 118 | return -1; 119 | } 120 | 121 | if (obj_group->max_obj_count != shm_pool_header_->group_info.group[i].max_obj_count) { 122 | LOG_ERROR("ObjGroup[%d] MISMATCH|max_obj_count[%u, %u] mismatch", i, obj_group->max_obj_count, shm_pool_header_->group_info.group[i].max_obj_count); 123 | return -1; 124 | } 125 | 126 | size_t group_size = sizeof(ObjGroup) + (sizeof(ObjIndex) + obj_group->max_class_size) * obj_group->max_obj_count; 127 | if (obj_group->group_size != group_size) { 128 | LOG_ERROR("ObjGroup[%d] MISMATCH|group_size[%zu, %zu] mismatch", i, obj_group->group_size, group_size); 129 | return -1; 130 | } 131 | 132 | obj_group->obj_index_ = reinterpret_cast((char*)obj_group + sizeof(ObjGroup)); 133 | obj_group->obj_node_ = reinterpret_cast((char*)obj_group->obj_index_ + sizeof(ObjIndex) * obj_group->max_obj_count); 134 | 135 | unsigned int used_obj_count = 0; 136 | int index = obj_group->used_index_head; 137 | while(index != -1) { 138 | used_obj_count++; 139 | void* obj = (void*)(obj_group->obj_node_ + index * obj_group->max_class_size); 140 | /// recovery obj; 141 | ShmObj* shm_obj = reinterpret_cast(ObjectCreatorMgr::Instance().CreateObject(obj, obj_group->obj_index_[index].obj_id.class_id)); 142 | shm_obj->Recover(); 143 | index = obj_group->obj_index_[index].next; 144 | } 145 | 146 | if (obj_group->used_obj_count != used_obj_count) { 147 | LOG_ERROR("ObjGroup[%d] MISMATCH|used_obj_count[%d, %d] mismatch", i, obj_group->used_obj_count, used_obj_count); 148 | return -1; 149 | } 150 | unsigned int free_obj_count = 0; 151 | index = obj_group->free_index_head; 152 | while(index != -1) { 153 | free_obj_count++; 154 | index = obj_group->obj_index_[index].next; 155 | } 156 | 157 | if (obj_group->used_obj_count + free_obj_count != obj_group->max_obj_count) { 158 | LOG_ERROR("ObjGroup[%d] MISMATCH|max_obj_count[%d] used[%d] free[%d] mismatch", i, obj_group->max_obj_count, obj_group->used_obj_count, free_obj_count); 159 | return -1; 160 | } 161 | 162 | obj_group = reinterpret_cast((char*)obj_group + obj_group->group_size); 163 | 164 | } 165 | LOG_INFO("========End Recover, Set System Resume = false"); 166 | System::SetSystemResume(false); 167 | } 168 | 169 | LOG_INFO("ShmPool Init Success"); 170 | 171 | return 0; 172 | } 173 | 174 | void ShmPool::InitObjGroup(ObjGroup * obj_group) { 175 | obj_group->obj_index_ = reinterpret_cast((char*)obj_group + sizeof(ObjGroup)); 176 | obj_group->obj_node_ = reinterpret_cast((char*)obj_group->obj_index_ + sizeof(ObjIndex) * obj_group->max_obj_count); 177 | obj_group->used_index_head = -1; 178 | obj_group->free_index_head = 0; 179 | obj_group->used_obj_count = 0; 180 | obj_group->seq = 0; ///初始可以为零,每次加一后再使用 181 | 182 | unsigned int i = 0; 183 | for( ; i < obj_group->max_obj_count - 1; i++) { 184 | obj_group->obj_index_[i].next = i + 1; 185 | obj_group->obj_index_[i].obj_id.id = 0; 186 | } 187 | 188 | obj_group->obj_index_[i].next = -1; 189 | obj_group->obj_index_[i].obj_id.id = 0; 190 | } 191 | 192 | 193 | ShmPool::ObjGroup* ShmPool::FindGroupByClassId(ClassId class_id) { 194 | for (int i = 0; i < shm_pool_header_->group_info.group_num; i++) { 195 | for (int j = 0; j < shm_pool_header_->group_info.group[i].class_id_num; j++) { 196 | if (shm_pool_header_->group_info.group[i].class_id[j] == class_id) { 197 | return shm_pool_header_->group_info.group[i].obj_group; 198 | } 199 | } 200 | } 201 | return NULL; 202 | } 203 | 204 | ShmPool::ObjGroup* ShmPool::FindGroupByGroupId(GroupId group_id) { 205 | if (group_id < 0 || group_id >= shm_pool_header_->group_info.group_num) { 206 | return NULL; 207 | } 208 | 209 | return shm_pool_header_->group_info.group[group_id].obj_group; 210 | } 211 | 212 | void* ShmPool::NewObject(ClassId class_id, ObjId & obj_id) { 213 | ObjGroup* obj_group = FindGroupByClassId(class_id); 214 | if (obj_group == NULL) { 215 | LOG_ERROR("cannot find obj_group for class_id[%d]", class_id); 216 | return NULL; 217 | } 218 | 219 | void* obj = NewObject(obj_group, class_id, obj_id); 220 | if (obj) { 221 | return ObjectCreatorMgr::Instance().CreateObject(obj, class_id); 222 | } else { 223 | return NULL; 224 | } 225 | } 226 | 227 | void* ShmPool::GetObject(const ObjId & obj_id) { 228 | ObjGroup* obj_group = FindGroupByGroupId(obj_id.group_id); 229 | if (obj_group == NULL) { 230 | return NULL; 231 | } 232 | 233 | return GetObject(obj_group, obj_id); 234 | } 235 | 236 | void ShmPool::FreeObject(const ObjId & obj_id) { 237 | ObjGroup* obj_group = FindGroupByGroupId(obj_id.group_id); 238 | if (obj_group == NULL) { 239 | LOG_ERROR("cannot find obj_group for group_id[%d]", obj_id.group_id); 240 | return; 241 | } 242 | FreeObject(obj_group, obj_id); 243 | } 244 | 245 | void* ShmPool::NewObject(ObjGroup* obj_group, ClassId class_id, ObjId & obj_id) { 246 | if (obj_group->free_index_head == -1 || obj_group->used_obj_count >= obj_group->max_obj_count) { 247 | LOG_ERROR("obj_group used up| group_id[%d] free_index_head[%d] max_obj_count[%d] used_obj_count[%d]", 248 | obj_group->group_id, obj_group->free_index_head, obj_group->max_obj_count, obj_group->used_obj_count); 249 | return NULL; 250 | } 251 | 252 | int index = obj_group->free_index_head; 253 | obj_group->free_index_head = obj_group->obj_index_[index].next; 254 | 255 | obj_group->obj_index_[index].next = obj_group->used_index_head; 256 | obj_group->used_index_head = index; 257 | 258 | obj_group->used_obj_count++; 259 | obj_group->seq++; 260 | if(obj_group->seq == 0) { 261 | obj_group->seq++; 262 | } 263 | 264 | obj_id.group_id = obj_group->group_id; 265 | obj_id.index = index; 266 | obj_id.class_id = class_id; 267 | obj_id.seq = obj_group->seq; 268 | 269 | obj_group->obj_index_[index].obj_id = obj_id; 270 | 271 | void* obj =(void *)(obj_group->obj_node_ + index * obj_group->max_class_size); 272 | /// NOTE: important!!! 273 | memset(obj, 0, obj_group->max_class_size); 274 | 275 | return obj; 276 | } 277 | 278 | void* ShmPool::GetObject(ObjGroup* obj_group, const ObjId & obj_id) { 279 | if (obj_group->used_obj_count <= 0 || obj_group->used_index_head == -1) { 280 | LOG_ERROR("obj_group empty|group_id[%d]", obj_group->group_id); 281 | return NULL; 282 | } 283 | 284 | /* 285 | int index = obj_group->used_index_head; 286 | while (index != -1) { 287 | if (index == obj_id.index) { 288 | break; 289 | } 290 | index = obj_group->obj_index_[index].next; 291 | } 292 | 293 | if (index != obj_id.index) { 294 | LOG_ERROR("%s:get obj error|obj_group[%d] obj_index[%d] is not used", __FUNCTION__, obj_group->group_id, obj_id.index); 295 | return NULL; 296 | } 297 | 298 | */ 299 | if (obj_group->obj_index_[obj_id.index].obj_id.id != obj_id.id) { 300 | LOG_ERROR("get obj error|obj_group[%d] obj_id[%zu, %zu] mismatch", 301 | obj_group->group_id, obj_group->obj_index_[obj_id.index].obj_id.id, obj_id.id); 302 | return NULL; 303 | } 304 | 305 | return (void *)(obj_group->obj_node_ + obj_id.index * obj_group->max_class_size); 306 | 307 | } 308 | 309 | void ShmPool::FreeObject(ObjGroup* obj_group, const ObjId & obj_id) { 310 | if (obj_group->used_obj_count <= 0 || obj_group->used_index_head == -1) { 311 | LOG_ERROR("obj_group not used|group_id[%d] used_obj_count[%d] used_index_head[%d]", 312 | obj_group->group_id, obj_group->used_obj_count, obj_group->used_index_head); 313 | return; 314 | } 315 | 316 | /// 先检查obj_id是否匹配 317 | if (obj_group->obj_index_[obj_id.index].obj_id.id != obj_id.id) { 318 | LOG_ERROR("get obj error|obj_group[%d] obj_id[%zu, %zu] mismatch", 319 | obj_group->group_id, obj_group->obj_index_[obj_id.index].obj_id.id, obj_id.id); 320 | return; 321 | } 322 | 323 | /// 从使用链表中查找 324 | int index = obj_group->used_index_head; 325 | int prev = index; 326 | while (index != -1) { 327 | if (index == obj_id.index) { 328 | break; 329 | } 330 | prev = index; 331 | index = obj_group->obj_index_[index].next; 332 | } 333 | 334 | if (index != obj_id.index) { 335 | LOG_ERROR("get obj error|obj_group[%d] obj_index[%d] is not used", obj_group->group_id, obj_id.index); 336 | return; 337 | } 338 | 339 | if (prev == index) { 340 | obj_group->used_index_head = obj_group->obj_index_[index].next; 341 | } else { 342 | obj_group->obj_index_[prev].next = obj_group->obj_index_[index].next; 343 | } 344 | 345 | obj_group->used_obj_count--; 346 | obj_group->obj_index_[index].next = obj_group->free_index_head; 347 | obj_group->obj_index_[index].obj_id.id = 0; 348 | obj_group->free_index_head = index; 349 | 350 | /// NOTE:一定要放在函数最后,防止析构函数再次进入该函数(函数可重入问题) 351 | void *obj = obj_group->obj_node_ + index * obj_group->max_class_size; 352 | ObjectCreatorMgr::Instance().FreeObject(obj, obj_id.class_id); 353 | } 354 | 355 | std::string ShmPool::DumpObjGroup(ObjGroup * obj_group) { 356 | std::ostringstream stream; 357 | stream << "group_id: " << obj_group->group_id << ";"; 358 | stream << "max_obj_count:" << obj_group->max_obj_count << ";"; 359 | stream << "used_obj_count:" << obj_group->used_obj_count << ";"; 360 | stream << "used_index_head:"; 361 | int index = obj_group->used_index_head; 362 | while(index != -1 ) { 363 | stream << "->[obj_id.index:" << index << ";"; 364 | stream << "obj_id.seq:" << obj_group->obj_index_[index].obj_id.seq << "]"; 365 | index = obj_group->obj_index_[index].next; 366 | } 367 | stream << "\n"; 368 | 369 | return stream.str(); 370 | } 371 | 372 | std::string ShmPool::DumpObj() { 373 | std::ostringstream stream; 374 | 375 | for (int i = 0; i < shm_pool_header_->group_info.group_num; i++) { 376 | stream << DumpObjGroup(shm_pool_header_->group_info.group[i].obj_group); 377 | } 378 | return stream.str(); 379 | } 380 | 381 | } // namespace --------------------------------------------------------------------------------