1/*
2 * IXSelectInterruptEvent.cpp
3 */
4
5//
6// On Windows we use a Windows Event to wake up ix::poll() (WSAWaitForMultipleEvents).
7// And on any other platform that doesn't support pipe file descriptors we
8// emulate the interrupt event by using a short timeout with ix::poll() and
9// read from the SelectInterrupt. (see Socket::poll() "Emulation mode")
10//
11#include <algorithm>
12#include "IXSelectInterruptEvent.h"
13
14namespace ix
15{
16 SelectInterruptEvent::SelectInterruptEvent()
17 {
18#ifdef _WIN32
19 _event = CreateEvent(NULL, TRUE, FALSE, NULL);
20#endif
21 }
22
23 SelectInterruptEvent::~SelectInterruptEvent()
24 {
25#ifdef _WIN32
26 CloseHandle(_event);
27#endif
28 }
29
30 bool SelectInterruptEvent::init(std::string& /*errorMsg*/)
31 {
32 return true;
33 }
34
35 bool SelectInterruptEvent::notify(uint64_t value)
36 {
37 std::lock_guard<std::mutex> lock(_valuesMutex);
38
39 // WebSocket implementation detail: We only need one of the values in the queue
40 if (std::find(_values.begin(), _values.end(), value) == _values.end())
41 _values.push_back(value);
42#ifdef _WIN32
43 SetEvent(_event); // wake up
44#endif
45 return true;
46 }
47
48 uint64_t SelectInterruptEvent::read()
49 {
50 std::lock_guard<std::mutex> lock(_valuesMutex);
51
52 if (_values.size() > 0)
53 {
54 uint64_t value = _values.front();
55 _values.pop_front();
56#ifdef _WIN32
57 // signal the event if there is still data in the queue
58 if (_values.size() == 0)
59 ResetEvent(_event);
60#endif
61 return value;
62 }
63 return 0;
64 }
65
66 bool SelectInterruptEvent::clear()
67 {
68 std::lock_guard<std::mutex> lock(_valuesMutex);
69 _values.clear();
70#ifdef _WIN32
71 ResetEvent(_event);
72#endif
73 return true;
74 }
75
76 void* SelectInterruptEvent::getEvent() const
77 {
78#ifdef _WIN32
79 return reinterpret_cast<void*>(_event);
80#else
81 return nullptr;
82#endif
83 }
84
85} // namespace ix
86