1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
#include "poller.hpp"
#include "../libfilezilla/mutex.hpp"
namespace fz {
poller::~poller()
{
if (sync_event_ != WSA_INVALID_EVENT) {
WSACloseEvent(sync_event_);
}
}
// zero on success, else errno
int poller::init()
{
if (sync_event_ == WSA_INVALID_EVENT) {
sync_event_ = WSACreateEvent();
}
if (sync_event_ == WSA_INVALID_EVENT) {
return 1;
}
return 0;
}
bool poller::wait(scoped_lock & l)
{
if (!signalled_) {
idle_wait_ = true;
cond_.wait(l);
idle_wait_ = false;
}
signalled_ = false;
return true;
}
// fds must be large enough to hold n+1 entries, but fds[n] must not be filled by caller
bool poller::wait(pollinfo* fds, size_t n, scoped_lock& l)
{
for (size_t i = 0; i < n; ++i) {
WSAEventSelect(fds[i].fd_, sync_event_, fds[i].events_);
}
l.unlock();
DWORD res = WSAWaitForMultipleEvents(1, &sync_event_, false, INFINITE, false);
l.lock();
signalled_ = false;
if (res == WSA_WAIT_FAILED) {
for (size_t i = 0; i < n; ++i) {
WSAEventSelect(fds[i].fd_, sync_event_, 0);
}
return false;
}
bool failure{};
for (size_t i = 0; i < n; ++i) {
if (WSAEnumNetworkEvents(fds[i].fd_, sync_event_, &fds[i].result_)) {
failure = true;
}
WSAEventSelect(fds[i].fd_, sync_event_, 0);
}
if (failure) {
return false;
}
return true;
}
void poller::interrupt(scoped_lock& l)
{
signalled_ = true;
if (idle_wait_) {
cond_.signal(l);
}
else {
WSASetEvent(sync_event_);
}
}
}
|