eRPC
nexus.h
1 #pragma once
2 
3 #include <unordered_map>
4 #include "common.h"
5 #include "heartbeat_mgr.h"
6 #include "session.h"
7 #include "sm_types.h"
8 #include "util/logger.h"
9 #include "util/mt_queue.h"
10 #include "util/tls_registry.h"
11 
12 namespace erpc {
13 
14 // Forward declaration for friendship
15 template <typename T>
16 class Rpc;
17 
21 class Nexus {
22  friend class Rpc<CTransport>;
23 
38  public:
39  Nexus(std::string local_uri, size_t numa_node = 0, size_t num_bg_threads = 0);
40 
41  ~Nexus();
42 
49  int register_req_func(uint8_t req_type, erpc_req_func_t req_func,
50  ReqFuncType req_func_type = ReqFuncType::kForeground);
51 
52  private:
53  enum class BgWorkItemType : bool { kReq, kResp };
54 
56  class BgWorkItem {
57  public:
58  BgWorkItem() {}
59 
60  static inline BgWorkItem make_req_item(void *context, SSlot *sslot) {
61  BgWorkItem ret;
62  ret.wi_type_ = BgWorkItemType::kReq;
63  ret.context_ = context;
64  ret.sslot_ = sslot;
65  return ret;
66  }
67 
68  static inline BgWorkItem make_resp_item(void *context,
69  erpc_cont_func_t cont_func,
70  void *tag) {
71  BgWorkItem ret;
72  ret.wi_type_ = BgWorkItemType::kResp;
73  ret.context_ = context;
74  ret.cont_func_ = cont_func;
75  ret.tag_ = tag;
76  return ret;
77  }
78 
79  BgWorkItemType wi_type_;
80  void *context_;
81 
82  // Fields for request handlers. For request handlers, we still have
83  // ownership of the request slot, so we can hold it until enqueue_response.
84  SSlot *sslot_;
85 
86  // Fields for continuations. For continuations, we have lost ownership of
87  // the request slot, so the work item contains all needed info by value.
88  erpc_cont_func_t cont_func_;
89  void *tag_;
90 
91  bool is_req() const { return wi_type_ == BgWorkItemType::kReq; }
92  };
93 
95  class Hook {
96  public:
97  uint8_t rpc_id_;
98 
100  MtQueue<BgWorkItem> *bg_req_queue_arr_[kMaxBgThreads] = {nullptr};
101 
104  MtQueue<SmWorkItem> sm_rx_queue_;
105  };
106 
109  bool rpc_id_exists(uint8_t rpc_id);
110 
112  void register_hook(Hook *hook);
113 
115  void unregister_hook(Hook *hook);
116 
118  class BgThreadCtx {
119  public:
120  volatile bool *kill_switch_;
121 
126  std::array<ReqFunc, kReqTypeArraySize> *req_func_arr_;
127 
128  TlsRegistry *tls_registry_;
129  size_t bg_thread_index_;
130  MtQueue<BgWorkItem> *bg_req_queue_;
131  };
132 
134  class SmThreadCtx {
135  public:
136  // Installed by the Nexus
137  std::string hostname_;
138  uint16_t sm_udp_port_;
139  double freq_ghz_;
140 
143  volatile bool *kill_switch_;
144 
145  HeartbeatMgr *heartbeat_mgr_;
146  volatile Hook **reg_hooks_arr_;
147  std::mutex *reg_hooks_lock_;
148  };
149 
151  static void bg_thread_func(BgThreadCtx ctx);
152 
154  static void sm_thread_func(SmThreadCtx ctx);
155 
157  const double freq_ghz_;
158  const std::string hostname_;
159  const uint16_t sm_udp_port_;
160  const size_t numa_node_;
161  const size_t num_bg_threads_;
162  TlsRegistry tls_registry_;
163 
165  std::array<ReqFunc, kReqTypeArraySize> req_func_arr_;
166  const uint8_t pad_[64] = {0};
167 
170  bool req_func_registration_allowed_ = true;
171 
173  Hook *reg_hooks_arr_[kMaxRpcId + 1] = {nullptr};
174  std::mutex reg_hooks_lock_;
175 
176  HeartbeatMgr heartbeat_mgr_;
177  volatile bool kill_switch_;
178 
179  std::thread sm_thread_;
180  MtQueue<BgWorkItem> bg_req_queue_[kMaxBgThreads];
181  std::thread bg_thread_arr_[kMaxBgThreads];
182 };
183 } // namespace erpc
An Rpc object is the main communication end point in eRPC. Applications use it to create sessions wit...
Definition: nexus.h:16
int register_req_func(uint8_t req_type, erpc_req_func_t req_func, ReqFuncType req_func_type=ReqFuncType::kForeground)
Register application-defined request handler function. This must be done before any Rpc registers a h...
Definition: nexus.h:12
A per-process library object used for initializing eRPC.
Definition: nexus.h:21
Nexus(std::string local_uri, size_t numa_node=0, size_t num_bg_threads=0)
Initialize eRPC for this process.