Skip to main content

Publisher

Struct Publisher 

Source
pub struct Publisher<T: Copy> { /* private fields */ }
Expand description

The write side of a Photon SPMC channel.

There is exactly one Publisher per channel. It is Send but not Sync — only one thread may publish at a time (single-producer guarantee enforced by &mut self).

Implementations§

Source§

impl<T: Copy> Publisher<T>

Source

pub fn publish_with(&mut self, f: impl FnOnce(&mut MaybeUninit<T>))

Publish by writing directly into the slot via a closure.

The closure receives a &mut MaybeUninit<T>, allowing in-place construction that can eliminate the write-side memcpy when the compiler constructs the value directly in slot memory.

This is the lossy (no backpressure) path. For bounded channels, prefer publish() with a pre-built value.

§Example
use std::mem::MaybeUninit;
let (mut p, s) = photon_ring::channel::<u64>(64);
let mut sub = s.subscribe();
p.publish_with(|slot| { slot.write(42u64); });
assert_eq!(sub.try_recv(), Ok(42));
Source

pub fn publish(&mut self, value: T)

Publish a single value. Zero-allocation, O(1).

On a bounded channel (created with channel_bounded()), this method spin-waits until there is room in the ring, ensuring no message loss. On a regular (lossy) channel, this publishes immediately without any backpressure check.

Source

pub fn try_publish(&mut self, value: T) -> Result<(), PublishError<T>>

Try to publish a single value with backpressure awareness.

  • On a regular (lossy) channel created with channel(), this always succeeds — it publishes the value and returns Ok(()).
  • On a bounded channel created with channel_bounded(), this checks whether the slowest subscriber has fallen too far behind. If publisher_seq - slowest_cursor >= capacity - watermark, it returns Err(PublishError::Full(value)) without writing.
Source

pub fn publish_batch(&mut self, values: &[T])

Publish a batch of values.

On a lossy channel: writes all values with a single cursor update at the end — consumers see the entire batch appear at once, and cache-line bouncing on the shared cursor is reduced to one store.

On a bounded channel: spin-waits for room before each value, ensuring no message loss. The cursor advances per-value (not batched), so consumers may observe a partial batch during publication.

Source

pub fn published(&self) -> u64

Number of messages published so far.

Source

pub fn sequence(&self) -> u64

Current sequence number (same as published()). Useful for computing lag: publisher.sequence() - subscriber.cursor.

Source

pub fn capacity(&self) -> u64

Ring capacity (power of two).

Source

pub fn mlock(&self) -> bool

Lock the ring buffer pages in RAM, preventing the OS from swapping them to disk. Reduces worst-case latency by eliminating page-fault stalls on the hot path.

Returns true on success. Requires CAP_IPC_LOCK or sufficient RLIMIT_MEMLOCK on Linux. No-op on other platforms.

Source

pub unsafe fn prefault(&self)

Pre-fault all ring buffer pages by writing a zero byte to each 4 KiB page. Ensures the first publish does not trigger a page fault.

§Safety

Must be called before any publish/subscribe operations begin. Calling this while the ring is in active use is undefined behavior because it writes zero bytes to live ring memory via raw pointers, which can corrupt slot data and seqlock stamps.

Trait Implementations§

Source§

impl<T: Copy + Send> Send for Publisher<T>

Auto Trait Implementations§

§

impl<T> Freeze for Publisher<T>

§

impl<T> !RefUnwindSafe for Publisher<T>

§

impl<T> !Sync for Publisher<T>

§

impl<T> Unpin for Publisher<T>

§

impl<T> UnsafeUnpin for Publisher<T>

§

impl<T> !UnwindSafe for Publisher<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.