Win wsa select event (#342)
* Fix #323: Missing SelectInterrupt implementation for Windows Using WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents to emulate poll() with an interrupt-event. * Cleanup * Fixed incomplete comment. * Switched ifdefs to support other Unixes with pipe file descriptors * Fixed: SelectInterrupt fallback code for getFd()==-1 && getEvent()==nullptr converted a PollResultType::Timeout into a ReadyForRead causing the HttpClient to fail because it uses a hard-coded "SelectInterrupt" instance that doesn't implement getFd() and getEvent(). * Fixed gcc compile errors * - HttpClient now uses the SelectInterruptFactory - Fixed wrong ix::poll result when using Windows WSA functions * We must deselect the networkevents from the socket event. Otherwise the socket will report states that aren't there.
This commit is contained in:
committed by
GitHub
parent
9f00428d57
commit
1f2895a469
84
ixwebsocket/IXSelectInterruptEvent.cpp
Normal file
84
ixwebsocket/IXSelectInterruptEvent.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* IXSelectInterruptEvent.cpp
|
||||
*/
|
||||
|
||||
//
|
||||
// On Windows we use a Windows Event to wake up ix::poll() (WSAWaitForMultipleEvents).
|
||||
// And on any other platform that doesn't support pipe file descriptors we
|
||||
// emulate the interrupt event by using a short timeout with ix::poll() and
|
||||
// read from the SelectInterrupt. (see Socket::poll() "Emulation mode")
|
||||
//
|
||||
#include "IXSelectInterruptEvent.h"
|
||||
|
||||
namespace ix
|
||||
{
|
||||
SelectInterruptEvent::SelectInterruptEvent()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
SelectInterruptEvent::~SelectInterruptEvent()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(_event);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SelectInterruptEvent::init(std::string& /*errorMsg*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SelectInterruptEvent::notify(uint64_t value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_valuesMutex);
|
||||
|
||||
// WebSocket implementation detail: We only need one of the values in the queue
|
||||
if (std::find(_values.begin(), _values.end(), value) == _values.end())
|
||||
_values.push_back(value);
|
||||
#ifdef _WIN32
|
||||
SetEvent(_event); // wake up
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t SelectInterruptEvent::read()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_valuesMutex);
|
||||
|
||||
if (_values.size() > 0)
|
||||
{
|
||||
uint64_t value = _values.front();
|
||||
_values.pop_front();
|
||||
#ifdef _WIN32
|
||||
// signal the event if there is still data in the queue
|
||||
if (_values.size() == 0)
|
||||
ResetEvent(_event);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SelectInterruptEvent::clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_valuesMutex);
|
||||
_values.clear();
|
||||
#ifdef _WIN32
|
||||
ResetEvent(_event);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void* SelectInterruptEvent::getEvent() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return reinterpret_cast<void*>(_event);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace ix
|
Reference in New Issue
Block a user