File indexing completed on 2025-01-18 09:28:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
0013 #define BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
0014
0015 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0016 # pragma once
0017 #endif
0018
0019 #include <boost/asio/detail/config.hpp>
0020
0021 #if defined(BOOST_ASIO_HAS_EVENTFD)
0022
0023 #include <sys/stat.h>
0024 #include <sys/types.h>
0025 #include <fcntl.h>
0026 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
0027 # include <asm/unistd.h>
0028 #else
0029 # include <sys/eventfd.h>
0030 #endif
0031 #include <boost/asio/detail/cstdint.hpp>
0032 #include <boost/asio/detail/eventfd_select_interrupter.hpp>
0033 #include <boost/asio/detail/throw_error.hpp>
0034 #include <boost/asio/error.hpp>
0035
0036 #include <boost/asio/detail/push_options.hpp>
0037
0038 namespace boost {
0039 namespace asio {
0040 namespace detail {
0041
0042 eventfd_select_interrupter::eventfd_select_interrupter()
0043 {
0044 open_descriptors();
0045 }
0046
0047 void eventfd_select_interrupter::open_descriptors()
0048 {
0049 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)
0050 write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
0051 if (read_descriptor_ != -1)
0052 {
0053 ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
0054 ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
0055 }
0056 #else
0057 # if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)
0058 write_descriptor_ = read_descriptor_ =
0059 ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
0060 # else
0061 errno = EINVAL;
0062 write_descriptor_ = read_descriptor_ = -1;
0063 # endif
0064 if (read_descriptor_ == -1 && errno == EINVAL)
0065 {
0066 write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
0067 if (read_descriptor_ != -1)
0068 {
0069 ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
0070 ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
0071 }
0072 }
0073 #endif
0074
0075 if (read_descriptor_ == -1)
0076 {
0077 int pipe_fds[2];
0078 if (pipe(pipe_fds) == 0)
0079 {
0080 read_descriptor_ = pipe_fds[0];
0081 ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
0082 ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);
0083 write_descriptor_ = pipe_fds[1];
0084 ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
0085 ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);
0086 }
0087 else
0088 {
0089 boost::system::error_code ec(errno,
0090 boost::asio::error::get_system_category());
0091 boost::asio::detail::throw_error(ec, "eventfd_select_interrupter");
0092 }
0093 }
0094 }
0095
0096 eventfd_select_interrupter::~eventfd_select_interrupter()
0097 {
0098 close_descriptors();
0099 }
0100
0101 void eventfd_select_interrupter::close_descriptors()
0102 {
0103 if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
0104 ::close(write_descriptor_);
0105 if (read_descriptor_ != -1)
0106 ::close(read_descriptor_);
0107 }
0108
0109 void eventfd_select_interrupter::recreate()
0110 {
0111 close_descriptors();
0112
0113 write_descriptor_ = -1;
0114 read_descriptor_ = -1;
0115
0116 open_descriptors();
0117 }
0118
0119 void eventfd_select_interrupter::interrupt()
0120 {
0121 uint64_t counter(1UL);
0122 int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
0123 (void)result;
0124 }
0125
0126 bool eventfd_select_interrupter::reset()
0127 {
0128 if (write_descriptor_ == read_descriptor_)
0129 {
0130 for (;;)
0131 {
0132
0133 uint64_t counter(0);
0134 errno = 0;
0135 int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
0136 if (bytes_read < 0 && errno == EINTR)
0137 continue;
0138 return true;
0139 }
0140 }
0141 else
0142 {
0143 for (;;)
0144 {
0145
0146 char data[1024];
0147 int bytes_read = ::read(read_descriptor_, data, sizeof(data));
0148 if (bytes_read == sizeof(data))
0149 continue;
0150 if (bytes_read > 0)
0151 return true;
0152 if (bytes_read == 0)
0153 return false;
0154 if (errno == EINTR)
0155 continue;
0156 if (errno == EWOULDBLOCK)
0157 return true;
0158 if (errno == EAGAIN)
0159 return true;
0160 return false;
0161 }
0162 }
0163 }
0164
0165 }
0166 }
0167 }
0168
0169 #include <boost/asio/detail/pop_options.hpp>
0170
0171 #endif
0172
0173 #endif