hmbdc
simplify-high-performance-messaging-programming
 All Classes Namespaces Functions Variables Friends Pages
ClientWithStash.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/app/Client.hpp"
5 #include "hmbdc/app/Message.hpp"
6 
7 #include <deque>
8 
9 namespace hmbdc { namespace app {
10 /**
11  * @class ClientWithStash<>
12  * @brief It behaves like Client, with the extra capability of storing messages received and processing
13  * them later - it is used when the user wants to process messages in a specific order other than
14  * FIFO. If a message is deemed to come too early, just stash it and move on (to
15  * the next message). The stashed messages will be delivered later at the user's choice - see the added
16  * stash and openStash functions. The stash mechanism can enforce any particular order of message
17  * processing regarless of the order of message being sent.
18  *
19  * @tparam CcClient the concrete Client type
20  * @tparam MaxStashedMessageSizeIn byte size of the max message that will need to be stashed,
21  * use 0 to auto-set to hold the max interested message
22  * @tparam typename ... Messages message types that the Client interested
23  */
24 template <typename CcClient, size_t MaxStashedMessageSizeIn, MessageC ... Messages>
26 : Client<CcClient, Messages...> {
27  using Base = Client<CcClient, Messages...>;
28  using Interests = typename Base::Interests;
29  using Requests = typename Base::Requests;
30  using Replies = typename Base::Replies;
31 
32  enum {
33  MaxStashedMessageSize = MaxStashedMessageSizeIn
34  ?MaxStashedMessageSizeIn
36  };
37 
38 /**
39  * @brief stash a message that will be delivered later to the same callback
40  * @details when the Client decide a message is not ready to be handled now but is needed later,
41  * it calls this message to stash it, see also openStash()
42  *
43  * @param message the message to be stashed
44  */
45  template <MessageC Message>
46  void stash(Message const& message) {
47  static_assert(index_in_tuple<Message, std::tuple<Messages...>>::value != sizeof...(Messages)
48  , "cannot stash uninterested message");
49  stash_.push_back(typename decltype(stash_)::value_type{});
50  new (stash_.back().data()) MessageWrap<Message>(message);
51  }
52 
53 protected:
54 
55 /**
56  * @brief release the stashed messages - after this call is returned, the callbacks of
57  * the stahsed message will be invoked with the stashed messages
58  * @details it is fine to stash more / new messages even in the above callbacks invoked
59  * due to stashed messages
60  */
61  void openStash() {
62  stashOpenCount_ = stash_.size();
63  }
64 
65 // private:
66  void consumeStash() {
67  CcClient& c = static_cast<CcClient&>(*this);
68  while (hmbdc_unlikely(stashOpenCount_)) {
69  auto m = (MessageHead*)stash_.front().data();
70  MessageDispacher<CcClient, Interests>()(c, *m);
71  stash_.pop_front();
72  stashOpenCount_--;
73  }
74  }
75  size_t stashOpenCount_ = 0;
76  std::deque<std::array<char, MaxStashedMessageSize + sizeof(MessageHead)>> stash_;
77 
78 public:
79 /**
80  * @brief do not touch - internal use
81  */
82  template <typename Iterator>
83  void handleRangeImpl(Iterator it, Iterator end, uint16_t threadId) {
84  Base::handleRangeImpl(it, end, threadId);
85  consumeStash();
86  }
87 };
88 
89 }} //hmbdc::app
Definition: MetaUtils.hpp:44
void handleRangeImpl(Iterator it, Iterator end, uint16_t threadId)
do not touch - internal use
Definition: ClientWithStash.hpp:83
a std tuple holding REPLY messages types it can dispatch
void openStash()
release the stashed messages - after this call is returned, the callbacks of the stahsed message will...
Definition: ClientWithStash.hpp:61
Definition: Message.hpp:78
Definition: Message.hpp:112
Definition: MetaUtils.hpp:96
It behaves like Client, with the extra capability of storing messages received and processing them la...
Definition: ClientWithStash.hpp:25
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:57
a std tuple holding messages types it can dispatch except REPLYs
Definition: BlockingContext.hpp:183
void stash(Message const &message)
stash a message that will be delivered later to the same callback
Definition: ClientWithStash.hpp:46
a std tuple holding REQUEST messages types it can dispatch