hmbdc
simplify-high-performance-messaging-programming
Client.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/app/MessageHandler.hpp"
5 #include "hmbdc/pattern/PoolConsumer.hpp"
6 #include "hmbdc/pattern/LockFreeBufferMisc.hpp"
7 #include "hmbdc/Compile.hpp"
8 
9 #include <tuple>
10 
11 namespace hmbdc { namespace app {
12 /**
13  * @class single_thread_powered_client
14  * @brief a trait class, if a Client can only run on a single specific thread in Pool,
15  * derive the Client from it, hmbdc will check to ensure that is the case
16  */
18 
19 /**
20  * @class Client<>
21  * @brief A Client represents a thread of execution/a task. The execution is managed by a Context.
22  * a Client object could participate in message dispatching as the receiver of specifed message types
23  * @details message is dispatched thru callbacks in the loose
24  * form of void handleMessageCb(Message const& m) or void handleMessageCb(Message& m).
25  * some callbacks have default implementations.
26  * however, all callbacks are overridable to provide desired effects;
27  * When running in a Context, all callbacks (*Cb methods) for a hmbdc Client instance
28  * are garanteed to be called from a single OS thread, ie. no 2 callabacks of an Client
29  * instance are called concurrently, so the Client programmer can assume a
30  * single thread programming model callback-wise.
31  * The above also holds true for timer firing callbacks when a concrete Client deriving
32  * from TimerManager that manages the timers
33  *
34  * See in example hmbdc.cpp @snippet hmbdc.cpp write a Client
35  *
36  * @tparam CcClient the concrete Client type
37  * @tparam typename ... Messages message types that the Client interested
38  * if the type of JustBytes is declared, a special callback
39  *
40  * @code
41  * void handleJustBytesCb(uint16_t tag, uint8_t* bytes){...}
42  * @endcode
43  * is expected
44  * see ConsoleClient.hpp
45  */
46 template <typename CcClient, typename ... Messages>
47 struct Client
48 : MessageHandler<CcClient, Messages ...> {
49  enum {
50  REGISTERED_MESSAGE_SIZE = sizeof...(Messages),
51  };
52  using Interests = std::tuple<Messages ...>;
53 
54  /**
55  * @brief return the name of thread that runs this client, override if necessary
56  * @details this only used when the Client is running in direct mode
57  * @return thread name - default to be hmbdc0, hmbdc1 ...
58  */
59  char const* hmbdcName() const { return nullptr; }
60 
61  /**
62  * @brief an overrideable method.
63  * returns the schedule policy and priority, override if necessary
64  * priority is only used when policy is "SCHED_RR", or "SCHED_FIFO"
65  * @details this is only used when the Client is running in direct mode
66  * supported policy are "SCHED_OTHER"(=nullptr), "SCHED_RR", "SCHED_FIFO"
67  * @return a tuple made of schedule policy and priority, default to be SCHED_OTHER
68  */
69  std::tuple<char const*, int> schedSpec() const {
70  return std::make_tuple<char const*, int>(nullptr, 0);
71  }
72 
73  /**
74  * @brief an overridable method.
75  * client receives events in batches and the max batch size is controllable when running
76  * in direct mode Context. Here is to specify the max size.
77  * @details a message could only be reaching one client when using partition Context. In this
78  * case, reduce the size (reduce the greediness) might be useful
79  * @return the max number of messages when grabbing messages to process
80  */
81  size_t maxBatchMessageCount() const {return std::numeric_limits<size_t>::max();}
82 
83 
84  /**
85  * @brief called before any messages got dispatched - only once
86  * @details this is the place some preparation code goes to
87  *
88  * @param threadSerialNumber normally the number
89  * indicating which thread is in action, except when REGISTERED_MESSAGE_SIZE == 0
90  * it is another undefined value
91  *
92  */
93  virtual void messageDispatchingStartedCb(uint16_t threadSerialNumber) {
94  //default do nothing
95  };
96 
97  /**
98  * @brief callback called when this Client is taken out of message dispatching
99  * @details after this call the Client is still at hook from the Context point of view
100  * (until droppedCb is called), so don't delete this Client yet or add it back to
101  * the Context. any exception thrown here is ignored,
102  *
103  * @param e the exception that caused the Client to be taken out of message dispatching
104  * e could be thrown by the Client itself in a callback function
105  * to voluntarily take itself out
106  */
107  virtual void stoppedCb(std::exception const& e) {
108  // called when this client is stopped, e.what() might have reason
109  };
110 
111  /**
112  * @brief callback called after the Client is safely taken out of the Context
113  * @details exception thrown here is ignored and return true is assumed
114  * @return if false, this Client is added back to the Context to process messages
115  * otherwise, no more callback. You could even safely "delete this; return true;"
116  */
117  virtual bool droppedCb() {
118  // called when this client is dropped and free to be deleted
119  return true;
120  };
121 
122  /**
123  * @brief this callback is called all the time (frequently) - the exact timing is
124  * after a batch of messages are dispatched. After this call returns, the previously
125  * dispatched message's addresses are no longer valid, which means if you cache the
126  * event addresses in the previous handleMessageCb()s, you cannot use those after
127  * the return of the next invokeCb function.
128  * @details you can collectively process the messages received/cached so far here, or
129  * do something needs to be done all the time like powering another message loop
130  *
131  * @param threadSerialNumber the number
132  * indicating which thread is in action
133  */
134  virtual void invokedCb(uint16_t threadSerialNumber) {
135  // called as frequently as workload allowed
136  }
137 
138  /**
139  * @brief trivial
140  */
141  virtual ~Client(){}
142 
143  /**
144  * @brief internal use, don't change or override
145  */
146  void stopped(std::exception const&e) noexcept {
147  try {
148  stoppedCb(e);
149  } catch (...) {}
150  }
151 
152  bool dropped() noexcept {
153  bool res = true;
154  try {
155  res = droppedCb();
156  } catch (...) {}
157  return res;
158  }
159 
160  template <typename Iterator>
161  void handleRangeImpl(Iterator& it,
162  Iterator const& end, uint16_t threadId) {
163  CcClient& c = static_cast<CcClient&>(*this);
164  for (;it != end; ++it) {
165  c.MessageHandler<CcClient, Messages ...>::handleMessage(*static_cast<MessageHead*>(*it));
166  }
167  }
168 };
169 
170 }} //hmbdc::app
virtual ~Client()
trivial
Definition: Client.hpp:141
virtual bool droppedCb()
callback called after the Client is safely taken out of the Context
Definition: Client.hpp:117
virtual void invokedCb(uint16_t threadSerialNumber)
this callback is called all the time (frequently) - the exact timing is after a batch of messages are...
Definition: Client.hpp:134
void stopped(std::exception const &e) noexcept
internal use, don&#39;t change or override
Definition: Client.hpp:146
std::tuple< char const *, int > schedSpec() const
an overrideable method. returns the schedule policy and priority, override if necessary priority is o...
Definition: Client.hpp:69
char const * hmbdcName() const
return the name of thread that runs this client, override if necessary
Definition: Client.hpp:59
size_t maxBatchMessageCount() const
an overridable method. client receives events in batches and the max batch size is controllable when ...
Definition: Client.hpp:81
virtual void stoppedCb(std::exception const &e)
callback called when this Client is taken out of message dispatching
Definition: Client.hpp:107
virtual void messageDispatchingStartedCb(uint16_t threadSerialNumber)
called before any messages got dispatched - only once
Definition: Client.hpp:93
a trait class, if a Client can only run on a single specific thread in Pool, derive the Client from i...
Definition: Client.hpp:17
A Client represents a thread of execution/a task. The execution is managed by a Context. a Client object could participate in message dispatching as the receiver of specifed message types.
Definition: Client.hpp:47
a std tuple holding messages types it can dispatch
Definition: Base.hpp:12
Definition: MessageHandler.hpp:36