- Suppress cppcoreguidelines-avoid-capturing-lambda-coroutines with
NOLINT where lifetime is guaranteed: GRPCServer (thisShared keeps
CallData alive), ServerHandler RPC/WS clients (captures by value,
handler outlives JobQueue jobs), and PathMPT_test (test blocks on
Gate::waitFor until the coroutine completes).
- Change ServerHandler::processRequest to take Output const& to fix
cppcoreguidelines-rvalue-reference-param-not-moved.
- Replace std::lock_guard with std::scoped_lock in RipplePathFind.
- Remove redundant includes and default member initializer in
Context.h, GRPCServer.h, RipplePathFind.cpp.
- NOLINT the compiler-mandated coroutine protocol names (promise_type,
await_ready, ...) that conflict with readability-identifier-naming and
readability-convert-member-functions-to-static
- Add [[nodiscard]] to handle(), done(), await_ready()
- Replace std::lock_guard with std::scoped_lock const
- Pass CoroTaskRunner name by value and std::move it; default-init
runCount_ in-class
- Drop unused <coroutine> include from JobQueue.h; include
instrumentation.h directly in JobQueueAwaiter.h
- CoroTask_test: kN constant naming, const locals, file-level NOLINT for
cppcoreguidelines-avoid-capturing-lambda-coroutines (lifetimes are
gated and joined)
- Replace the magic 30s in doRipplePathFind with
RPC::Tuning::kPathfindCompletionTimeout.
- In PathRequestManager::updateAll, invoke updateComplete() via a
ScopeExit guard on the one-shot (hasCompletion) path so the blocked
RPC handler is released immediately even if doUpdate throws, instead
of waiting out the full timeout.
The no-ledger branch of doRipplePathFind parks its JobQueue worker on a
condition_variable for up to 30s, waiting for a completion that is fired
from a JtUpdatePf job -- which itself needs a free worker to run. With
unbounded JtClientRpc concurrency, enough simultaneous ripple_path_find
calls could park every worker, stalling the entire JobQueue until the
30s timeouts expired. The old Boost.Coroutine implementation suspended
and released the worker, so it did not have this failure mode.
Reuse the RPC::LegacyPathFind guard (already applied on the
ledger-specified branch) to admit at most kMaxPathfindsInProgress
non-admin blocking requests, returning rpcTOO_BUSY beyond that. The
guard stays in scope across the wait.
- testExceptionPropagation now co_awaits an inner CoroTask<void> that
throws and asserts the rethrown message, covering the
CoroTask<void>::await_resume rethrow path; the old version could not
distinguish a throw from a normal return.
- testJobQueueAwaiter now actually awaits the JobQueueAwaiter struct
(single use per coroutine, per the GCC-12 note) and asserts the full
ordered step sequence instead of only the terminal value.
- testValueException asserts the caught exception's message.
- All waitFor() timeouts early-return on failure instead of falling
through to join()/state reads (null-deref and TSAN-race hazards on
timeout, plus the nSuspend_ assert in ~Env).
- Remove dead shared_ptr locals in testCorrectOrder/testMultipleYields.
- Add missing includes (<array>, <stdexcept>, <string>, <vector>,
LocalValue.h, CoroTask.h).
- resume() now skips the handle resume when the task is null or done
(duplicate external post() after completion), matching the old
Coro::resume() 'if (coro_)' guard instead of invoking UB in release
builds. The runCount_ bookkeeping still runs to balance post().
- Exceptions escaping a top-level coroutine body were captured by
unhandled_exception() and destroyed unobserved with the frame; they
are now logged at error level before the frame is released.
- Document that join() may return via the finished_ disjunct while the
final resume() is still completing its bookkeeping.
- Remove BoostToStdCoroutineSwitchPlan.md and BoostToStdCoroutineTaskList.md
working documents from the repo root; the rename script rewrites their
'rippled' references and the job fails on the resulting dirty tree.
- Reword two CoroTask.h comments to use 'xrpld'.
- Drop cspell words (cppcoro, gantt, Pratik, Mankawde) that existed only
for the removed documents.
Forward-merge the updated coroutine primitives (which themselves carry the
latest develop) into the entry-point migration.
Conflict resolutions:
- .cspell.config.yaml: keep develop's dotfile name, merge word lists.
- Context.h: drop the coro member; infoSub gets a default initializer.
- Application.cpp, ServerHandler.cpp, TestHelpers.cpp, Path_test.cpp,
PathMPT_test.cpp: adopt develop's designated-initializer JsonContext and
renamed identifiers (JtClient, kApiVersionIfUnspecified, kMaxSrcCur, Gate).
- GRPCServer: process(coro) becomes processRequest(), posted with
postCoroTask.
- RipplePathFind.cpp: follow develop's move to handlers/orderbook/ and
PathRequestManager; the completion state shared with the path-finding
continuation is now heap-allocated so it outlives an early return.
- AMMTest.cpp: develop moved find_paths_request into TestHelpers.cpp, so the
local copy is dropped and the migration applied there instead.
Resolves the develop rename of cspell.config.yaml and the JobQueue.h
conflicts, and aligns the new coroutine primitives with develop naming
(CreateT, mutex_/mutexRun_, JtClient, forceMultiThread,
beast::unit_test::Suite).
Also addresses two review findings:
- postCoroTask now holds a jobCounter_ reservation for the whole
function. JobQueue::stop() joins jobCounter_ before asserting
nSuspend_ == 0, so the reservation closes the window between the
++nSuspend_ and the balancing post()/expectEarlyExit(), and doubles
as the shutdown check.
- YieldPostAwaiter::await_suspend returns a coroutine_handle<>
(symmetric transfer) instead of resuming inline. This keeps a
yield loop against a stopping JobQueue from growing the stack
without bound and avoids touching a frame that resume() may have
already destroyed.