Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
yasio-3.39.6

1. Reimplement reactor backends: select, poll
2. Now the default reactor backend is poll
3. Add compiler flag `YASIO_DISABLE_POLL` for switching to socket.select as same with previous releases


yasio-3.39.5

1. Fix no callback when resolve domain failed by `getaddrinfo`
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ macro (yasio_config_lib_options target_name)
yasio_config_pred(${target_name} YASIO_HAVE_HALF_FLOAT)
yasio_config_pred(${target_name} YASIO_ENABLE_PASSIVE_EVENT)
yasio_config_pred(${target_name} YASIO_NO_JNI_ONLOAD)
yasio_config_pred(${target_name} YASIO_DISABLE_POLL)
endmacro()

yasio_config_lib_options(${yasio_target_name})
Expand Down
10 changes: 8 additions & 2 deletions yasio/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ SOFTWARE.
// #define YASIO_ENABLE_UDS 1

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

/*
** Uncomment or add compiler flag -DYASIO_DISABLE_POLL to use socket.select for all platforms
** If you need support Windows XP, you need disable poll
*/
// #define YASIO_DISABLE_POLL 1

/*
** Workaround for 'vs2013 without full c++11 support', in the future, drop vs2013 support and
** follow 3 lines code will be removed
Expand Down Expand Up @@ -192,7 +198,7 @@ SOFTWARE.
/*
** The yasio version macros
*/
#define YASIO_VERSION_NUM 0x033905
#define YASIO_VERSION_NUM 0x033906

/*
** The macros used by io_service.
Expand Down
32 changes: 32 additions & 0 deletions yasio/detail/fd_set_adapter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//////////////////////////////////////////////////////////////////////////////////////////
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
//
// detail/fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)

#pragma once

#include "yasio/detail/config.hpp"

#if !defined(YASIO_DISABLE_POLL)
# include "yasio/detail/poll_fd_set.hpp"
#else
# include "yasio/detail/select_fd_set.hpp"
#endif

namespace yasio
{
YASIO__NS_INLINE
namespace inet
{
#if !defined(YASIO_DISABLE_POLL)
using fd_set_adapter = poll_fd_set;
#else
using fd_set_adapter = select_fd_set;
#endif
} // namespace inet
} // namespace yasio
96 changes: 96 additions & 0 deletions yasio/detail/poll_fd_set.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//////////////////////////////////////////////////////////////////////////////////////////
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
//
// detail/poll_fd_set.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)
#pragma once
#include <vector>
#include "yasio/detail/socket.hpp"

namespace yasio
{
YASIO__NS_INLINE
namespace inet
{
class poll_fd_set {
public:
poll_fd_set& operator=(poll_fd_set& rhs)
{
this->fd_set_ = rhs.fd_set_;
return *this;
}

void reset() { this->fd_set_.clear(); }

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); }

int is_set(socket_native_type fd, int events) const
{
int underlying_events = 0;
if (events & socket_event::read)
underlying_events |= POLLIN;
if (events & socket_event::write)
underlying_events |= POLLOUT;
if (events & socket_event::error)
underlying_events |= (POLLERR | POLLHUP | POLLNVAL);
auto it = std::find_if(this->fd_set_.begin(), this->fd_set_.end(), [fd](const pollfd& pfd) { return pfd.fd == fd; });
return it != this->fd_set_.end() ? (it->revents & underlying_events) : 0;
}

void set(socket_native_type fd, int events)
{
int underlying_events = 0;
if (yasio__testbits(events, socket_event::read))
underlying_events |= POLLIN;

if (yasio__testbits(events, socket_event::write))
underlying_events |= POLLOUT;

if (yasio__testbits(events, socket_event::error))
underlying_events |= POLLERR;
pollfd_mod(this->fd_set_, fd, underlying_events, 0);
}

void unset(socket_native_type fd, int events)
{
int underlying_events = 0;
if (yasio__testbits(events, socket_event::read))
underlying_events |= POLLIN;

if (yasio__testbits(events, socket_event::write))
underlying_events |= POLLOUT;

if (yasio__testbits(events, socket_event::error))
underlying_events |= POLLERR;

pollfd_mod(this->fd_set_, fd, 0, underlying_events);
}

protected:
static void pollfd_mod(std::vector<pollfd>& fdset, socket_native_type fd, int add_events, int remove_events)
{
auto it = std::find_if(fdset.begin(), fdset.end(), [fd](const pollfd& pfd) { return pfd.fd == fd; });
if (it != fdset.end())
{
it->events |= add_events;
it->events &= ~remove_events;
if (it->events == 0)
fdset.erase(it);
}
else
{
auto events = add_events & ~remove_events;
if (events)
fdset.push_back(pollfd{fd, static_cast<short>(events), 0});
}
}

protected:
std::vector<pollfd> fd_set_;
};
} // namespace inet
} // namespace yasio
95 changes: 95 additions & 0 deletions yasio/detail/select_fd_set.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//////////////////////////////////////////////////////////////////////////////////////////
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
//
// detail/select_fd_set.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2012-2022 HALX99 (halx99 at live dot com)
#pragma once

#include <vector>
#include "yasio/detail/socket.hpp"

namespace yasio
{
YASIO__NS_INLINE
namespace inet
{
class select_fd_set {
public:
select_fd_set() { reset(); }

void reset()
{
FD_ZERO(&fd_set_[read_op]);
FD_ZERO(&fd_set_[write_op]);
FD_ZERO(&fd_set_[except_op]);
max_nfds_ = 0;
}

select_fd_set& operator=(select_fd_set& rhs)
{
::memcpy(this->fd_set_, rhs.fd_set_, sizeof(rhs.fd_set_));
max_nfds_ = rhs.max_nfds_;
return *this;
}

int poll_io(timeval& waitd_tv)
{
return ::select(this->max_nfds_, &(fd_set_[read_op]), &(fd_set_[write_op]), nullptr, &waitd_tv);
}

int is_set(socket_native_type fd, int events) const
{
int retval = 0;
if (events & socket_event::read)
retval |= FD_ISSET(fd, &fd_set_[read_op]);
if (events & socket_event::write)
retval |= FD_ISSET(fd, &fd_set_[write_op]);
if (events & socket_event::error)
retval |= FD_ISSET(fd, &fd_set_[except_op]);
return retval;
}

void set(socket_native_type fd, int events)
{
if (yasio__testbits(events, socket_event::read))
FD_SET(fd, &(fd_set_[read_op]));

if (yasio__testbits(events, socket_event::write))
FD_SET(fd, &(fd_set_[write_op]));

if (yasio__testbits(events, socket_event::error))
FD_SET(fd, &(fd_set_[except_op]));

if (max_nfds_ < static_cast<int>(fd) + 1)
max_nfds_ = static_cast<int>(fd) + 1;
}

void unset(socket_native_type fd, int events)
{
if (yasio__testbits(events, socket_event::read))
FD_CLR(fd, &(fd_set_[read_op]));

if (yasio__testbits(events, socket_event::write))
FD_CLR(fd, &(fd_set_[write_op]));

if (yasio__testbits(events, socket_event::error))
FD_CLR(fd, &(fd_set_[except_op]));
}

protected:
enum
{
read_op,
write_op,
except_op,
max_ops,
};
fd_set fd_set_[max_ops];
int max_nfds_ = 0;
};
} // namespace inet
} // namespace yasio
21 changes: 21 additions & 0 deletions yasio/detail/socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,25 @@ inline bool IN6_IS_ADDR_GLOBAL(const in6_addr* a)

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

#define yasio__setbits(x, m) ((x) |= (m))
#define yasio__clearbits(x, m) ((x) &= ~(m))
#define yasio__testbits(x, m) ((x) & (m))
#define yasio__setlobyte(x, v) ((x) = ((x) & ~((decltype(x))0xff)) | (v))

namespace yasio
{
YASIO__NS_INLINE
namespace inet
{
struct socket_event {
enum
{ // event mask
read = 1,
write = 2,
error = 4,
readwrite = read | write,
};
};
}
} // namespace yasio
#endif
Loading