| | |
| | | namespace bhome_msg |
| | | { |
| | | using namespace bhome_shm; |
| | | using namespace bhome::msg; // for serialized data in MsgI |
| | | |
| | | // MsgI is safe to be stored in shared memory, so POD data or offset_ptr is required. |
| | | // message format: header(meta) + body(data). |
| | |
| | | uint32_t(body.ByteSizeLong()), [&](void *p, int len) { body.SerializeToArray(p, len); }); |
| | | } |
| | | |
| | | void *Pack(SharedMemory &shm, const std::string &content) |
| | | { |
| | | void *addr = shm.Alloc(content.size()); |
| | | if (addr) { |
| | | memcpy(addr, content.data(), content.size()); |
| | | } |
| | | return addr; |
| | | } |
| | | |
| | | bool MakeRC(SharedMemory &shm, void *addr); |
| | | bool Make(SharedMemory &shm, void *addr); |
| | | |
| | |
| | | bool IsCounted() const { return static_cast<bool>(count_); } |
| | | |
| | | template <class Body> |
| | | bool Make(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | { |
| | | return Make(shm, Pack(shm, head, body)); |
| | | } |
| | | template <class Body> |
| | | bool MakeRC(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | inline bool MakeRC(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | { |
| | | return MakeRC(shm, Pack(shm, head, body)); |
| | | } |
| | | bool MakeRC(SharedMemory &shm, MsgI &a) |
| | | |
| | | bool EnableRefCount(SharedMemory &shm); |
| | | template <class Body> |
| | | inline bool Make(SharedMemory &shm, const BHMsgHead &head, const Body &body) |
| | | { |
| | | if (a.IsCounted()) { |
| | | *this = a; |
| | | AddRef(); |
| | | return true; |
| | | } else { |
| | | void *p = a.ptr_.get(); |
| | | a.ptr_ = 0; |
| | | return MakeRC(shm, p); |
| | | } |
| | | void *p = Pack(shm, head, body); |
| | | auto NeedRefCount = [&]() { return head.type() == kMsgTypePublish; }; |
| | | return NeedRefCount() ? MakeRC(shm, p) : Make(shm, p); |
| | | } |
| | | template <class Body> |
| | | static inline std::string Serialize(const BHMsgHead &head, const Body &body) |
| | | { |
| | | uint32_t head_len = head.ByteSizeLong(); |
| | | uint32_t body_len = body.ByteSizeLong(); |
| | | std::string s(4 + head_len + 4 + body_len, '\0'); |
| | | size_t pos = 0; |
| | | auto add1 = [&](auto &&msg, auto &&size) { |
| | | Put32(&s[pos], size); |
| | | pos += 4; |
| | | msg.SerializeToArray(&s[pos], size); |
| | | pos += size; |
| | | }; |
| | | add1(head, head_len); |
| | | add1(body, body_len); |
| | | assert(pos == s.size()); |
| | | return s; |
| | | } |
| | | inline bool Make(SharedMemory &shm, const std::string &content) |
| | | { |
| | | void *p = Pack(shm, content); |
| | | return Make(shm, p); |
| | | } |
| | | |
| | | bool ParseHead(BHMsgHead &head) const; |
| | | template <class Body> |
| | | bool ParseBody(Body &body) const |