mirror of
https://github.com/chriskohlhoff/asio.git
synced 2026-01-18 16:51:17 +01:00
Add config option to determine whether eventfd is used.
Add a new configuration option "reactor" / "use_eventfd" that is used by the epoll_reactor. When true (the default), the reactor uses an eventfd as its select_interrupter implementation. When false, a pipe is used instead.
This commit is contained in:
@@ -29,7 +29,7 @@ class eventfd_select_interrupter
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
ASIO_DECL eventfd_select_interrupter();
|
||||
ASIO_DECL explicit eventfd_select_interrupter(bool use_eventfd = true);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~eventfd_select_interrupter();
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
private:
|
||||
// Open the descriptors. Throws on error.
|
||||
ASIO_DECL void open_descriptors();
|
||||
ASIO_DECL void open_descriptors(bool use_eventfd);
|
||||
|
||||
// Close the descriptors.
|
||||
ASIO_DECL void close_descriptors();
|
||||
|
||||
@@ -41,7 +41,7 @@ epoll_reactor::epoll_reactor(asio::execution_context& ctx)
|
||||
scheduler_(use_service<scheduler>(ctx)),
|
||||
mutex_(config(ctx).get("reactor", "registration_locking", true),
|
||||
config(ctx).get("reactor", "registration_locking_spin_count", 0)),
|
||||
interrupter_(),
|
||||
interrupter_(config(ctx).get("reactor", "use_eventfd", true)),
|
||||
epoll_fd_(do_epoll_create()),
|
||||
timer_fd_(config(ctx).get("reactor", "use_timerfd", true)
|
||||
? do_timerfd_create() : -1),
|
||||
|
||||
@@ -38,38 +38,43 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
eventfd_select_interrupter::eventfd_select_interrupter()
|
||||
eventfd_select_interrupter::eventfd_select_interrupter(bool use_eventfd)
|
||||
{
|
||||
open_descriptors();
|
||||
open_descriptors(use_eventfd);
|
||||
}
|
||||
|
||||
void eventfd_select_interrupter::open_descriptors()
|
||||
void eventfd_select_interrupter::open_descriptors(bool use_eventfd)
|
||||
{
|
||||
if (use_eventfd)
|
||||
{
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
|
||||
if (read_descriptor_ != -1)
|
||||
{
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
write_descriptor_ = read_descriptor_ =
|
||||
::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
errno = EINVAL;
|
||||
write_descriptor_ = read_descriptor_ = -1;
|
||||
# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
if (read_descriptor_ == -1 && errno == EINVAL)
|
||||
{
|
||||
write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
|
||||
write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
|
||||
if (read_descriptor_ != -1)
|
||||
{
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
write_descriptor_ = read_descriptor_ =
|
||||
::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||
# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
errno = EINVAL;
|
||||
write_descriptor_ = read_descriptor_ = -1;
|
||||
# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
|
||||
if (read_descriptor_ == -1 && errno == EINVAL)
|
||||
{
|
||||
write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
|
||||
if (read_descriptor_ != -1)
|
||||
{
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
|
||||
}
|
||||
else
|
||||
write_descriptor_ = read_descriptor_ = -1;
|
||||
|
||||
if (read_descriptor_ == -1)
|
||||
{
|
||||
@@ -107,12 +112,10 @@ void eventfd_select_interrupter::close_descriptors()
|
||||
|
||||
void eventfd_select_interrupter::recreate()
|
||||
{
|
||||
bool use_eventfd = (write_descriptor_ == read_descriptor_);
|
||||
close_descriptors();
|
||||
|
||||
write_descriptor_ = -1;
|
||||
read_descriptor_ = -1;
|
||||
|
||||
open_descriptors();
|
||||
write_descriptor_ = read_descriptor_ = -1;
|
||||
open_descriptors(use_eventfd);
|
||||
}
|
||||
|
||||
void eventfd_select_interrupter::interrupt()
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
pipe_select_interrupter::pipe_select_interrupter()
|
||||
pipe_select_interrupter::pipe_select_interrupter(bool)
|
||||
{
|
||||
open_descriptors();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
socket_select_interrupter::socket_select_interrupter()
|
||||
socket_select_interrupter::socket_select_interrupter(bool)
|
||||
{
|
||||
open_descriptors();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class pipe_select_interrupter
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
ASIO_DECL pipe_select_interrupter();
|
||||
ASIO_DECL explicit pipe_select_interrupter(bool = true);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~pipe_select_interrupter();
|
||||
|
||||
@@ -34,7 +34,7 @@ class socket_select_interrupter
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
ASIO_DECL socket_select_interrupter();
|
||||
ASIO_DECL explicit socket_select_interrupter(bool = true);
|
||||
|
||||
// Destructor.
|
||||
ASIO_DECL ~socket_select_interrupter();
|
||||
|
||||
@@ -177,6 +177,18 @@ below.
|
||||
fails with `EAGAIN`.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`reactor`]
|
||||
[`use_eventfd`]
|
||||
[`bool`]
|
||||
[`true`]
|
||||
[
|
||||
Linux [^epoll] backend only.
|
||||
|
||||
When `true`, the reactor uses an [^eventfd] descriptor to wake a blocked
|
||||
[^epoll_wait] call. When `false`, a pipe is used instead.
|
||||
]
|
||||
]
|
||||
[
|
||||
[`reactor`]
|
||||
[`use_timerfd`]
|
||||
|
||||
Reference in New Issue
Block a user