Loading src/quic.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -4600,6 +4600,20 @@ void quic::pumpNetwork(int flags) { } } void quic::pumpNetworkWait(int timeout_ms) { // Bounded, best-effort wait for the socket to become readable — never // holds quic_mtx() while waiting (socketwait operates on the raw fd), // so this can't stall anything else touching this connection // concurrently. A false/timeout return is not an error: it just means // pumpNetwork() below will find nothing new, same as if this wait were // skipped entirely. if (timeout_ms > 0) { socketwait sw; sw.waitRead(*this, timeout_ms); } pumpNetwork(MSG_DONTWAIT); } // ============================================================================ // Stream Data Receive (for specific stream) // ============================================================================ Loading src/socket.h +18 −0 Original line number Diff line number Diff line Loading @@ -887,6 +887,24 @@ namespace netplus { // while reading specific streams via recvStreamData(). void pumpNetwork(int flags = 0); // Like pumpNetwork(), but if nothing is immediately available, // blocks up to timeout_ms waiting for the socket to become readable // first — instead of the caller busy-spinning pumpNetwork() itself // purely to notice new data. Measured need: a tight // `while (...) pumpNetwork(MSG_DONTWAIT);` client loop (e.g. // benchmark_quic.cpp's benchmark_transfer, or any HTTP/3 client // polling for a response) shows thousands of recvmmsg() calls per // second returning nothing whenever the connection is briefly idle // (see QUIC_PERF's recvmmsg=.../s counter for a call site that has // this problem). timeout_ms <= 0 skips the wait entirely — same as // calling pumpNetwork(MSG_DONTWAIT) directly. Still calls // pumpNetwork() exactly once every call, wait outcome or not, since // that also drives PMTU/PTO/keepalive timers unconditionally on a // bare (non-event-loop) connection — see pumpNetwork()'s own // comment on that. Purely additive: pumpNetwork() itself is // unchanged, so no existing caller's behavior changes. void pumpNetworkWait(int timeout_ms); // Connection ID management const std::vector<uint8_t>& getLocalConnectionId() const { return _local_cid; } const std::vector<uint8_t>& getRemoteConnectionId() const { return _remote_cid; } Loading Loading
src/quic.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -4600,6 +4600,20 @@ void quic::pumpNetwork(int flags) { } } void quic::pumpNetworkWait(int timeout_ms) { // Bounded, best-effort wait for the socket to become readable — never // holds quic_mtx() while waiting (socketwait operates on the raw fd), // so this can't stall anything else touching this connection // concurrently. A false/timeout return is not an error: it just means // pumpNetwork() below will find nothing new, same as if this wait were // skipped entirely. if (timeout_ms > 0) { socketwait sw; sw.waitRead(*this, timeout_ms); } pumpNetwork(MSG_DONTWAIT); } // ============================================================================ // Stream Data Receive (for specific stream) // ============================================================================ Loading
src/socket.h +18 −0 Original line number Diff line number Diff line Loading @@ -887,6 +887,24 @@ namespace netplus { // while reading specific streams via recvStreamData(). void pumpNetwork(int flags = 0); // Like pumpNetwork(), but if nothing is immediately available, // blocks up to timeout_ms waiting for the socket to become readable // first — instead of the caller busy-spinning pumpNetwork() itself // purely to notice new data. Measured need: a tight // `while (...) pumpNetwork(MSG_DONTWAIT);` client loop (e.g. // benchmark_quic.cpp's benchmark_transfer, or any HTTP/3 client // polling for a response) shows thousands of recvmmsg() calls per // second returning nothing whenever the connection is briefly idle // (see QUIC_PERF's recvmmsg=.../s counter for a call site that has // this problem). timeout_ms <= 0 skips the wait entirely — same as // calling pumpNetwork(MSG_DONTWAIT) directly. Still calls // pumpNetwork() exactly once every call, wait outcome or not, since // that also drives PMTU/PTO/keepalive timers unconditionally on a // bare (non-event-loop) connection — see pumpNetwork()'s own // comment on that. Purely additive: pumpNetwork() itself is // unchanged, so no existing caller's behavior changes. void pumpNetworkWait(int timeout_ms); // Connection ID management const std::vector<uint8_t>& getLocalConnectionId() const { return _local_cid; } const std::vector<uint8_t>& getRemoteConnectionId() const { return _remote_cid; } Loading