| | |
| | | class MsgI |
| | | { |
| | | private: |
| | | struct Meta { |
| | | RefCount count_; |
| | | }; |
| | | offset_ptr<void> ptr_; |
| | | offset_ptr<RefCount> count_; |
| | | void *Alloc(SharedMemory &shm, const size_t size); |
| | | void Free(SharedMemory &shm); |
| | | Meta *meta() const { return get<Meta>() - 1; } |
| | | |
| | | typedef std::function<void(void *p, int len)> ToArray; |
| | | void *Pack(SharedMemory &shm, |
| | |
| | | |
| | | void *Pack(SharedMemory &shm, const std::string &content) |
| | | { |
| | | void *addr = shm.Alloc(content.size()); |
| | | void *addr = Alloc(shm, content.size()); |
| | | if (addr) { |
| | | memcpy(addr, content.data(), content.size()); |
| | | } |
| | | return addr; |
| | | } |
| | | |
| | | bool MakeRC(SharedMemory &shm, void *addr); |
| | | bool Make(SharedMemory &shm, void *addr); |
| | | MsgI(void *p) : |
| | | ptr_(p) {} |
| | | |
| | | public: |
| | | MsgI(void *p = 0, RefCount *c = 0) : |
| | | ptr_(p), count_(c) {} |
| | | |
| | | void swap(MsgI &a) |
| | | { |
| | | std::swap(ptr_, a.ptr_); |
| | | std::swap(count_, a.count_); |
| | | } |
| | | MsgI() : |
| | | MsgI(nullptr) {} |
| | | MsgI(SharedMemory &shm, const size_t size) : |
| | | MsgI(Alloc(shm, size)) {} |
| | | void swap(MsgI &a) { std::swap(ptr_, a.ptr_); } |
| | | bool valid() const { return static_cast<bool>(ptr_); } |
| | | template <class T = void> |
| | | T *get() { return static_cast<T *>(ptr_.get()); } |
| | | T *get() const { return static_cast<T *>(ptr_.get()); } |
| | | |
| | | // AddRef and Release works for both counted and not counted msg. |
| | | int AddRef() const { return IsCounted() ? count_->Inc() : 1; } |
| | | int AddRef() const { return valid() ? meta()->count_.Inc() : 1; } |
| | | int Release(SharedMemory &shm); |
| | | int Count() const { return valid() ? meta()->count_.Get() : 1; } |
| | | |
| | | int Count() const { return IsCounted() ? count_->Get() : 1; } |
| | | bool IsCounted() const { return static_cast<bool>(count_); } |
| | | |
| | | template <class Body> |
| | | inline bool MakeRC(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | { |
| | | return MakeRC(shm, Pack(shm, head, body)); |
| | | } |
| | | |
| | | bool EnableRefCount(SharedMemory &shm); |
| | | template <class Body> |
| | | inline bool Make(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | { |
| | | void *p = Pack(shm, head, body); |
| | | auto NeedRefCount = [&]() { return head.type() == kMsgTypePublish; }; |
| | | return NeedRefCount() ? MakeRC(shm, p) : Make(shm, p); |
| | | return Make(shm, Pack(shm, head, body)); |
| | | } |
| | | template <class Body> |
| | | static inline std::string Serialize(const BHMsgHead &head, const Body &body) |