Skip to main content

ReadAheadPool

Struct ReadAheadPool 

Source
pub struct ReadAheadPool { /* private fields */ }
Expand description

The process-wide read-ahead allocator: one byte budget shared by all active streams, with try_lock LRU eviction. Deadlock-free by construction — the budget is a lock-free atomic, the registry lock is a leaf (released before any buffer mutex), and eviction never blocks on a buffer mutex (try_lock + skip).

Implementations§

Source§

impl ReadAheadPool

Source

pub fn new(budget: u64) -> Self

Source

pub fn enabled(&self) -> bool

Source

pub fn per_stream_cap(&self) -> u64

Per-stream window cap derived from the budget.

Source

pub fn register(&self, key: usize, buf: Arc<Mutex<ReadAhead>>)

Lazily register a handle’s buffer once sequential access is detected.

Source

pub fn deregister(&self, key: usize)

Deregister on release; uncharges the buffer’s bytes. Drops the streams lock BEFORE locking the buffer: a concurrent read holds its buffer mutex and then blocking-acquires streams (via permitted_window), so holding streams while locking the buffer here would invert that order and deadlock. Keeping streams a leaf (released before any buffer mutex) preserves the pool’s deadlock-free invariant.

Source

pub fn touch(&self, key: usize)

Mark key as most-recently-served (LRU bump). No-op if unregistered.

Best-effort: a try_lock that SKIPS rather than blocks on contention. It runs at the end of every backing pread, on every stream, so a blocking lock here serializes all concurrent playback on this one registry mutex (#519). A skipped bump only leaves a stamp slightly stale, at worst evicting a marginally-warmer stream — and eviction is already best-effort (try_lock + skip), so the LRU order was never exact to begin with.

Source

pub fn permitted_window(&self, key: usize, old_len: u64, desired: u64) -> u64

Decide the largest window (≤ desired, ≤ per-stream cap) a stream may grow to right now, given a current size of old_len. Evicts colder OTHER streams as needed to make room for the (window - old_len) delta, but does NOT charge — charging happens in reconcile against the ACTUAL bytes read. Never blocks on a buffer mutex (try_lock + skip). Call only on a miss.

Source

pub fn reconcile(&self, old_len: u64, new_len: u64)

Charge the budget by the ACTUAL window-size change (old_len → new_len). Keeps the invariant charged == Σ(registered buffers' bytes.len()).

Source

pub fn has_room_for(&self, need: u64) -> bool

Best-effort check that need bytes of free (uncharged) budget exist. Speculative prefetch uses this rather than evicting live streams: under memory pressure it simply declines to prefetch. Racy by design — the caller still reconciles the actual stored delta, so the charged == Σ bytes invariant holds regardless; this only bounds overshoot.

Source

pub fn charged(&self) -> u64

Bytes currently held across all registered read-ahead buffers (telemetry musefs_readahead_charged_bytes; #394).

Source

pub fn budget(&self) -> u64

Total read-ahead RAM envelope; 0 when read-ahead is disabled (telemetry musefs_readahead_budget_bytes; #394).

Auto Trait Implementations§

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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.