/* * ===================================================================================== * * 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 #include #include #include #include #include namespace bhome_shm { using namespace boost::interprocess; typedef managed_shared_memory mshm_t; class CasMutex { std::atomic flag_; bool cas(bool expected, bool new_val) { return flag_.compare_exchange_strong(expected, new_val); } public: CasMutex() : flag_(false) {} bool try_lock() { return cas(false, true); } void lock() { while (!try_lock()) { std::this_thread::yield(); } } void unlock() { cas(true, false); } }; class MutexWithTimeLimit { typedef boost::interprocess::interprocess_mutex MutexT; // typedef CasMutex MutexT; typedef std::chrono::steady_clock Clock; typedef Clock::duration Duration; static Duration Now() { return Clock::now().time_since_epoch(); } const Duration limit_; std::atomic last_lock_time_; MutexT mutex_; public: typedef MutexT::internal_mutex_type internal_mutex_type; const internal_mutex_type &internal_mutex() const { return mutex_.internal_mutex(); } internal_mutex_type &internal_mutex() { return mutex_.internal_mutex(); } explicit MutexWithTimeLimit(Duration limit) : limit_(limit) {} MutexWithTimeLimit() : MutexWithTimeLimit(std::chrono::seconds(1)) {} ~MutexWithTimeLimit() { static_assert(std::is_pod::value); } bool try_lock(); void lock(); void unlock() { mutex_.unlock(); } }; // typedef boost::interprocess::interprocess_mutex Mutex; typedef MutexWithTimeLimit Mutex; typedef scoped_lock Guard; typedef interprocess_condition Cond; class SharedMemory : public mshm_t { std::string name_; 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()); } void *Alloc(const size_t size) { return allocate(size, std::nothrow); } void Dealloc(void *p) { if (p) { deallocate(p); } } template void Dealloc(offset_ptr ptr) { return Dealloc(ptr.get()); } template T *New(Params const &...params) { return construct(anonymous_instance, std::nothrow)(params...); } template void Delete(T *p) { if (p) { destroy_ptr(p); }; } template void Delete(offset_ptr p) { Delete(p.get()); } template T *Find(const std::string &name) { return find(name.c_str()).first; } }; template using Allocator = allocator; template using Deleter = deleter; template using SharedPtr = shared_ptr, Deleter>; // ShmObject manages an object in shared memory, but ShmObject itself is not in shared memory. template class ShmObject : private boost::noncopyable { static std::string ObjName(const std::string &name) { return "obj" + name; } protected: typedef T Data; typedef SharedMemory ShmType; private: ShmType &shm_; std::string name_; Data *pdata_ = nullptr; bool IsOk() const { return pdata_; } protected: ShmType &shm() const { return shm_; } public: template ShmObject(ShmType &segment, const std::string &name, Params &&...t) : shm_(segment), name_(name) { pdata_ = shm_.find_or_construct(ObjName(name_).c_str(), std::nothrow)(t...); if (!IsOk()) { throw("Error: Not enough memory, can not allocate \"" + name_ + "\""); } } static bool Remove(SharedMemory &shm, const std::string &name) { return shm.destroy(ObjName(name).c_str()); } 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 ~ShmObject() {} std::string name() const { return name_; } Data *data() { return pdata_; } const Data *data() const { return pdata_; } Data *operator->() { return data(); } const Data *operator->() const { return data(); } bool Remove() { return Remove(shm_, name_); } }; } // namespace bhome_shm #endif // end of include guard: SHM_6CHO6D6C