NCBI C++ ToolKit
UvHelper.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef UV_HELPER__HPP
2 #define UV_HELPER__HPP
3 
4 /* $Id: UvHelper.hpp 88559 2019-12-17 14:21:36Z satskyse $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Dmitri Dmitrienko
30  *
31  * File Description:
32  *
33  */
34 
35 #include <stdexcept>
36 #include <sstream>
37 
38 #include <corelib/ncbimtx.hpp>
40 
41 #include "uv.h"
42 
44 
46 {
47 public:
48  enum EErrCode {
52  };
53 
54  const char* GetErrCodeString(void) const override;
55 
57 };
58 
60 {
61 public:
62  enum EErrCode {
70  };
71 
73  const CException* prev_exception,
74  EErrCode err_code,
75  const string& message,
76  int uv_err_code,
77  EDiagSev severity = eDiag_Error) :
78  CUvBaseException(info, prev_exception, (CUvBaseException::EErrCode) err_code,
79  message + ": " + uv_strerror(uv_err_code), severity),
80  m_UvErrCode(uv_err_code)
82 
83  const char* GetErrCodeString() const override;
84 
85 private:
87 };
88 
89 class CUvLoop {
90 private:
91  uv_loop_t m_loop;
93  static void s_walk(uv_handle_t* handle, void* arg) {
94  std::function<void(uv_handle_t* handle)> *cb = static_cast<std::function<void(uv_handle_t* handle)>*>(arg);
95  (*cb)(handle);
96  }
97 public:
98  CUvLoop() :
99  m_loop({0}),
100  m_initialized(false)
101  {
102  PSG_TRACE("CUvLoop::CUvLoop " << &m_loop);
103  int rc = uv_loop_init(&m_loop);
104  if (rc)
105  NCBI_THROW2(CUvException, eUvLoopInitFailure, "uv_loop_init failed", rc);
106  m_initialized = true;
107  }
109  PSG_TRACE("CUvLoop::~CUvLoop " << &m_loop);
110  Close();
111  }
112  uv_loop_t* Handle() {
113  return &m_loop;
114  }
115  int Close() {
116  PSG_TRACE("CUvLoop::Close " << &m_loop);
117  int rc = 0;
118  if (m_initialized) {
119  rc = uv_run(&m_loop, UV_RUN_DEFAULT);
120  if (rc)
121  PSG_TRACE("uv_run returned " << rc);
122  rc = uv_loop_close(&m_loop);
123  if (rc)
124  PSG_TRACE("uv_loop_close returned " << rc);
125  m_initialized = false;
126  }
127  return rc;
128  }
129  void Stop() {
130  if (m_initialized) {
131  PSG_TRACE("CUvLoop::Stop " << &m_loop);
132  uv_stop(&m_loop);
133  }
134  }
135  void Walk(std::function<void(uv_handle_t* handle)> cb) {
136  if (m_initialized) {
137  uv_walk(&m_loop, s_walk, &cb);
138  }
139  }
140 };
141 
142 class CUvSignal {
143 private:
144  uv_signal_t m_sig;
146  bool m_started;
147 public:
148  CUvSignal(uv_loop_t *loop) :
149  m_sig({0}),
150  m_initialized(false),
151  m_started(false)
152  {
153  int rc;
154  rc = uv_signal_init(loop, &m_sig);
155  if (rc)
156  NCBI_THROW2(CUvException, eUvSignalInitFailure, "uv_signal_init failed", rc);
157  m_initialized = true;
158  }
160  Close();
161  }
162  void Start(int signum, uv_signal_cb cb) {
163  if (m_started)
164  NCBI_THROW(CUvBaseException, eSignalAlreadyStarted, "signal has already started");
165  int rc = uv_signal_start(&m_sig, cb, signum);
166  if (rc)
167  NCBI_THROW2(CUvException, eUvSignalStartFailure, "uv_signal_start failed", rc);
168  m_started = true;
169  }
170  void Stop() {
171  if (!m_started)
172  NCBI_THROW(CUvBaseException, eSignalNotStarted, "signal hasn't started");
173  uv_signal_stop(&m_sig);
174  m_started = false;
175  }
176  void Close() {
177  if (m_initialized) {
178  if (m_started) {
179  uv_signal_stop(&m_sig);
180  m_started = false;
181  }
182  uv_close(reinterpret_cast<uv_handle_t*>(&m_sig), NULL);
183  m_initialized = false;
184  }
185  }
186 };
187 
188 class CUvTcp {
189 private:
190  uv_tcp_t m_tcp;
192  static void s_close_cb(uv_handle_t *handle) {
193  CUvTcp *self = static_cast<CUvTcp*>(handle->data);
194  self->m_initialized = false;
195  }
196  void InternalClose(void (*close_cb)(uv_handle_t* handle), bool from_dtor) {
197  if (m_initialized) {
198  PSG_TRACE("CUvTcp::Close " << &m_tcp);
199  uv_handle_t *handle = reinterpret_cast<uv_handle_t*>(&m_tcp);
200  if (from_dtor) {
201  handle->data = this;
202  uv_close(handle, s_close_cb);
203  while (m_initialized)
204  uv_run(handle->loop, UV_RUN_ONCE);
205  }
206  else {
207  m_initialized = false;
208  uv_close(handle, close_cb);
209  }
210  }
211  }
212 public:
213  CUvTcp(uv_loop_t *loop) :
214  m_tcp({0}),
215  m_initialized(false)
216  {
217  PSG_TRACE("CUvTcp::CUvTcp " << &m_tcp);
218  Init(loop);
219  }
221  PSG_TRACE("CUvTcp::~CUvTcp " << &m_tcp);
222  InternalClose(nullptr, true);
223  }
224  void Init(uv_loop_t *loop) {
225  if (!m_initialized) {
226  int rc;
227  rc = uv_tcp_init(loop, &m_tcp);
228  if (rc)
229  NCBI_THROW2(CUvException, eUvTcpInitFailure, "uv_tcp_init failed", rc);
230  m_initialized = true;
231  }
232  }
233  bool Initialized() const {
234  return m_initialized;
235  }
236  void NoDelay(bool set) {
237  if (m_initialized) {
238  uv_tcp_nodelay(&m_tcp, set ? 1 : 0);
239  }
240  }
241  void KeepAlive(bool set) {
242  if (m_initialized) {
243  uv_tcp_keepalive(&m_tcp, set ? 1 : 0, 120);
244  }
245  }
246  uv_tcp_t* Handle() {
247  if (!m_initialized)
248  NCBI_THROW(CUvBaseException, eTcpHandleClosed, "tcp handle is closed");
249  return &m_tcp;
250  }
251  void Bind(const char* addr, unsigned int port) {
252  int e;
253  std::stringstream ss;
254  struct sockaddr_in addr_in;
255 
256  e = uv_ip4_addr(addr, port, &addr_in);
257 
258  if (e != 0) {
259  ss << (e == EINVAL ? "invalid" : "failed to parse") << " address/port: " << addr << ':' << port;
260  NCBI_THROW2(CUvException, eUvIp4AddrFailure, ss.str(), e);
261  }
262 
263  e = uv_tcp_bind(&m_tcp, reinterpret_cast<struct sockaddr*>(&addr_in), 0);
264  if (e != 0 || errno == EADDRINUSE) {
265  ss << "failed to bind socket to address/port: " << addr << ':' << port;
266  NCBI_THROW2(CUvException, eUvTcpBindFailure, ss.str(), e);
267  }
268  }
269  void Close(void (*close_cb)(uv_handle_t* handle)) {
270  InternalClose(close_cb, false);
271  }
272  void StopRead() {
273  if (m_initialized) {
274  PSG_TRACE("CUvTcp::StopRead " << &m_tcp);
275  uv_read_stop(reinterpret_cast<uv_stream_t*>(&m_tcp));
276  }
277  }
278 };
279 
280 inline const char* CUvBaseException::GetErrCodeString(void) const
281 {
282  switch (GetErrCode())
283  {
284  case eSignalAlreadyStarted: return "eSignalAlreadyStarted";
285  case eSignalNotStarted: return "eSignalNotStarted";
286  case eTcpHandleClosed: return "eTcpHandleClosed";
287  default: return CException::GetErrCodeString();
288  }
289 }
290 
291 inline const char* CUvException::GetErrCodeString(void) const
292 {
293  switch (GetErrCode()) {
294  case eUvLoopInitFailure: return "eUvLoopInitFailure";
295  case eUvSignalInitFailure: return "eUvSignalInitFailure";
296  case eUvSignalStartFailure: return "eUvSignalStartFailure";
297  case eUvIp4AddrFailure: return "eUvIp4AddrFailure";
298  case eUvTcpInitFailure: return "eUvTcpInitFailure";
299  case eUvTcpBindFailure: return "eUvTcpBindFailure";
300  case eUvSemInitFailure: return "eUvSemInitFailure";
301  default: return CException::GetErrCodeString();
302  }
303 }
304 
305 #endif
USING_NCBI_SCOPE
Definition: UvHelper.hpp:39
Incapsulate compile time information such as __FILE__, __LINE__, NCBI_MODULE, current function.
Definition: ncbidiag.hpp:65
NCBI_EXCEPTION_DEFAULT(CUvBaseException, CException)
const char * GetErrCodeString(void) const override
Get error code interpreted as text.
Definition: UvHelper.hpp:280
int m_UvErrCode
Definition: UvHelper.hpp:86
@ eUvSignalInitFailure
Definition: UvHelper.hpp:64
@ eUvLoopInitFailure
Definition: UvHelper.hpp:63
@ eUvSemInitFailure
Definition: UvHelper.hpp:69
@ eUvTcpBindFailure
Definition: UvHelper.hpp:68
@ eUvTcpInitFailure
Definition: UvHelper.hpp:67
@ eUvIp4AddrFailure
Definition: UvHelper.hpp:66
@ eUvSignalStartFailure
Definition: UvHelper.hpp:65
CUvException(const CDiagCompileInfo &info, const CException *prev_exception, EErrCode err_code, const string &message, int uv_err_code, EDiagSev severity=eDiag_Error) const char GetErrCodeString)() const override
Definition: UvHelper.hpp:83
CUvLoop()
Definition: UvHelper.hpp:98
uv_loop_t m_loop
Definition: UvHelper.hpp:91
void Stop()
Definition: UvHelper.hpp:129
bool m_initialized
Definition: UvHelper.hpp:92
void Walk(std::function< void(uv_handle_t *handle)> cb)
Definition: UvHelper.hpp:135
static void s_walk(uv_handle_t *handle, void *arg)
Definition: UvHelper.hpp:93
~CUvLoop()
Definition: UvHelper.hpp:108
uv_loop_t * Handle()
Definition: UvHelper.hpp:112
int Close()
Definition: UvHelper.hpp:115
void Start(int signum, uv_signal_cb cb)
Definition: UvHelper.hpp:162
void Close()
Definition: UvHelper.hpp:176
void Stop()
Definition: UvHelper.hpp:170
CUvSignal(uv_loop_t *loop)
Definition: UvHelper.hpp:148
uv_signal_t m_sig
Definition: UvHelper.hpp:144
bool m_started
Definition: UvHelper.hpp:146
bool m_initialized
Definition: UvHelper.hpp:145
CUvTcp(uv_loop_t *loop)
Definition: UvHelper.hpp:213
void NoDelay(bool set)
Definition: UvHelper.hpp:236
void StopRead()
Definition: UvHelper.hpp:272
void Bind(const char *addr, unsigned int port)
Definition: UvHelper.hpp:251
void Init(uv_loop_t *loop)
Definition: UvHelper.hpp:224
void KeepAlive(bool set)
Definition: UvHelper.hpp:241
bool Initialized() const
Definition: UvHelper.hpp:233
void Close(void(*close_cb)(uv_handle_t *handle))
Definition: UvHelper.hpp:269
uv_tcp_t * Handle()
Definition: UvHelper.hpp:246
~CUvTcp()
Definition: UvHelper.hpp:220
void InternalClose(void(*close_cb)(uv_handle_t *handle), bool from_dtor)
Definition: UvHelper.hpp:196
static void s_close_cb(uv_handle_t *handle)
Definition: UvHelper.hpp:192
bool m_initialized
Definition: UvHelper.hpp:191
uv_tcp_t m_tcp
Definition: UvHelper.hpp:190
Definition: set.hpp:45
#define NULL
Definition: ncbistd.hpp:225
EDiagSev
Severity level for the posted diagnostics.
Definition: ncbidiag.hpp:650
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbiexpt.cpp:453
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define NCBI_THROW2(exception_class, err_code, message, extra)
Throw exception with extra parameter.
Definition: ncbiexpt.hpp:1754
EErrCode
Error types that an application can generate.
Definition: ncbiexpt.hpp:884
#define NCBI_EXCEPTION_DEFAULT_IMPLEMENTATION(exception_class, base_class)
Helper macro for default exception implementation.
Definition: ncbiexpt.hpp:1300
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
static MDB_envinfo info
Definition: mdb_load.c:37
Multi-threading – mutexes; rw-locks; semaphore.
T signum(T x_)
#define PSG_TRACE(message)
Modified on Wed May 29 18:40:43 2024 by modify_doxy.py rev. 669887