@@ -56,15 +56,13 @@ class EpollNetProvider {
56
56
~EpollNetProvider ();
57
57
int connect (Conn_t &conn, const std::string_view& addr, unsigned port,
58
58
size_t timeout);
59
- void close (int socket );
59
+ void close (Conn_t &conn );
60
60
/* * Read and write to sockets; polling using epoll. */
61
61
int wait (int timeout);
62
62
63
63
bool check (Conn_t &conn);
64
64
private:
65
65
static constexpr size_t DEFAULT_TIMEOUT = 100 ;
66
- static constexpr size_t EVENT_POLL_COUNT_MAX = 64 ;
67
- static constexpr size_t EPOLL_QUEUE_LEN = 1024 ;
68
66
static constexpr size_t EPOLL_EVENTS_MAX = 128 ;
69
67
70
68
// return 0 if all data from buffer was processed (sent or read);
@@ -73,13 +71,10 @@ class EpollNetProvider {
73
71
int send (Conn_t &conn);
74
72
int recv (Conn_t &conn);
75
73
76
- int poll (struct ConnectionEvent *fds, size_t *fd_count,
77
- int timeout = DEFAULT_TIMEOUT);
78
- void setPollSetting (int socket, int setting);
79
- void registerEpoll (int socket);
74
+ void setPollSetting (Conn_t &conn, int setting);
75
+ void registerEpoll (Conn_t &conn);
80
76
81
77
/* * <socket : connection> map. Contains both ready to read/send connections */
82
- std::map<int , Conn_t > m_Connections;
83
78
Connector_t &m_Connector;
84
79
int m_EpollFd;
85
80
};
@@ -88,7 +83,7 @@ template<class BUFFER, class NETWORK>
88
83
EpollNetProvider<BUFFER, NETWORK>::EpollNetProvider(Connector_t &connector) :
89
84
m_Connector (connector)
90
85
{
91
- m_EpollFd = epoll_create (EPOLL_QUEUE_LEN );
86
+ m_EpollFd = epoll_create1 (EPOLL_CLOEXEC );
92
87
if (m_EpollFd == -1 ) {
93
88
LOG_ERROR (" Failed to initialize epoll: " , strerror (errno));
94
89
abort ();
@@ -99,22 +94,20 @@ template<class BUFFER, class NETWORK>
99
94
EpollNetProvider<BUFFER, NETWORK>::~EpollNetProvider ()
100
95
{
101
96
::close (m_EpollFd);
102
- m_EpollFd = 0 ;
103
-
104
- for (auto conn = m_Connections.begin (); conn != m_Connections.end ();)
105
- conn = m_Connections.erase (conn);
97
+ m_EpollFd = -1 ;
106
98
}
107
99
108
100
template <class BUFFER , class NETWORK >
109
101
void
110
- EpollNetProvider<BUFFER, NETWORK>::registerEpoll(int socket )
102
+ EpollNetProvider<BUFFER, NETWORK>::registerEpoll(Conn_t &conn )
111
103
{
112
104
/* Configure epoll with new socket. */
113
105
assert (m_EpollFd >= 0 );
114
106
struct epoll_event event;
115
107
event.events = EPOLLIN;
116
- event.data .fd = socket;
117
- if (epoll_ctl (m_EpollFd, EPOLL_CTL_ADD, socket, &event) != 0 ) {
108
+ event.data .ptr = conn.getImpl ();
109
+ conn.getImpl ()->ref ();
110
+ if (epoll_ctl (m_EpollFd, EPOLL_CTL_ADD, conn.getSocket (), &event) != 0 ) {
118
111
LOG_ERROR (" Failed to add socket to epoll: "
119
112
" epoll_ctl() returned with errno: " ,
120
113
strerror (errno));
@@ -124,11 +117,11 @@ EpollNetProvider<BUFFER, NETWORK>::registerEpoll(int socket)
124
117
125
118
template <class BUFFER , class NETWORK >
126
119
void
127
- EpollNetProvider<BUFFER, NETWORK>::setPollSetting(int socket , int setting) {
120
+ EpollNetProvider<BUFFER, NETWORK>::setPollSetting(Conn_t &conn , int setting) {
128
121
struct epoll_event event;
129
122
event.events = setting;
130
- event.data .fd = socket ;
131
- if (epoll_ctl (m_EpollFd, EPOLL_CTL_MOD, socket , &event) != 0 ) {
123
+ event.data .ptr = conn. getImpl () ;
124
+ if (epoll_ctl (m_EpollFd, EPOLL_CTL_MOD, conn. getSocket () , &event) != 0 ) {
132
125
LOG_ERROR (" Failed to change epoll mode: "
133
126
" epoll_ctl() returned with errno: " ,
134
127
strerror (errno));
@@ -173,16 +166,16 @@ EpollNetProvider<BUFFER, NETWORK>::connect(Conn_t &conn,
173
166
LOG_DEBUG (" Greetings are decoded" );
174
167
LOG_DEBUG (" Authentication processing..." );
175
168
// TODO: add authentication step.
176
- registerEpoll (socket);
177
169
conn.setSocket (socket);
178
- m_Connections. insert ({socket, conn} );
170
+ registerEpoll ( conn);
179
171
return 0 ;
180
172
}
181
173
182
174
template <class BUFFER , class NETWORK >
183
175
void
184
- EpollNetProvider<BUFFER, NETWORK>::close(int socket )
176
+ EpollNetProvider<BUFFER, NETWORK>::close(Conn_t& conn )
185
177
{
178
+ int socket = conn.getSocket ();
186
179
assert (socket >= 0 );
187
180
#ifndef NDEBUG
188
181
struct sockaddr sa;
@@ -201,46 +194,15 @@ EpollNetProvider<BUFFER, NETWORK>::close(int socket)
201
194
" corresponding to address " , addr);
202
195
}
203
196
#endif
197
+ conn.getImpl ()->unref ();
204
198
NETWORK::close (socket);
205
- struct epoll_event event;
206
- event.events = EPOLLIN;
207
- event.data .fd = socket;
208
199
/*
209
200
* Descriptor is automatically removed from epoll handler
210
201
* when all descriptors are closed. So in case
211
202
* there's other descriptors on open socket, invoke
212
203
* epoll_ctl manually.
213
204
*/
214
- epoll_ctl (m_EpollFd, EPOLL_CTL_DEL, socket, &event);
215
- // close can be called during epoll provider destruction. In this case
216
- // all connections staying alive only due to the presence in m_Connections
217
- // map. While cleaning up m_Connections destructors of connections will be
218
- // called. So to avoid double-free presence check in m_Connections is required.
219
- if (m_Connections.find (socket) != m_Connections.end ()) {
220
- assert (m_Connections.find (socket)->second .getSocket () == socket);
221
- m_Connections.erase (socket);
222
- }
223
- }
224
-
225
- template <class BUFFER , class NETWORK >
226
- int
227
- EpollNetProvider<BUFFER, NETWORK>::poll(struct ConnectionEvent *fds,
228
- size_t *fd_count, int timeout)
229
- {
230
- static struct epoll_event events[EPOLL_EVENTS_MAX];
231
- *fd_count = 0 ;
232
- int event_cnt = epoll_wait (m_EpollFd, events, EPOLL_EVENTS_MAX,
233
- timeout);
234
- if (event_cnt == -1 )
235
- return -1 ;
236
- assert (event_cnt >= 0 );
237
- for (int i = 0 ; i < event_cnt; ++i) {
238
- fds[*fd_count].sock = events[i].data .fd ;
239
- fds[*fd_count].event = events[i].events ;
240
- (*fd_count)++;
241
- }
242
- assert (*fd_count == (size_t ) event_cnt);
243
- return 0 ;
205
+ epoll_ctl (m_EpollFd, EPOLL_CTL_DEL, socket, nullptr );
244
206
}
245
207
246
208
template <class BUFFER , class NETWORK >
@@ -286,7 +248,7 @@ EpollNetProvider<BUFFER, NETWORK>::send(Conn_t &conn)
286
248
hasSentBytes (conn, sent_bytes);
287
249
if (rc != 0 ) {
288
250
if (netWouldBlock (errno)) {
289
- setPollSetting (conn. getSocket () , EPOLLIN | EPOLLOUT);
251
+ setPollSetting (conn, EPOLLIN | EPOLLOUT);
290
252
return 1 ;
291
253
}
292
254
conn.setError (std::string (" Failed to send request: " ) +
@@ -316,19 +278,17 @@ EpollNetProvider<BUFFER, NETWORK>::wait(int timeout)
316
278
}
317
279
318
280
/* Firstly poll connections to point out if there's data to read. */
319
- static struct ConnectionEvent events[EVENT_POLL_COUNT_MAX ];
320
- size_t event_cnt = 0 ;
321
- if (poll ((ConnectionEvent *)&events, & event_cnt, timeout) != 0 ) {
281
+ struct epoll_event events[EPOLL_EVENTS_MAX ];
282
+ int event_cnt = epoll_wait (m_EpollFd, events, EPOLL_EVENTS_MAX, timeout) ;
283
+ if (event_cnt < 0 ) {
322
284
// Poll error doesn't belong to any connection so just global
323
285
// log it.
324
286
LOG_ERROR (" Poll failed: " , strerror (errno));
325
287
return -1 ;
326
288
}
327
- for (size_t i = 0 ; i < event_cnt; ++i) {
328
- assert (m_Connections.find (events[i].sock ) != m_Connections.end ());
329
- if ((events[i].event & EPOLLIN) != 0 ) {
330
- Conn_t conn = m_Connections.find (events[i].sock )->second ;
331
- assert (conn.getSocket () == events[i].sock );
289
+ for (int i = 0 ; i < event_cnt; ++i) {
290
+ Conn_t conn ((typename Conn_t::Impl_t *)events[i].data .ptr );
291
+ if ((events[i].events & EPOLLIN) != 0 ) {
332
292
LOG_DEBUG (" Registered poll event " , i, " : " ,
333
293
conn.getSocket (), " socket is ready to read" );
334
294
/*
@@ -342,9 +302,7 @@ EpollNetProvider<BUFFER, NETWORK>::wait(int timeout)
342
302
m_Connector.readyToDecode (conn);
343
303
}
344
304
345
- if ((events[i].event & EPOLLOUT) != 0 ) {
346
- Conn_t conn = m_Connections.find (events[i].sock )->second ;
347
- assert (conn.getSocket () == events[i].sock );
305
+ if ((events[i].events & EPOLLOUT) != 0 ) {
348
306
LOG_DEBUG (" Registered poll event " , i, " : " ,
349
307
conn.getSocket (), " socket is ready to write" );
350
308
int rc = send (conn);
@@ -353,7 +311,7 @@ EpollNetProvider<BUFFER, NETWORK>::wait(int timeout)
353
311
/* All data from connection has been successfully written. */
354
312
if (rc == 0 ) {
355
313
m_Connector.finishSend (conn);
356
- setPollSetting (conn. getSocket () , EPOLLIN);
314
+ setPollSetting (conn, EPOLLIN);
357
315
}
358
316
}
359
317
}
0 commit comments