# Arno - P3832R4a & P3833R4a Timed lock algorithms for multiple lockables / `std::multi_lock` --- ## Verdict **With findings** - The papers have 8 findings that merit attention. The most important is that neither paper has a conclusion section, leaving the reader without a funnel-out or restatement of the ask. --- ## Strengths - **A4 (Self-Containment)**: Both papers are self-contained. A reader can follow the entire argument without leaving the document. Domain terms (*Cpp17TimedLockable*, *Cpp17Lockable*) are well-known to the target audience (SG1/LEWG), and the relationship between the two papers is stated explicitly. - **A5 (Term Consistency)**: Terminology is consistent throughout both papers. "Lockable," "deadlock avoidance," "timed locking," and "try_lock" are used uniformly. - **A15 (Code Context)**: Every code block has preceding prose establishing provenance and purpose. Examples are labeled, and the distinction between proposed and existing code is always clear. - **A12 (Audience Calibration)**: Both papers are well-calibrated for SG1/LEWG. The problem statement, design rationale, and wording are accessible to any C++ committee member with basic threading familiarity. - **Design tables and family completion**: P3833's table showing how `multi_lock` completes the mutex-wrapper family is an effective structural device that immediately communicates the contribution's position in the standard library. - **Wording quality**: The proposed wording in both papers is precise, follows standard conventions, and reads as production-ready normative text. --- ## Findings ### 1. Missing Conclusion / Funnel Out **Rule:** A2 **Severity:** high Neither paper contains a conclusion section. The reader reaches the end of the references without a restatement of the contribution, its significance to the standard, or the specific ask. A delegate who skips to the end of either paper learns nothing about what C++ gains if the proposal is accepted, what further work it enables, or what the authors are requesting from the committee. For ask-papers targeting LEWG/SG1, this is a significant structural gap. Addressing it: Add a brief conclusion to each paper that restates the contribution, names the ask (e.g., "advance to wording review" or "poll for inclusion in C++29"), and states downstream significance (P3833 depends on P3832; together they complete the timed-locking story). --- ### 2. Abstract Lacks Explicit Ask **Rule:** A1 (check 4) **Severity:** medium > P3832: "These extend the `std::lock` family of functions to timed lockables, enabling consistent and safe use of multiple timed mutexes." > P3833: "...while supporting multiple mutexes simultaneously." Both abstracts name the contribution but neither states the specific request from the committee. A delegate reading only the abstract does not know what action is being requested (advance to LEWG review? poll for C++29?). Addressing it: Add one sentence at the end of each abstract stating the ask, e.g., "This paper requests LEWG approve the proposed wording for inclusion in C++29." --- ### 3. P3832 Section 4 (Design Rationale) Opens Without Preparation **Rule:** A3 **Severity:** medium > "- **Free functions**: Consistent with `std::lock` and `std::try_lock`." Section 4 of P3832 opens directly with a bullet list of design points without any framing sentence explaining what the section covers or why these decisions matter to the overall argument. The reader encounters a list without knowing what question it answers. Addressing it: Add one or two sentences before the bullet list, e.g., "The following design decisions were guided by consistency with existing multi-lock algorithms and the constraints of the *Cpp17TimedLockable* requirements." --- ### 4. P3832 Section 3 (Impact on the Standard) Opens Without Preparation **Rule:** A3 **Severity:** medium > "- Pure library extension." Same issue as finding 3. The section jumps directly into a bullet list without framing. A short introductory sentence would orient the reader. --- ### 5. P3833 `try_lock_until` Effects Wording Underspecified for Multi-Mutex Case **Rule:** A7 (Structural Promises) **Severity:** medium > "Otherwise, uses an algorithm similar to `lock()` but with timed operations respecting `abs_time`." P3832 specifies its algorithm in detail (try_lock_until on one lockable, try_lock on the rest, unlock-and-retry). P3833's `try_lock_until` Effects for the multi-mutex case says "uses an algorithm similar to `lock()` but with timed operations" without stating whether it delegates to the free function `try_lock_until` from P3832 or specifies its own behavior. The word "similar" is a structural claim that leaves the actual semantics ambiguous. Addressing it: Either state "Equivalent to: `return try_lock_until(abs_time, *get(pm)...);`" (delegating to P3832), or reproduce the algorithm description. The current phrasing leaves implementers guessing. --- ### 6. P3833 Destructor Exception Semantics **Rule:** A7 (Structural Promises) **Severity:** medium > "The destructor provides the basic guarantee: if `owns_lock()` is `true`, it calls `unlock()`, which may throw but ensures all mutexes are unlocked before propagating the exception." The design discussion states the destructor "may throw." However, the normative wording for the destructor (paragraph 23) simply says "If `owns` is `true`, calls `unlock()`" without addressing exception behavior. Standard destructors are expected not to throw (or are implicitly `noexcept`). If this destructor can throw, it needs explicit normative language; if it cannot, the design discussion text is misleading. This is a structural inconsistency between the rationale and the wording. Addressing it: Either mark the destructor `noexcept` and wrap unlock in a try/catch (matching `unique_lock`'s behavior), or add normative text specifying the throwing behavior. Align the design discussion with whichever choice is made. --- ### 7. P3833 Move-Assignment Semantics **Rule:** A7 **Severity:** low > "Effects: Equivalent to: `multi_lock(std::move(u)).swap(*this)`." This formulation means that if `*this` currently owns locks, those locks are released by the temporary's destructor. This is correct but subtle - `unique_lock`'s move-assignment also unlocks the target. Worth noting: if the destructor can throw (per Finding 6), this move-assignment is not truly `noexcept` as declared. The two issues are coupled. --- ### 8. P3832 Vague "Minimal" Claim **Rule:** A17 (Weasel Quantifiers) / A9 (Value Substantiation) **Severity:** low > "Minimal implementation burden: can be implemented using existing lock-style algorithms plus timeout handling." The word "minimal" is a value claim. The sentence partially substantiates it ("can be implemented using existing...") but does not enumerate what is needed. Since the implementation section already provides a concrete example and a reference implementation, this is a minor issue - the evidence exists elsewhere in the paper. --- ## Notes - P3832's revision history is thorough and demonstrates responsive iteration with SG1 feedback. This is good practice. - P3833's "Alternative Designs Considered" section is well-argued and adds value. The rejection rationale for container-based interfaces is clear. - Both papers would benefit from a one-sentence forward reference to each other in their respective abstracts, since they form a cohesive pair. P3832 mentions P3833 in Design Rationale; P3833 mentions P3832 in Design Decisions. Cross-referencing earlier (in the abstract) would help a reader encountering either paper in isolation. - The `Account` example in P3833 R3 is a strong motivating example that concretely demonstrates why `multi_lock` matters beyond what `scoped_lock` provides. --- ## Methodology - Tool: The Arno (arno.md) - Rules applied: 17 - Challenge filters: 3 - Findings generated: 14 - Findings survived: 8 - Findings killed: 6 (3 by C1 - paper already handles it, 2 by C2 - audience mismatch for SG1-specific content, 1 by C3 - too trivial) *2026-06-27 11:19 - Claude (Sonnet)*