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 ...>
50  enum {
51  REGISTERED_MESSAGE_SIZE = sizeof...(Messages),
52  };
53 
54  /**
55  * @brief trivial constructor
56  */
58  : hmbdc::pattern::PoolConsumer(REGISTERED_MESSAGE_SIZE) {
59  }
60 
61  /**
62  * @brief called before any messages got dispatched - only once
63  * @details this is the place some preparation code goes to
64  *
65  * @param threadSerialNumber normally the number
66  * indicating which thread is in action, except when REGISTERED_MESSAGE_SIZE == 0
67  * it is another undefined value
68  *
69  */
70  /*virtual*/ void messageDispatchingStartedCb(uint16_t threadSerialNumber) override {
71  //default do nothing
72  };
73 
74  /**
75  * @brief callback called when this Client is taken out of message dispatching
76  * @details after this call the Client is still at hook from the Context point of view
77  * (until droppedCb is called), so don't delete this Client yet or add it back to
78  * the Context. any exception thrown here is ignored,
79  *
80  * @param e the exception that caused the Client to be taken out of message dispatching
81  * e could be thrown by the Client itself in a callback function
82  * to voluntarily take itself out
83  */
84  /*virtual*/ void stoppedCb(std::exception const& e) override {
85  // called when this client is stopped, e.what() might have reason
86  };
87 
88  /**
89  * @brief callback called after the Client is safely taken out of the Context
90  * @details exception thrown here is ignored and return true is assumed
91  * @return if false, this Client is added back to the Context to process messages
92  * otherwise, no more callback. You could even safely "delete this; return true;"
93  */
94  /*virtual*/ bool droppedCb() override {
95  // called when this client is dropped and free to be deleted
96  return true;
97  };
98 
99  /**
100  * @brief this callback is called all the time (frequently)
101  * @details used if the Client needs to do something all the time like
102  * powering another message loop
103  *
104  * @param threadSerialNumber the number
105  * indicating which thread is in action
106  */
107  /*virtual*/ void invokedCb(uint16_t threadSerialNumber) override {
108  // called as frequently as workload allowed
109  }
110 
111  /**
112  * @brief return the name of thread that runs this client, override if necessary
113  * @details this only used when the Client is running in direct mode
114  * @return thread name - default to be hmbdc0, hmbdc1 ...
115  */
116  char const* hmbdcName() const { return nullptr; }
117 
118  /**
119  * @brief an overrideable method.
120  * returns the schedule policy and priority, override if necessary
121  * priority is only used when policy is "SCHED_RR", or "SCHED_FIFO"
122  * @details this is only used when the Client is running in direct mode
123  * supported policy are "SCHED_OTHER"(=nullptr), "SCHED_RR", "SCHED_FIFO"
124  * @return a tuple made of schedule policy and priority, default to be SCHED_OTHER
125  */
126  std::tuple<char const*, int> schedSpec() const {
127  return std::make_tuple<char const*, int>(nullptr, 0);
128  }
129 
130  /**
131  * @brief an overridable method.
132  * client receives events in batches and the max batch size is controllable when running
133  * in direct mode Context. Here is to specify the max size.
134  * @details a message could only be reaching one client when using partition Context. In this
135  * case, reduce the size (reduce the greediness) might be useful
136  * @return the max number of messages when grabbing messages to process
137  */
138  size_t maxBatchMessageCount() const {return std::numeric_limits<size_t>::max();}
139 
140  /**
141  * @brief internal use, don't change or override
142  */
144  BufIt const& end, uint16_t threadSerialNumber) override {
145  CcClient& c = static_cast<CcClient&>(*this);
146  for (;it != end; ++it) {
147  c.MessageHandler<CcClient, Messages ...>::handleMessage(*static_cast<MessageHead*>(*it));
148  }
149  }
150 
151 };
152 
153 }} //hmbdc::app
void handleRangeImpl(BufIt &it, BufIt const &end, uint16_t threadSerialNumber) override
internal use, don&#39;t change or override
Definition: Client.hpp:143
void stoppedCb(std::exception const &e) override
callback called when this Client is taken out of message dispatching
Definition: Client.hpp:84
Client()
trivial constructor
Definition: Client.hpp:57
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:126
char const * hmbdcName() const
return the name of thread that runs this client, override if necessary
Definition: Client.hpp:116
size_t maxBatchMessageCount() const
an overridable method. client receives events in batches and the max batch size is controllable when ...
Definition: Client.hpp:138
void messageDispatchingStartedCb(uint16_t threadSerialNumber) override
called before any messages got dispatched - only once
Definition: Client.hpp:70
void invokedCb(uint16_t threadSerialNumber) override
this callback is called all the time (frequently)
Definition: Client.hpp:107
bool droppedCb() override
callback called after the Client is safely taken out of the Context
Definition: Client.hpp:94
Definition: PoolConsumer.hpp:13
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
Definition: Base.hpp:12
Definition: MessageHandler.hpp:36
Definition: LockFreeBufferMisc.hpp:73