pub struct MpPublisher<T: Pod> { /* private fields */ }Expand description
The write side of a Photon MPMC channel.
Unlike Publisher, MpPublisher is Clone + Send + Sync — multiple
threads can publish concurrently. Sequence numbers are claimed atomically
via fetch_add on a shared counter, and the cursor is advanced with a
single best-effort CAS (no spin loop). Consumers use stamp-based reading,
so the cursor only needs to be eventually consistent for subscribe(),
latest(), and pending().
Created via channel_mpmc().
Implementations§
Source§impl<T: Pod> MpPublisher<T>
impl<T: Pod> MpPublisher<T>
Sourcepub fn publish(&self, value: T)
pub fn publish(&self, value: T)
Publish a single value. Zero-allocation, O(1) amortised.
Multiple threads may call this concurrently. Each call atomically claims a sequence number, writes the slot using the seqlock protocol, then advances the shared cursor.
Instead of spinning on the cursor CAS (which serializes all producers on one cache line), this implementation waits for the predecessor’s slot stamp to become committed. Stamp checks distribute contention across per-slot cache lines, avoiding the single-point serialization bottleneck. Once the predecessor is confirmed done, a single CAS advances the cursor, followed by a catch-up loop to absorb any successors that are also done.
Sourcepub fn publish_with(&self, f: impl FnOnce(&mut MaybeUninit<T>))
pub fn publish_with(&self, f: impl FnOnce(&mut MaybeUninit<T>))
Publish by writing directly into the slot via a closure.
Like publish, but the closure receives a
&mut MaybeUninit<T> for in-place construction, potentially
eliminating a write-side memcpy.
§Example
use std::mem::MaybeUninit;
let (p, subs) = photon_ring::channel_mpmc::<u64>(64);
let mut sub = subs.subscribe();
p.publish_with(|slot| { slot.write(42u64); });
assert_eq!(sub.try_recv(), Ok(42));