hmbdc
simplify-high-performance-messaging-programming
Message.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/time/Time.hpp"
5 #include <stdint.h>
6 #include <utility>
7 #include <ostream>
8 #include <type_traits>
9 #include <memory.h>
10 
11 namespace hmbdc { namespace app {
12 
13 /**
14  * @brief each message type has 16 bit tag
15  * @details 0-1000 is reserved for internal use, user message starts from 1001
16  *
17  * see @example hmbdc.cpp for defining messages
18  * @tparam tag 16 bit unsigned tag
19  */
20 template <uint16_t tag>
21 struct hasTag {
22  enum {typeTag = tag};
23 };
24 
25 struct MessageHead {
26  MessageHead(uint16_t typeTag)
27  : reserved2(0)
28  , reserved(0)
29  , typeTag(typeTag)
30  {}
31  template <typename Message> Message& get();
32  template <typename Message> Message const& get() const;
33  template <typename Message> void setPayload(Message const&);
34  template <typename Message, typename ...Args> void setPayloadInPlace(Args&& ... args);
35  uint32_t reserved2;
36  uint16_t reserved;
37  uint16_t typeTag;
38 
39  friend
40  std::ostream& operator << (std::ostream& os, MessageHead const & h) {
41  return os << h.reserved << ' ' << h.typeTag;
42  }
43 } __attribute__((packed));
44 
45 template <typename Message>
47  template <typename ...Args>
48  MessageWrap(Args&& ... args)
49  : MessageHead(Message::typeTag)
50  , payload(std::forward<Args>(args)...) {
51  static_assert(std::is_class<Message>::value, "wrong type to wrap");
52  }
53  Message payload;
54 
55  friend
56  std::ostream& operator << (std::ostream& os, MessageWrap<Message> const & w) {
57  return os << static_cast<MessageHead const&>(w) << ' ' << w.payload;
58  }
59 };
60 
61 template <typename Message>
62 Message&
63 MessageHead::get() {
64  return static_cast<MessageWrap<Message>*>(this)->payload;
65 }
66 
67 template <typename Message>
68 Message const&
69 MessageHead::get() const{
70  return static_cast<MessageWrap<Message> const*>(this)->payload;
71 }
72 
73 template <typename Message>
74 void
75 MessageHead::
76 setPayload(Message const& m) {
77  new (&get<Message>()) Message(m);
78  typeTag = Message::typeTag;
79 }
80 
81 template <typename Message, typename ...Args>
82 void
83 MessageHead::
84 setPayloadInPlace(Args&& ... args) {
85  new (&get<Message>()) Message(std::forward<Args>(args)...);
86  typeTag = Message::typeTag;
87 }
88 
89 struct Flush
90 : hasTag<0> {
91 };
92 
93 template <size_t MaxStreamableSize>
94 struct LoggingT
95 : hasTag<3> {
96  char payload[MaxStreamableSize];
97 } __attribute__((__may_alias__, packed));
98 
99 /**
100  * @brief A special type of message
101  * @details When a Client declare this type as interested, all
102  * messages will be delievered in byte form to this client
103  * additonally - see Client.hpp and ConsoleClient.hpp documentation
104  */
105 struct JustBytes
106 : hasTag<4> {
107  JustBytes() = delete;
108 };
109 
110 struct Trace {
111  Trace()
112  : tsIndex(1) {
113  ts[0] = (time::SysTime::now());
114  }
115  uint8_t tsIndex;
116  time::SysTime ts[6];
117  friend
118  std::ostream& operator << (std::ostream& os, Trace const & t) {
119  for (auto i = 0u; i < t.tsIndex; ++i) os << t.ts[i] << ' ';
120  return os;
121  }
122 };
123 
124 template<>
126  MessageWrap(uint16_t tag, void const* bytes, size_t len)
127  : MessageHead(tag) {
128  memcpy(&payload, bytes, len);
129  }
130  uint8_t payload;
131 
132  friend
133  std::ostream& operator << (std::ostream& os, MessageWrap<JustBytes> const & w) {
134  return os << static_cast<MessageHead const&>(w) << " *";
135  }
136 };
137 static_assert(sizeof(MessageWrap<JustBytes>) == sizeof(MessageHead) + 1, "wrong packing");
138 static_assert(sizeof(MessageWrap<Flush>) == sizeof(MessageHead) + sizeof(Flush), "wrong packing");
139 }} //hmbdc::app
Definition: Message.hpp:125
Definition: Message.hpp:21
Definition: Message.hpp:94
Definition: Message.hpp:89
Definition: Message.hpp:25
A special type of message.
Definition: Message.hpp:105
Definition: Time.hpp:15
Definition: Message.hpp:110
Definition: Message.hpp:46
Definition: Client.hpp:11