4#include "Stroika/Foundation/StroikaPreComp.h"
6#if qStroika_Foundation_Common_Platform_POSIX
9#elif qStroika_Foundation_Common_Platform_Windows
17#include "Stroika/Foundation/Containers/Sequence.h"
22#include "Exceptions.h"
23#if qStroika_Foundation_Common_Platform_Windows
24#include "Platform/Windows/Exception.h"
25#include "Platform/Windows/WaitSupport.h"
28#include "Stroika/Foundation/IO/Network/ConnectionOrientedMasterSocket.h"
29#include "Stroika/Foundation/IO/Network/ConnectionOrientedStreamSocket.h"
55 struct EventFD_Based_ :
public EventFD {
57 EventFD_Based_ () =
default;
58 virtual bool IsSet ()
const override
62 virtual void Set ()
override
70 virtual void Clear ()
override
79 virtual void _ReadAllAvail () = 0;
80 virtual void _WriteOne () = 0;
83 atomic<bool> fIsSet_{
false};
91 struct EventFD_Based_SocketPair_ : EventFD_Based_ {
92 static const inline BLOB sSingleEltDatum{
BLOB ({1})};
94 EventFD_Based_SocketPair_ ()
97 auto [r, w] = ConnectionOrientedStreamSocket::NewPair (SocketAddress::FamilyType::INET, Socket::Type::STREAM);
104 virtual pair<SDKPollableType, WaitForIOReady_Base::TypeOfMonitorSet> GetWaitInfo ()
override
107 return pair<SDKPollableType, WaitForIOReady_Base::TypeOfMonitorSet>{
110 virtual void _ReadAllAvail ()
override
114 while (fReadSocket_.ReadNonBlocking (buf))
117 virtual void _WriteOne ()
override
120 fWriteSocket_.Write (sSingleEltDatum);
137 return make_unique<EventFD_Based_SocketPair_> ();
145auto WaitForIOReady_Base::_WaitQuietlyUntil (
const pair<SDKPollableType, TypeOfMonitorSet>* start,
148#if USE_NOISY_TRACE_IN_THIS_MODULE_
149 Debug::TraceContextBumper ctx{
"WaitForIOReady_Base::_WaitQuietlyUntil",
"args={}"_f, vector<pair<SDKPollableType, TypeOfMonitorSet>>{start, end}};
151 DurationSeconds time2Wait = Math::AtLeast<DurationSeconds> (timeoutAt - Time::GetTickCount (), 0s);
153 StackBuffer<pollfd> pollData;
155 pollData.GrowToSize_uninitialized (end - start);
157 for (
auto i = start; i != end; ++i) {
159 for (TypeOfMonitor ii : i->second) {
161 case TypeOfMonitor::eRead:
164 case TypeOfMonitor::eWrite:
167 case TypeOfMonitor::ePriority:
172 pollData[idx] = pollfd{i->first, events, 0};
173 Assert (pollData[idx].revents == 0);
180 [[maybe_unused]]
int timeoutMilliseconds = Math::Round<int> (time2Wait.count () * 1000);
181 Assert (timeoutMilliseconds >= 0);
183#if qStroika_Foundation_Common_Platform_Windows
184#if qStroika_Foundation_Execution_WaitForIOReady_BreakWSAPollIntoTimedMillisecondChunks > 0
187 DurationSeconds timeLeft2Wait = Math::AtLeast<DurationSeconds> (timeoutAt - Time::GetTickCount (), 0s);
189 timeLeft2Wait, 0s, DurationSeconds{qStroika_Foundation_Execution_WaitForIOReady_BreakWSAPollIntoTimedMillisecondChunks / 1000.0});
190 int time2WaitMillisecondsThisLoop =
static_cast<int> (time2WaitThisLoop.count () * 1000);
191 if ((pollResult = ::WSAPoll (pollData.begin (),
static_cast<ULONG
> (pollData.GetSize ()), time2WaitMillisecondsThisLoop)) == SOCKET_ERROR) {
192 ThrowSystemErrNo (::WSAGetLastError ());
194 if (pollResult != 0 or Time::GetTickCount () >= timeoutAt) {
199 if ((pollResult = ::WSAPoll (pollData.begin (),
static_cast<ULONG
> (pollData.GetSize ()), timeoutMilliseconds)) == SOCKET_ERROR) {
200 Platform::Windows::Exception::Throw (::WSAGetLastError ());
207#if USE_NOISY_TRACE_IN_THIS_MODULE_
210 if (pollResult != 0) {
211 for (
size_t i = 0; i < pollData.GetSize (); ++i) {
212 if (pollData[i].revents != 0) {
213#if USE_NOISY_TRACE_IN_THIS_MODULE_
214 dbgResult += start[i].first;
220#if USE_NOISY_TRACE_IN_THIS_MODULE_
221 DbgTrace (
"returning {}"_f, dbgResult);
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(...)
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
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...