/* * ===================================================================================== * * Filename: shm.h * * Description: * * Version: 1.0 * Created: 2021年03月22日 16时19分21秒 * Revision: none * Compiler: gcc * * Author: Li Chao (), * Organization: * * ===================================================================================== */ #ifndef SHM_6CHO6D6C #define SHM_6CHO6D6C #include #include #include #include namespace bhome_shm { using namespace boost::interprocess; typedef managed_shared_memory mshm_t; typedef interprocess_mutex Mutex; typedef scoped_lock Guard; class SharedMemory : public mshm_t { std::string name_; Mutex *pmutex_ = 0; static permissions AllowAll() { permissions perm; perm.set_unrestricted(); return perm; } void Swap(SharedMemory &a); public: static bool Remove(const std::string &name) { return shared_memory_object::remove(name.c_str()); } SharedMemory(const std::string &name, const uint64_t size); ~SharedMemory(); std::string name() const { return name_; } bool Remove() { return Remove(name()); } template T *FindOrCreate(const std::string &name, Params &&...params) { return find_or_construct(name.c_str(), std::nothrow)(std::forward(params)...); } template T *Create(const std::string &name, Params &&...params) { return construct(name.c_str(), std::nothrow)(std::forward(params)...); } template bool Destroy(const std::string &name) { return destroy(name.c_str()); } void *Alloc(const size_t size) { Guard lock(*pmutex_); return allocate(size, std::nothrow); } void Dealloc(void *p) { Guard lock(*pmutex_); if (p) { deallocate(p); } } template T *Find(const std::string &name) { return find(name.c_str()).first; } }; enum Mode { eOpen = 0, eCreate = 1, eOpenOrCreate = 2 }; // NamedShmObject manages an object in shared memory, but NamedShmObject itself is not in shared memory. template class NamedShmObject : private boost::noncopyable { static std::string ObjName(const std::string &name) { return "obj" + name; } public: typedef T Data; typedef SharedMemory ShmType; ShmType &shm() const { return shm_; } template NamedShmObject(ShmType &segment, const std::string &name, Mode mode, Params &&...t) : shm_(segment), name_(name) { switch (mode) { case eOpen: pdata_ = shm_.Find(ObjName(name_)); break; case eCreate: pdata_ = shm_.Create(ObjName(name_), std::forward(t)...); break; case eOpenOrCreate: pdata_ = shm_.FindOrCreate(ObjName(name_), std::forward(t)...); break; default: break; } if (!IsOk()) { throw std::runtime_error("Error: shm can not create/open \"" + name_ + "\""); } } NamedShmObject(const int64_t offset, ShmType &segment, const std::string &name) : shm_(segment), name_(name) { pdata_ = reinterpret_cast(Addr(shm_.get_address()) + offset); } bool IsOk() const { return pdata_; } static bool Remove(SharedMemory &shm, const std::string &name) { return shm.Destroy(ObjName(name)); } static Data *Find(SharedMemory &shm, const std::string &name) { return shm.Find(ObjName(name)); } Data *Find(const std::string &name) { return Find(shm_, ObjName(name)); } virtual ~NamedShmObject() {} std::string name() const { return name_; } Data *data() { return pdata_; } const Data *data() const { return pdata_; } int64_t offset() const { return Addr(pdata_) - Addr(shm_.get_address()); } Data *operator->() { return data(); } const Data *operator->() const { return data(); } bool Remove() { return Remove(shm_, name_); } private: static int64_t Addr(const void *p) { return reinterpret_cast(p); } ShmType &shm_; std::string name_; Data *pdata_ = nullptr; }; } // namespace bhome_shm #endif // end of include guard: SHM_6CHO6D6C