OGLplus  (0.59.0) a C++ wrapper for rendering APIs

asio_backend.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_LOGGING_ASIO_BACKEND_HPP
10 #define EAGINE_LOGGING_ASIO_BACKEND_HPP
11 
12 #include "../config/platform.hpp"
13 #include "ostream_backend.hpp"
14 #include <iostream>
15 
16 #ifdef __clang__
17 EAGINE_DIAG_PUSH()
18 EAGINE_DIAG_OFF(disabled-macro-expansion)
19 EAGINE_DIAG_OFF(covered-switch-default)
20 EAGINE_DIAG_OFF(zero-as-null-pointer-constant)
21 EAGINE_DIAG_OFF(shorten-64-to-32)
22 EAGINE_DIAG_OFF(deprecated)
23 #endif
24 
25 #include <asio/io_context.hpp>
26 #include <asio/ip/tcp.hpp>
27 #if EAGINE_POSIX
28 #include <asio/local/stream_protocol.hpp>
29 #endif
30 #include <asio/streambuf.hpp>
31 #include <asio/write.hpp>
32 
33 #ifdef __clang__
34 EAGINE_DIAG_POP()
35 #endif
36 
37 namespace eagine {
38 //------------------------------------------------------------------------------
39 #if EAGINE_POSIX
40 class asio_local_ostream_log_connection {
41  static auto _fix_addr(string_view addr_str) noexcept {
42  return addr_str ? addr_str : string_view{"/tmp/eagine-xmllog"};
43  }
44 
45 public:
46  asio_local_ostream_log_connection(string_view addr_str)
47  : _endpoint{c_str(_fix_addr(addr_str))}
48  , _socket{_context}
49  , _out{&_buffer} {
50  _socket.connect(_endpoint);
51  }
52 
53  auto out() noexcept -> std::ostream& {
54  if(_socket.is_open()) {
55  return _out;
56  }
57  return std::clog;
58  }
59 
60 protected:
61  void _flush() {
62  try {
63  if(_socket.is_open()) {
64  const auto done = asio::write(_socket, _buffer);
65  _buffer.consume(done);
66  }
67  } catch(...) {
68  }
69  }
70 
71 private:
72  asio::io_context _context{};
73  asio::local::stream_protocol::endpoint _endpoint{};
74  asio::local::stream_protocol::socket _socket;
75  asio::streambuf _buffer{};
76  std::ostream _out;
77 };
78 #endif
79 //------------------------------------------------------------------------------
80 class asio_tcpipv4_ostream_log_connection {
81 public:
82  asio_tcpipv4_ostream_log_connection(string_view addr_str)
83  : _addr{_fix_addr(addr_str)}
84  , _resolver{_context}
85  , _socket{_context}
86  , _out{&_buffer} {
87  for(auto& endpt :
88  _resolver.resolve(std::get<0>(_addr), std::get<1>(_addr))) {
89  _socket.connect(endpt);
90  break;
91  }
92  }
93 
94  auto out() noexcept -> std::ostream& {
95  if(_socket.is_open()) {
96  return _out;
97  }
98  return std::clog;
99  }
100 
101 protected:
102  void _flush() {
103  try {
104  if(_socket.is_open()) {
105  const auto done = asio::write(_socket, _buffer);
106  _buffer.consume(done);
107  }
108  } catch(...) {
109  }
110  }
111 
112 private:
113  static auto _fix_addr(string_view addr_str)
114  -> std::tuple<std::string, std::string> {
115  auto [hostname, port_str] = split_by_last(addr_str, string_view(":"));
116  return {
117  hostname ? to_string(hostname) : std::string("localhost"),
118  port_str ? to_string(port_str) : std::string("34917")};
119  }
120  std::tuple<std::string, std::string> _addr;
121 
122  asio::io_context _context{};
123  asio::ip::tcp::resolver _resolver;
124  asio::ip::tcp::socket _socket;
125  asio::streambuf _buffer{};
126  std::ostream _out;
127 };
128 //------------------------------------------------------------------------------
129 template <typename Connection, typename Lockable>
130 class asio_ostream_log_backend
131  : public Connection
132  , public ostream_log_backend<Lockable> {
133 
134  using base = ostream_log_backend<Lockable>;
135 
136  void flush() noexcept final {
137  Connection::_flush();
138  }
139 
140 public:
141  asio_ostream_log_backend(
142  string_view addr_str,
143  log_event_severity min_severity)
144  : Connection(addr_str)
145  , ostream_log_backend<Lockable>(Connection::out(), min_severity) {}
146 
147  asio_ostream_log_backend(log_event_severity min_severity)
148  : asio_ostream_log_backend(string_view{}, min_severity) {}
149 
150  asio_ostream_log_backend(asio_ostream_log_backend&&) = delete;
151  asio_ostream_log_backend(const asio_ostream_log_backend&) = delete;
152  auto operator=(asio_ostream_log_backend&&) = delete;
153  auto operator=(const asio_ostream_log_backend&) = delete;
154 
155  ~asio_ostream_log_backend() noexcept override {
156  this->finish_log();
157  }
158 };
159 //------------------------------------------------------------------------------
160 #if EAGINE_POSIX
161 template <typename Lockable = std::mutex>
162 using asio_local_ostream_log_backend =
163  asio_ostream_log_backend<asio_local_ostream_log_connection, Lockable>;
164 #define EAGINE_HAS_ASIO_LOCAL_LOG_BACKEND 1
165 #else
166 #define EAGINE_HAS_ASIO_LOCAL_LOG_BACKEND 0
167 #endif // EAGINE_POSIX
168 
169 template <typename Lockable = std::mutex>
170 using asio_tcpipv4_ostream_log_backend =
171  asio_ostream_log_backend<asio_tcpipv4_ostream_log_connection, Lockable>;
172 //------------------------------------------------------------------------------
173 } // namespace eagine
174 
175 #endif // EAGINE_LOGGING_ASIO_BACKEND_HPP
basic_string_span< const char > string_view
Alias for const string views.
Definition: string_span.hpp:116
static constexpr auto c_str(memory::basic_span< C, P, S > s) -> std::enable_if_t< std::is_convertible_v< memory::basic_span< C, P, S >, basic_string_span< C, P, S >>, basic_c_str< C, P, S >>
Functions that construct a basic_c_str from a basic_string_span.
Definition: string_span.hpp:226
Common code is placed in this namespace.
Definition: eagine.hpp:21
static auto split_by_last(basic_span< T1, P1, S1 > spn, basic_span< T2, P2, S2 > what) -> std::tuple< basic_span< T1, P1, S1 >, basic_span< T1, P1, S1 >>
Splits a span by the last occurrence of what (before and after, what)
Definition: span_algo.hpp:479
static auto zero(basic_span< T, P, S > spn) -> std::enable_if_t< std::is_integral_v< T >||std::is_floating_point_v< T >, basic_span< T, P, S >>
Fills a span with zero value of type T.
Definition: span_algo.hpp:548
log_event_severity
Log event severity enumeration.
Definition: severity.hpp:18

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).