ringbuf/wrap/
caching.rs

1//! Caching implementation.
2//!
3//! Fetches changes from the ring buffer only when there is no more slots to perform requested operation.
4
5use super::{direct::Obs, frozen::Frozen, traits::Wrap};
6use crate::{
7    rb::RbRef,
8    traits::{
9        consumer::{impl_consumer_traits, Consumer},
10        producer::{impl_producer_traits, Producer},
11        Observer,
12    },
13};
14use core::{mem::MaybeUninit, num::NonZeroUsize};
15
16/// Caching wrapper of a ring buffer.
17pub struct Caching<R: RbRef, const P: bool, const C: bool> {
18    frozen: Frozen<R, P, C>,
19}
20
21/// Caching producer implementation.
22pub type CachingProd<R> = Caching<R, true, false>;
23/// Caching consumer implementation.
24pub type CachingCons<R> = Caching<R, false, true>;
25
26impl<R: RbRef, const P: bool, const C: bool> Caching<R, P, C> {
27    /// Create a new ring buffer cached wrapper.
28    ///
29    /// Panics if wrapper with matching rights already exists.
30    pub fn new(rb: R) -> Self {
31        Self { frozen: Frozen::new(rb) }
32    }
33
34    /// Get ring buffer observer.
35    pub fn observe(&self) -> Obs<R> {
36        self.frozen.observe()
37    }
38
39    /// Freeze current state.
40    pub fn freeze(self) -> Frozen<R, P, C> {
41        self.frozen
42    }
43}
44
45impl<R: RbRef, const P: bool, const C: bool> Wrap for Caching<R, P, C> {
46    type RbRef = R;
47
48    fn rb_ref(&self) -> &R {
49        self.frozen.rb_ref()
50    }
51    fn into_rb_ref(self) -> R {
52        self.frozen.into_rb_ref()
53    }
54}
55
56impl<R: RbRef, const P: bool, const C: bool> AsRef<Self> for Caching<R, P, C> {
57    fn as_ref(&self) -> &Self {
58        self
59    }
60}
61impl<R: RbRef, const P: bool, const C: bool> AsMut<Self> for Caching<R, P, C> {
62    fn as_mut(&mut self) -> &mut Self {
63        self
64    }
65}
66
67impl<R: RbRef, const P: bool, const C: bool> Observer for Caching<R, P, C> {
68    type Item = <R::Rb as Observer>::Item;
69
70    #[inline]
71    fn capacity(&self) -> NonZeroUsize {
72        self.frozen.capacity()
73    }
74
75    #[inline]
76    fn read_index(&self) -> usize {
77        if P {
78            self.frozen.fetch();
79        }
80        self.frozen.read_index()
81    }
82    #[inline]
83    fn write_index(&self) -> usize {
84        if C {
85            self.frozen.fetch();
86        }
87        self.frozen.write_index()
88    }
89
90    unsafe fn unsafe_slices(&self, start: usize, end: usize) -> (&[MaybeUninit<Self::Item>], &[MaybeUninit<Self::Item>]) {
91        self.frozen.unsafe_slices(start, end)
92    }
93    unsafe fn unsafe_slices_mut(&self, start: usize, end: usize) -> (&mut [MaybeUninit<Self::Item>], &mut [MaybeUninit<Self::Item>]) {
94        self.frozen.unsafe_slices_mut(start, end)
95    }
96
97    #[inline]
98    fn read_is_held(&self) -> bool {
99        self.frozen.read_is_held()
100    }
101    #[inline]
102    fn write_is_held(&self) -> bool {
103        self.frozen.write_is_held()
104    }
105}
106
107impl<R: RbRef> Producer for CachingProd<R> {
108    #[inline]
109    unsafe fn set_write_index(&self, value: usize) {
110        self.frozen.set_write_index(value);
111        self.frozen.commit();
112    }
113
114    fn try_push(&mut self, elem: Self::Item) -> Result<(), Self::Item> {
115        if self.frozen.is_full() {
116            self.frozen.fetch();
117        }
118        let r = self.frozen.try_push(elem);
119        if r.is_ok() {
120            self.frozen.commit();
121        }
122        r
123    }
124}
125
126impl<R: RbRef> Consumer for CachingCons<R> {
127    #[inline]
128    unsafe fn set_read_index(&self, value: usize) {
129        self.frozen.set_read_index(value);
130        self.frozen.commit();
131    }
132
133    fn try_pop(&mut self) -> Option<<Self as Observer>::Item> {
134        if self.frozen.is_empty() {
135            self.frozen.fetch();
136        }
137        let r = self.frozen.try_pop();
138        if r.is_some() {
139            self.frozen.commit();
140        }
141        r
142    }
143}
144
145impl_producer_traits!(CachingProd<R: RbRef>);
146impl_consumer_traits!(CachingCons<R: RbRef>);