Skip to content

Commit a3a4e34

Browse files
authored
Refactor fd set (#387)
* Implement reactor by poll Notes: - [x] Reimplement reactor backends: select, poll - [x] Now the default reactor backend is poll - [x] Add compiler flag `YASIO_DISABLE_POLL` for switching to socket.select as same with previous releases
1 parent 98a2595 commit a3a4e34

9 files changed

Lines changed: 334 additions & 121 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
yasio-3.39.6
2+
3+
1. Reimplement reactor backends: select, poll
4+
2. Now the default reactor backend is poll
5+
3. Add compiler flag `YASIO_DISABLE_POLL` for switching to socket.select as same with previous releases
6+
7+
18
yasio-3.39.5
29

310
1. Fix no callback when resolve domain failed by `getaddrinfo`

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ macro (yasio_config_lib_options target_name)
401401
yasio_config_pred(${target_name} YASIO_HAVE_HALF_FLOAT)
402402
yasio_config_pred(${target_name} YASIO_ENABLE_PASSIVE_EVENT)
403403
yasio_config_pred(${target_name} YASIO_NO_JNI_ONLOAD)
404+
yasio_config_pred(${target_name} YASIO_DISABLE_POLL)
404405
endmacro()
405406

406407
yasio_config_lib_options(${yasio_target_name})

yasio/detail/config.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ SOFTWARE.
9797
// #define YASIO_ENABLE_UDS 1
9898

9999
/*
100-
** Uncomment or add compiler flag -DYASIO_NT_COMPAT_GAI for earlier versions of Windows XP
100+
** Uncomment or add compiler flag -DYASIO_NT_COMPAT_GAI for compatible with Windows XP
101101
** see: https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo
102102
*/
103103
// #define YASIO_NT_COMPAT_GAI 1
@@ -128,6 +128,12 @@ SOFTWARE.
128128
*/
129129
// #define YASIO_OBS_BUILTIN_STACK 1
130130

131+
/*
132+
** Uncomment or add compiler flag -DYASIO_DISABLE_POLL to use socket.select for all platforms
133+
** If you need support Windows XP, you need disable poll
134+
*/
135+
// #define YASIO_DISABLE_POLL 1
136+
131137
/*
132138
** Workaround for 'vs2013 without full c++11 support', in the future, drop vs2013 support and
133139
** follow 3 lines code will be removed
@@ -192,7 +198,7 @@ SOFTWARE.
192198
/*
193199
** The yasio version macros
194200
*/
195-
#define YASIO_VERSION_NUM 0x033905
201+
#define YASIO_VERSION_NUM 0x033906
196202

197203
/*
198204
** The macros used by io_service.

yasio/detail/fd_set_adapter.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////
2+
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
3+
// client application.
4+
//////////////////////////////////////////////////////////////////////////////////////////
5+
//
6+
// detail/fd_set_adapter.hpp
7+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
//
9+
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)
10+
11+
#pragma once
12+
13+
#include "yasio/detail/config.hpp"
14+
15+
#if !defined(YASIO_DISABLE_POLL)
16+
# include "yasio/detail/poll_fd_set.hpp"
17+
#else
18+
# include "yasio/detail/select_fd_set.hpp"
19+
#endif
20+
21+
namespace yasio
22+
{
23+
YASIO__NS_INLINE
24+
namespace inet
25+
{
26+
#if !defined(YASIO_DISABLE_POLL)
27+
using fd_set_adapter = poll_fd_set;
28+
#else
29+
using fd_set_adapter = select_fd_set;
30+
#endif
31+
} // namespace inet
32+
} // namespace yasio

yasio/detail/poll_fd_set.hpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////
2+
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
3+
// client application.
4+
//////////////////////////////////////////////////////////////////////////////////////////
5+
//
6+
// detail/poll_fd_set.hpp
7+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
//
9+
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)
10+
#pragma once
11+
#include <vector>
12+
#include "yasio/detail/socket.hpp"
13+
14+
namespace yasio
15+
{
16+
YASIO__NS_INLINE
17+
namespace inet
18+
{
19+
class poll_fd_set {
20+
public:
21+
poll_fd_set& operator=(poll_fd_set& rhs)
22+
{
23+
this->fd_set_ = rhs.fd_set_;
24+
return *this;
25+
}
26+
27+
void reset() { this->fd_set_.clear(); }
28+
29+
int poll_io(timeval& waitd_tv) { return ::poll(this->fd_set_.data(), static_cast<int>(this->fd_set_.size()), waitd_tv.tv_sec * 1000 + waitd_tv.tv_usec / 1000); }
30+
31+
int is_set(socket_native_type fd, int events) const
32+
{
33+
int underlying_events = 0;
34+
if (events & socket_event::read)
35+
underlying_events |= POLLIN;
36+
if (events & socket_event::write)
37+
underlying_events |= POLLOUT;
38+
if (events & socket_event::error)
39+
underlying_events |= (POLLERR | POLLHUP | POLLNVAL);
40+
auto it = std::find_if(this->fd_set_.begin(), this->fd_set_.end(), [fd](const pollfd& pfd) { return pfd.fd == fd; });
41+
return it != this->fd_set_.end() ? (it->revents & underlying_events) : 0;
42+
}
43+
44+
void set(socket_native_type fd, int events)
45+
{
46+
int underlying_events = 0;
47+
if (yasio__testbits(events, socket_event::read))
48+
underlying_events |= POLLIN;
49+
50+
if (yasio__testbits(events, socket_event::write))
51+
underlying_events |= POLLOUT;
52+
53+
if (yasio__testbits(events, socket_event::error))
54+
underlying_events |= POLLERR;
55+
pollfd_mod(this->fd_set_, fd, underlying_events, 0);
56+
}
57+
58+
void unset(socket_native_type fd, int events)
59+
{
60+
int underlying_events = 0;
61+
if (yasio__testbits(events, socket_event::read))
62+
underlying_events |= POLLIN;
63+
64+
if (yasio__testbits(events, socket_event::write))
65+
underlying_events |= POLLOUT;
66+
67+
if (yasio__testbits(events, socket_event::error))
68+
underlying_events |= POLLERR;
69+
70+
pollfd_mod(this->fd_set_, fd, 0, underlying_events);
71+
}
72+
73+
protected:
74+
static void pollfd_mod(std::vector<pollfd>& fdset, socket_native_type fd, int add_events, int remove_events)
75+
{
76+
auto it = std::find_if(fdset.begin(), fdset.end(), [fd](const pollfd& pfd) { return pfd.fd == fd; });
77+
if (it != fdset.end())
78+
{
79+
it->events |= add_events;
80+
it->events &= ~remove_events;
81+
if (it->events == 0)
82+
fdset.erase(it);
83+
}
84+
else
85+
{
86+
auto events = add_events & ~remove_events;
87+
if (events)
88+
fdset.push_back(pollfd{fd, static_cast<short>(events), 0});
89+
}
90+
}
91+
92+
protected:
93+
std::vector<pollfd> fd_set_;
94+
};
95+
} // namespace inet
96+
} // namespace yasio

yasio/detail/select_fd_set.hpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//////////////////////////////////////////////////////////////////////////////////////////
2+
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
3+
// client application.
4+
//////////////////////////////////////////////////////////////////////////////////////////
5+
//
6+
// detail/select_fd_set.hpp
7+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8+
//
9+
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)
10+
#pragma once
11+
12+
#include <vector>
13+
#include "yasio/detail/socket.hpp"
14+
15+
namespace yasio
16+
{
17+
YASIO__NS_INLINE
18+
namespace inet
19+
{
20+
class select_fd_set {
21+
public:
22+
select_fd_set() { reset(); }
23+
24+
void reset()
25+
{
26+
FD_ZERO(&fd_set_[read_op]);
27+
FD_ZERO(&fd_set_[write_op]);
28+
FD_ZERO(&fd_set_[except_op]);
29+
max_nfds_ = 0;
30+
}
31+
32+
select_fd_set& operator=(select_fd_set& rhs)
33+
{
34+
::memcpy(this->fd_set_, rhs.fd_set_, sizeof(rhs.fd_set_));
35+
max_nfds_ = rhs.max_nfds_;
36+
return *this;
37+
}
38+
39+
int poll_io(timeval& waitd_tv)
40+
{
41+
return ::select(this->max_nfds_, &(fd_set_[read_op]), &(fd_set_[write_op]), nullptr, &waitd_tv);
42+
}
43+
44+
int is_set(socket_native_type fd, int events) const
45+
{
46+
int retval = 0;
47+
if (events & socket_event::read)
48+
retval |= FD_ISSET(fd, &fd_set_[read_op]);
49+
if (events & socket_event::write)
50+
retval |= FD_ISSET(fd, &fd_set_[write_op]);
51+
if (events & socket_event::error)
52+
retval |= FD_ISSET(fd, &fd_set_[except_op]);
53+
return retval;
54+
}
55+
56+
void set(socket_native_type fd, int events)
57+
{
58+
if (yasio__testbits(events, socket_event::read))
59+
FD_SET(fd, &(fd_set_[read_op]));
60+
61+
if (yasio__testbits(events, socket_event::write))
62+
FD_SET(fd, &(fd_set_[write_op]));
63+
64+
if (yasio__testbits(events, socket_event::error))
65+
FD_SET(fd, &(fd_set_[except_op]));
66+
67+
if (max_nfds_ < static_cast<int>(fd) + 1)
68+
max_nfds_ = static_cast<int>(fd) + 1;
69+
}
70+
71+
void unset(socket_native_type fd, int events)
72+
{
73+
if (yasio__testbits(events, socket_event::read))
74+
FD_CLR(fd, &(fd_set_[read_op]));
75+
76+
if (yasio__testbits(events, socket_event::write))
77+
FD_CLR(fd, &(fd_set_[write_op]));
78+
79+
if (yasio__testbits(events, socket_event::error))
80+
FD_CLR(fd, &(fd_set_[except_op]));
81+
}
82+
83+
protected:
84+
enum
85+
{
86+
read_op,
87+
write_op,
88+
except_op,
89+
max_ops,
90+
};
91+
fd_set fd_set_[max_ops];
92+
int max_nfds_ = 0;
93+
};
94+
} // namespace inet
95+
} // namespace yasio

yasio/detail/socket.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,25 @@ inline bool IN6_IS_ADDR_GLOBAL(const in6_addr* a)
228228

229229
#define YASIO_ADDR_ANY(af) (af == AF_INET ? "0.0.0.0" : "::")
230230

231+
#define yasio__setbits(x, m) ((x) |= (m))
232+
#define yasio__clearbits(x, m) ((x) &= ~(m))
233+
#define yasio__testbits(x, m) ((x) & (m))
234+
#define yasio__setlobyte(x, v) ((x) = ((x) & ~((decltype(x))0xff)) | (v))
235+
236+
namespace yasio
237+
{
238+
YASIO__NS_INLINE
239+
namespace inet
240+
{
241+
struct socket_event {
242+
enum
243+
{ // event mask
244+
read = 1,
245+
write = 2,
246+
error = 4,
247+
readwrite = read | write,
248+
};
249+
};
250+
}
251+
} // namespace yasio
231252
#endif

0 commit comments

Comments
 (0)