28
28
#include < mutex> // NOLINT(build/c++11)
29
29
#include < new>
30
30
31
- #include " my_io.h" // NOLINT(build/include_subdir)
31
+ #include " my_io.h" // NOLINT(build/include_subdir)
32
+ #include " mysql/psi/mysql_socket.h"
32
33
#include " violite.h" // NOLINT(build/include_subdir)
33
34
34
35
#include " plugin/x/src/interface/connection_acceptor.h"
37
38
#include " plugin/x/src/ngs/socket_events.h"
38
39
#include " plugin/x/src/operations_factory.h"
39
40
40
- // Surpressing numerous warnings generated by libevent on Windows.
41
- #ifdef WIN32
42
- #pragma warning(push)
43
- #pragma warning(disable : 4005)
44
- #endif // WIN32
45
- #include < event2/event.h> // libevent
46
- #include < event2/event_compat.h>
47
- #include < event2/event_struct.h>
48
- #include < event2/thread.h>
49
- #ifdef WIN32
50
- #pragma warning(pop)
51
- #endif // WIN32
52
-
53
- #ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
54
- #define XPL_EVTHREAD_INITIALIZE () evthread_use_windows_threads()
55
- #elif EVTHREAD_USE_PTHREADS_IMPLEMENTED
56
- #define XPL_EVTHREAD_INITIALIZE () evthread_use_pthreads()
57
- #else
58
- #define XPL_EVTHREAD_INITIALIZE () \
59
- do { \
60
- } while (0 )
61
- #endif
62
-
63
41
namespace ngs {
64
42
43
+ using TcpAcceptor = net::ip::tcp::acceptor;
44
+ using Socket = TcpAcceptor::socket_type;
45
+ using Endpoint_type = TcpAcceptor::endpoint_type;
46
+
65
47
class Connection_acceptor_socket : public xpl ::iface::Connection_acceptor {
66
48
public:
67
49
using Socket_ptr = std::shared_ptr<xpl::iface::Socket>;
@@ -112,65 +94,55 @@ class Connection_acceptor_socket : public xpl::iface::Connection_acceptor {
112
94
static const int MAX_ACCEPT_REATTEMPT = 10 ;
113
95
};
114
96
115
- struct Socket_events ::Timer_data {
116
- std::function<bool ()> callback;
117
- event ev;
118
- timeval tv;
119
- Socket_events *self;
97
+ class Socket_events ::EntryTimer {
98
+ public:
99
+ EntryTimer (net::io_context &io) : timer{io} {}
120
100
121
- static void free (Timer_data *data) {
122
- evtimer_del (&data-> ev ) ;
123
- free_object (data) ;
124
- }
101
+ public:
102
+ std::function< bool ()> callback ;
103
+ std::chrono::milliseconds duration ;
104
+ net::steady_timer timer;
125
105
};
126
106
127
- struct Socket_events ::Socket_data {
107
+ class Socket_events ::EntryAcceptingSocket {
108
+ public:
109
+ EntryAcceptingSocket (net::io_context &io) : acceptor{io} {}
110
+ ~EntryAcceptingSocket () { acceptor.release (); }
111
+
112
+ public:
128
113
std::function<void (xpl::iface::Connection_acceptor &)> callback;
129
- event ev;
130
114
std::shared_ptr<xpl::iface::Socket> socket;
131
-
132
- static void free (Socket_data *data) {
133
- event_del (&data->ev );
134
- free_object (data);
135
- }
115
+ TcpAcceptor acceptor;
136
116
};
137
117
138
- Socket_events::Socket_events () {
139
- static std::once_flag flag_event_threads_initialized;
140
-
141
- std::call_once (flag_event_threads_initialized,
142
- []() { XPL_EVTHREAD_INITIALIZE (); });
143
-
144
- m_evbase = event_base_new ();
145
-
146
- if (!m_evbase) throw std::bad_alloc ();
147
- }
118
+ Socket_events::Socket_events () {}
148
119
149
120
Socket_events::~Socket_events () {
150
121
std::for_each (m_timer_events.begin (), m_timer_events.end (),
151
- &Timer_data::free );
122
+ &free_object<EntryTimer> );
152
123
153
124
std::for_each (m_socket_events.begin (), m_socket_events.end (),
154
- &Socket_data::free);
155
-
156
- event_base_free (m_evbase);
125
+ &free_object<EntryAcceptingSocket>);
157
126
}
158
127
159
128
bool Socket_events::listen (
160
129
std::shared_ptr<xpl::iface::Socket> sock,
161
130
std::function<void (xpl::iface::Connection_acceptor &)> callback) {
162
- m_socket_events.push_back (allocate_object<Socket_data>());
163
- Socket_data *socket_event = m_socket_events.back ();
131
+ m_socket_events.push_back (
132
+ allocate_object<EntryAcceptingSocket>(m_io_context));
133
+ EntryAcceptingSocket *socket_event = m_socket_events.back ();
164
134
165
135
socket_event->callback = callback;
166
136
socket_event->socket = sock;
137
+ socket_event->acceptor .assign (Endpoint_type ().protocol (),
138
+ sock->get_socket_fd ());
167
139
168
- event_set (& socket_event->ev , static_cast < int >(sock-> get_socket_fd ()) ,
169
- EV_READ | EV_PERSIST, &Socket_events::socket_data_avaiable,
170
- socket_event);
171
- event_base_set (m_evbase, &socket_event-> ev );
140
+ socket_event->acceptor . async_wait (Socket::wait_read ,
141
+ [ this , socket_event](std::error_code ec) {
142
+ callback_accept_socket ( socket_event, ec );
143
+ } );
172
144
173
- return 0 == event_add (&socket_event-> ev , nullptr ) ;
145
+ return true ;
174
146
}
175
147
176
148
/* * Register a callback to be executed in a fixed time interval.
@@ -182,53 +154,61 @@ NOTE: This method may only be called from the same thread as the event loop.
182
154
*/
183
155
void Socket_events::add_timer (const std::size_t delay_ms,
184
156
std::function<bool ()> callback) {
185
- Timer_data *data = allocate_object<Timer_data>();
186
- data->tv .tv_sec = static_cast <long >(delay_ms / 1000 );
187
- data->tv .tv_usec = (delay_ms % 1000 ) * 1000 ;
188
- data->callback = callback;
189
- data->self = this ;
190
- // XXX use persistent timer events after switch to libevent2
191
- evtimer_set (&data->ev , timeout_call, data);
192
- event_base_set (m_evbase, &data->ev );
193
- evtimer_add (&data->ev , &data->tv );
194
-
195
- MUTEX_LOCK (lock, m_timers_mutex);
196
- m_timer_events.push_back (data);
197
- }
198
-
199
- void Socket_events::loop () { event_base_loop (m_evbase, 0 ); }
157
+ EntryTimer *timer_entry = allocate_object<EntryTimer>(m_io_context);
158
+ timer_entry->duration = std::chrono::milliseconds{delay_ms};
159
+ timer_entry->callback = callback;
160
+ {
161
+ MUTEX_LOCK (lock, m_timers_mutex);
162
+ m_timer_events.push_back (timer_entry);
163
+ }
200
164
201
- void Socket_events::break_loop () { event_base_loopexit (m_evbase, nullptr ); }
165
+ timer_entry->timer .expires_after (timer_entry->duration );
166
+ timer_entry->timer .async_wait ([this , timer_entry](std::error_code ec) {
167
+ callback_timeout (timer_entry, ec);
168
+ });
169
+ }
202
170
203
- void Socket_events::timeout_call (socket_type, short , void *arg) {
204
- Timer_data *data = static_cast <Timer_data *>(arg);
171
+ void Socket_events::loop () { m_io_context.run (); }
205
172
206
- if (!data->callback ()) {
207
- evtimer_del (&data->ev );
173
+ void Socket_events::break_loop () { m_io_context.stop (); }
208
174
175
+ void Socket_events::callback_timeout (EntryTimer *timer_entry,
176
+ std::error_code ec) {
177
+ if (ec || !timer_entry->callback ()) {
209
178
{
210
- MUTEX_LOCK (timer_lock, data-> self -> m_timers_mutex );
211
- data-> self -> m_timer_events . erase (
212
- std::remove (data-> self -> m_timer_events .begin (),
213
- data-> self -> m_timer_events .end (), data ),
214
- data-> self -> m_timer_events .end ());
179
+ MUTEX_LOCK (timer_lock, m_timers_mutex);
180
+
181
+ m_timer_events. erase ( std::remove (m_timer_events.begin (),
182
+ m_timer_events.end (), timer_entry ),
183
+ m_timer_events.end ());
215
184
}
216
185
217
- free_object (data );
186
+ free_object (timer_entry );
218
187
} else {
219
188
// schedule for another round
220
- evtimer_add (&data->ev , &data->tv );
189
+ timer_entry->timer .expires_after (timer_entry->duration );
190
+ timer_entry->timer .async_wait ([this , timer_entry](std::error_code ec) {
191
+ callback_timeout (timer_entry, ec);
192
+ });
221
193
}
222
194
}
223
195
224
- void Socket_events::socket_data_avaiable (socket_type, short , void *arg) {
225
- Socket_data *data = static_cast <Socket_data *>(arg);
226
- xpl::Operations_factory operations_factory;
227
- std::shared_ptr<xpl::iface::System> system_interface (
228
- operations_factory.create_system_interface ());
229
- Connection_acceptor_socket acceptor (data->socket , *system_interface);
230
-
231
- data->callback (acceptor);
196
+ void Socket_events::callback_accept_socket (
197
+ EntryAcceptingSocket *acceptors_entry, std::error_code ec) {
198
+ if (!ec) {
199
+ xpl::Operations_factory operations_factory;
200
+ std::shared_ptr<xpl::iface::System> system_interface (
201
+ operations_factory.create_system_interface ());
202
+ Connection_acceptor_socket vio_socket_forge (acceptors_entry->socket ,
203
+ *system_interface);
204
+
205
+ acceptors_entry->callback (vio_socket_forge);
206
+
207
+ acceptors_entry->acceptor .async_wait (
208
+ Socket::wait_read, [this , acceptors_entry](std::error_code ec) {
209
+ callback_accept_socket (acceptors_entry, ec);
210
+ });
211
+ }
232
212
}
233
213
234
214
} // namespace ngs
0 commit comments