Skip to content

webrtc: Replace Mutex<State> with lock-free AtomicU8 and consolidate wakers for WebRTC substream #523

@timwu20

Description

@timwu20

Summary

Replace the current Arc<Mutex<State>> with a lock-free AtomicU8 for managing WebRTC substream state, as suggested in PR #513.

This change also proposes merging the two separate wakers (shutdown_waker and write_waker) into a single state_waker. Before implementing, we need to verify this waker consolidation is safe and won't cause issues like infinite poll loops or unacceptable spurious wakeups.

Current Implementation

state: Arc<Mutex<State>>,

With separate wakers:

  • shutdown_waker: Arc<AtomicWaker> - notifies when FIN_ACK received
  • write_waker: Arc<AtomicWaker> - notifies when STOP_SENDING/RESET_STREAM received

Proposed Implementation

struct SharedState {
    // lock-free / more efficient
    // BITS 0 to 3
    // 0: open 1: sendClosed 2: closing 3: FinSent (our states) 4: FinAck

    // BIT 4: remote recv closed via FIN recv
    // BIT 5: STOP_SENDING remote send closed
    state: AtomicU8,

    // Waker for tasks waiting on state changes (ie poll write blocked on state, but poll shutdown has
    state_waker: AtomicWaker,
}

Investigation Required

Before implementing, we need to verify that we can merge all wakers into a single state_waker:

  1. shutdown_waker - currently woken when:

    • FIN_ACK received (on_messageState::FinAcked)
    • Registered in poll_shutdown when waiting for FIN_ACK
  2. write_waker - currently woken when:

    • STOP_SENDING received (on_messageState::SendClosed)
    • RESET_STREAM received (on_messageState::SendClosed)
    • Registered in poll_write when blocked due to backpressure

The key question: Can we safely wake a single state_waker on any state transition without causing spurious wakeups that degrade performance?

Since Substream is owned and polled by exactly one task, merging should be safe - the same task handles both poll_write and poll_shutdown. However, we should verify:

  • No scenario where waking causes infinite poll loops
  • Performance impact of spurious wakeups is acceptable (state transitions are rare)

Benefits

  • Lock-free state access (no mutex contention)
  • More efficient for concurrent access patterns
  • Reduced memory overhead (single AtomicU8 vs Mutex)

Trade-offs

  • Slightly more complex bit manipulation
  • May need careful ordering semantics (SeqCst vs Relaxed)
  • Single waker approach requires validation

Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions