Repository navigation
Completion tokens: complete through the caller's immediate executor, and tests - #41
Merged
Merged
Conversation
The Coverage job configured its tree by hand; it now uses the build-coverage preset, which reproduces the report locally. docs/snippets.cpp is linked into test_all to be run, not to be measured, so docs/ joins test/ among the paths the report leaves out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No backend that hands out a Session leaves the default in place, so a session with nothing behind it stands in for one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
complete_immediately() handed asio::async_immediate() a lambda around the handler, and async_immediate() asks what it is given for its immediate executor: the lambda has none, so an immediate executor the caller bound was never fetched and every completion was posted. It now executes on the handler's own, falling back to a post as before, so the caller decides whether it is completed inline. So does the default async_shutdown_impl() of any_async_stream. The second half of the Recursion test had passed regardless, through the extra frames of the binder's path; it now reads twice and requires the second read to nest deeper (HTTP/2 and HTTP/3 only, HTTP/1.1 reads in a task of its own and never completes immediately). Each operation completes the same way on all of its paths. The client's submit and get_response called their handler inline when they failed, and post it now, as they do when they succeed. A server's Response::async_submit() over HTTP/2 and HTTP/3 completes inline on all paths: the responses of requests that arrived together go out in one send only if their handlers have all written before the write pass runs, and queueing the completion, ahead of the pass or behind it, cost 16-41% of throughput. docs/benchmark.md has the measurements. complete_later() is complete() now, being the default way to complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_asio.cpp runs async_submit(), async_shutdown() and the rest with as_tuple, cancel_after, the default token and plain callbacks, over all three protocols, and cancel_after on a shutdown that waits for a peer that never answers. test_quic.cpp adds cancel_after on async_accept_stream(). An empty handle has no executor, so a callback completes inside the call and cancel_after cannot start its timer: documented on Reader::get_executor(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since the namespaces are named after their directories, a bare asio:: in a test is anyhttp's inline runtime namespace, and test_asio.cpp and test_quic.cpp no longer compiled after the rebase onto master. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WHEN_write_is_stuck_THEN_shutdown_interrupts_it_and_says_so/HTTP2 failed about one run in four under gtest-parallel -w 100. It called shutdown() 50ms in, taking the write to be stuck by then, but a peer that stops reading keeps a small window open for some 200ms on loopback, and a client that got little CPU had not filled the pipe yet: its DATA frame completed, the GOAWAY fit in after it, and the session ended cleanly -- correctly reported as success. The peer now waits for its advertised receive window to be 0 on two samples 10ms apart before it lets the client shut down: that window stays closed, and the client has filled its send buffer behind it. A receive queue that has stopped growing is no proof of that, it stands still for tens of milliseconds at a time. tcpi_rcv_wnd is read in tcp_info.cpp, as <linux/tcp.h> clashes with the <netinet/tcp.h> Asio includes, and glibc's struct tcp_info ends before that field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Completion-token API (ASIO): completions honour the caller's immediate executor, and the token layer gets tests of its own.
complete_immediately()wrapped the handler in a lambda, soasync_immediate()never saw an immediate executor the caller had bound, and every completion was posted. It now runs on the handler's own immediate executor, and posts only when there is none. Error paths now complete the same way as success paths: the client's submit and get_response used to call their handler inline when they failed and now post it, as they do when they succeed. A server'sResponse::async_submit()over HTTP/2 and HTTP/3 stays inline on all paths: queueing that completion cost 16–41% of throughput (measurements indocs/benchmark.md).complete_later()is nowcomplete().Recursionnow requires the second read to nest deeper.test_asio.cpprunsasync_submit(),async_shutdown()and the rest withas_tuple,cancel_after, the default token and plain callbacks, over all three protocols.test_quic.cppaddscancel_afteronasync_accept_stream(). An empty handle has no executor, which is now documented onReader::get_executor().Session::Impl's defaultshutdown()reportsoperation_not_supported.build-coveragepreset for the published report. The Coverage job now uses it, anddocs/is left out of the report.asio::is now anyhttp's runtime namespace. It can be squashed into the completion-token commit.ClientTlsEnd…WHEN_write_is_stuck_THEN_shutdown_interrupts_it_and_says_so/HTTP2failed about 1 run in 4 undergtest-parallel -w 100. It assumed the write was stuck 50 ms in, but a peer that stops reading keeps a small window open for about 200 ms on loopback. The peer now waits until its advertised receive window (tcpi_rcv_wnd, read in the newtest/tcp_info.cpp) is 0 on two samples in a row. Result: 600/600 runs pass on ASIO with-w 200, and 200/200 on COROSIO.Tested: the full suite under
gtest-parallelinbuild/(ASIO) andbuild-corosio/, andbuild-gcccompilestest_all.🤖 Generated with Claude Code