mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-23 15:10:34 +00:00
Separate the two responsibilities the old SpanGuard fused: span ownership (thread-free) and scope activation (thread-bound TLS push). - SpanGuard now owns ONLY the span. Its Impl drops the optional<Scope>, the owner thread-id, the Detached tag and the scope-less ctor; ~Impl is just `if (span) span->End()`. The guard never binds a thread-local context stack, so it may be moved to and destroyed on any thread. - ScopedSpanGuard is a new pimpl type that wraps a SpanGuard plus an optional<Scope>. Member order (guard first, scope second) pops the scope before the span ends. It is non-copyable and non-movable; factories return unnamed temporaries so guaranteed copy elision covers `auto s = ScopedSpanGuard::freshRoot(...)`. - `operator SpanGuard() &&` replaces detached()/detachInPlace(): it pops the scope eagerly on the origin thread and yields a thread-free SpanGuard for handoff to a job or another thread. detached(), detachInPlace() (both overloads) and the Detached apparatus are deleted. - Move-assignment is re-enabled on SpanGuard (no Scope to re-bind), in both the real class and the no-op stub. - rootSpan() renamed to freshRoot() in both classes (behavior unchanged: still forces kIsRootSpanKey). - hashSpan behavior is intentionally unchanged (only builds the now unscoped Impl); the true-root IdGenerator fix is a separate later task. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>