4#include "Stroika/Foundation/StroikaPreComp.h"
6#if qStroika_Foundation_Common_Platform_POSIX
9#elif qStroika_Foundation_Common_Platform_Windows
21#include "Exceptions.h"
22#if qStroika_Foundation_Common_Platform_Windows
23#include "Platform/Windows/Exception.h"
24#include "Platform/Windows/WaitSupport.h"
27#include "Stroika/Foundation/IO/Network/ConnectionOrientedMasterSocket.h"
28#include "Stroika/Foundation/IO/Network/ConnectionOrientedStreamSocket.h"
50 struct EventFD_Based_ :
public EventFD {
52 EventFD_Based_ () =
default;
53 virtual bool IsSet ()
const override
57 virtual void Set ()
override
65 virtual void Clear ()
override
74 virtual void _ReadAllAvail () = 0;
75 virtual void _WriteOne () = 0;
78 atomic<bool> fIsSet_{
false};
86 struct EventFD_Based_SocketPair_ : EventFD_Based_ {
87 static const inline BLOB sSingleEltDatum{
BLOB ({1})};
89 EventFD_Based_SocketPair_ ()
92 auto [r, w] = ConnectionOrientedStreamSocket::NewPair (SocketAddress::FamilyType::INET, Socket::Type::STREAM);
99 virtual pair<SDKPollableType, WaitForIOReady_Base::TypeOfMonitorSet> GetWaitInfo ()
override
102 return pair<SDKPollableType, WaitForIOReady_Base::TypeOfMonitorSet>{
105 virtual void _ReadAllAvail ()
override
109 while (fReadSocket_.ReadNonBlocking (buf))
112 virtual void _WriteOne ()
override
115 fWriteSocket_.Write (sSingleEltDatum);
132 return make_unique<EventFD_Based_SocketPair_> ();
140auto WaitForIOReady_Base::_WaitQuietlyUntil (
const pair<SDKPollableType, TypeOfMonitorSet>* start,
143 DurationSeconds time2Wait = Math::AtLeast<DurationSeconds> (timeoutAt - Time::GetTickCount (), 0s);
145 StackBuffer<pollfd> pollData;
147 pollData.GrowToSize_uninitialized (end - start);
149 for (
auto i = start; i != end; ++i) {
151 for (TypeOfMonitor ii : i->second) {
153 case TypeOfMonitor::eRead:
156 case TypeOfMonitor::eWrite:
159 case TypeOfMonitor::eError:
162 case TypeOfMonitor::eHUP:
167 pollData[idx] = pollfd{i->first, events, 0};
168 Assert (pollData[idx].revents == 0);
175 [[maybe_unused]]
int timeoutMilliseconds = Math::Round<int> (time2Wait.count () * 1000);
176 Assert (timeoutMilliseconds >= 0);
178#if qStroika_Foundation_Common_Platform_Windows
179#if qStroika_Foundation_Execution_WaitForIOReady_BreakWSAPollIntoTimedMillisecondChunks > 0
182 DurationSeconds timeLeft2Wait = Math::AtLeast<DurationSeconds> (timeoutAt - Time::GetTickCount (), 0s);
184 timeLeft2Wait, 0s, DurationSeconds{qStroika_Foundation_Execution_WaitForIOReady_BreakWSAPollIntoTimedMillisecondChunks / 1000.0});
185 int time2WaitMillisecondsThisLoop =
static_cast<int> (time2WaitThisLoop.count () * 1000);
186 if ((pollResult = ::WSAPoll (pollData.begin (),
static_cast<ULONG
> (pollData.GetSize ()), time2WaitMillisecondsThisLoop)) == SOCKET_ERROR) {
187 ThrowSystemErrNo (::WSAGetLastError ());
189 if (pollResult != 0 or Time::GetTickCount () >= timeoutAt) {
194 if ((pollResult = ::WSAPoll (pollData.begin (),
static_cast<ULONG
> (pollData.GetSize ()), timeoutMilliseconds)) == SOCKET_ERROR) {
195 Platform::Windows::Exception::Throw (::WSAGetLastError ());
202 if (pollResult != 0) {
203 for (
size_t i = 0; i < pollData.GetSize (); ++i) {
204 if (pollData[i].revents != 0) {
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
#define Stroika_Foundation_Debug_OptionalizeTraceArgs(...)
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
nonvirtual PlatformNativeHandle GetNativeSocket() const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
void CheckForInterruption()
unique_ptr< EventFD > mkEventFD()
auto Handle_ErrNoResultInterruption(CALL call) -> decltype(call())
Handle UNIX EINTR system call behavior - fairly transparently - just effectively removes them from th...