ringbuf/wrap/
caching.rs
1use 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
16pub struct Caching<R: RbRef, const P: bool, const C: bool> {
18 frozen: Frozen<R, P, C>,
19}
20
21pub type CachingProd<R> = Caching<R, true, false>;
23pub type CachingCons<R> = Caching<R, false, true>;
25
26impl<R: RbRef, const P: bool, const C: bool> Caching<R, P, C> {
27 pub fn new(rb: R) -> Self {
31 Self { frozen: Frozen::new(rb) }
32 }
33
34 pub fn observe(&self) -> Obs<R> {
36 self.frozen.observe()
37 }
38
39 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>);