network, sockets: Replace POLL_IN, POLL_OUT, etc. constants with an enum class PollEvents

Actually, two enum classes, since for some reason there are two separate
yet identical `PollFD` types used in the codebase.  I get that one is
ABI-compatible with the Switch while the other is an abstract type used
for the host, but why not use `WSAPOLLFD` directly for the latter?

Anyway, why make this change?  Because on Apple platforms, `POLL_IN`,
`POLL_OUT`, etc. (with an underscore) are defined as macros in
<sys/signal.h>.  (This is inherited from FreeBSD.)  So defining
a variable with the same name causes a compile error.

I could just rename the variables, but while I was at it I thought I
might as well switch to an enum for stronger typing.

Also, change the type used for values copied directly to/from the
`events` and `revents` fields of the host *native*
`pollfd`/`WSASPOLLFD`, from `u32` to `short`, as `short` is the correct
canonical type on both Unix and Windows.
This commit is contained in:
comex 2020-08-31 10:20:44 -04:00
parent 5933667cb8
commit 0791082b43
6 changed files with 82 additions and 71 deletions

View file

@ -238,49 +238,49 @@ SockAddrIn TranslateToSockAddrIn(sockaddr input_) {
return result;
}
u16 TranslatePollEvents(u32 events) {
u32 result = 0;
short TranslatePollEvents(PollEvents events) {
short result = 0;
if ((events & POLL_IN) != 0) {
events &= ~POLL_IN;
if (True(events & PollEvents::In)) {
events &= ~PollEvents::In;
result |= POLLIN;
}
if ((events & POLL_PRI) != 0) {
events &= ~POLL_PRI;
if (True(events & PollEvents::Pri)) {
events &= ~PollEvents::Pri;
#ifdef _WIN32
LOG_WARNING(Service, "Winsock doesn't support POLLPRI");
#else
result |= POLL_PRI;
result |= POLLPRI;
#endif
}
if ((events & POLL_OUT) != 0) {
events &= ~POLL_OUT;
if (True(events & PollEvents::Out)) {
events &= ~PollEvents::Out;
result |= POLLOUT;
}
UNIMPLEMENTED_IF_MSG(events != 0, "Unhandled guest events=0x{:x}", events);
UNIMPLEMENTED_IF_MSG((u16)events != 0, "Unhandled guest events=0x{:x}", (u16)events);
return static_cast<u16>(result);
return result;
}
u16 TranslatePollRevents(u32 revents) {
u32 result = 0;
const auto translate = [&result, &revents](u32 host, u32 guest) {
PollEvents TranslatePollRevents(short revents) {
PollEvents result{};
const auto translate = [&result, &revents](short host, PollEvents guest) {
if ((revents & host) != 0) {
revents &= ~host;
revents &= static_cast<short>(~host);
result |= guest;
}
};
translate(POLLIN, POLL_IN);
translate(POLLPRI, POLL_PRI);
translate(POLLOUT, POLL_OUT);
translate(POLLERR, POLL_ERR);
translate(POLLHUP, POLL_HUP);
translate(POLLIN, PollEvents::In);
translate(POLLPRI, PollEvents::Pri);
translate(POLLOUT, PollEvents::Out);
translate(POLLERR, PollEvents::Err);
translate(POLLHUP, PollEvents::Hup);
UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
return static_cast<u16>(result);
return result;
}
template <typename T>
@ -350,7 +350,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
}
for (size_t i = 0; i < num; ++i) {
pollfds[i].revents = TranslatePollRevents(static_cast<u32>(host_pollfds[i].revents));
pollfds[i].revents = TranslatePollRevents(host_pollfds[i].revents);
}
if (result > 0) {

View file

@ -61,18 +61,24 @@ struct SockAddrIn {
};
/// Cross-platform poll fd structure
struct PollFD {
Socket* socket;
u16 events;
u16 revents;
enum class PollEvents : u16 {
// Using Pascal case because IN is a macro on Windows.
In = 1 << 0,
Pri = 1 << 1,
Out = 1 << 2,
Err = 1 << 3,
Hup = 1 << 4,
Nval = 1 << 5,
};
constexpr u16 POLL_IN = 1 << 0;
constexpr u16 POLL_PRI = 1 << 1;
constexpr u16 POLL_OUT = 1 << 2;
constexpr u16 POLL_ERR = 1 << 3;
constexpr u16 POLL_HUP = 1 << 4;
constexpr u16 POLL_NVAL = 1 << 5;
DECLARE_ENUM_FLAG_OPERATORS(PollEvents);
struct PollFD {
Socket* socket;
PollEvents events;
PollEvents revents;
};
class NetworkInstance {
public: