1use super::{Container, Rb, RbBase, RbRead, RbWrite, SharedStorage};
2use crate::{consumer::Consumer, producer::Producer};
3use core::{
4 cell::Cell,
5 mem::{ManuallyDrop, MaybeUninit},
6 num::NonZeroUsize,
7 ptr,
8};
9
10#[cfg(feature = "alloc")]
11use alloc::rc::Rc;
12
13/// Ring buffer for using in single thread.
14///
15/// Does *not* implement [`Sync`]. And its [`Producer`] and [`Consumer`] do *not* implement [`Send`].
16///
17#[cfg_attr(
18 feature = "std",
19 doc = r##"
20This code must fail to compile:
21
22```compile_fail
23use std::{thread, vec::Vec};
24use ringbuf::LocalRb;
25
26let (mut prod, mut cons) = LocalRb::<i32, Vec<_>>::new(256).split();
27thread::spawn(move || {
28 prod.push(123).unwrap();
29})
30.join();
31thread::spawn(move || {
32 assert_eq!(cons.pop().unwrap(), 123);
33})
34.join();
35```
36"##
37)]
38pub struct LocalRb<T, C: Container<T>> {
39 storage: SharedStorage<T, C>,
40 head: Cell<usize>,
41 tail: Cell<usize>,
42}
43
44impl<T, C: Container<T>> RbBase<T> for LocalRb<T, C> {
45 #[inline]
46 unsafe fn slices(
47 &self,
48 head: usize,
49 tail: usize,
50 ) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>]) {
51 self.storage.as_mut_slices(head, tail)
52 }
53
54 #[inline]
55 fn capacity_nonzero(&self) -> NonZeroUsize {
56 self.storage.len()
57 }
58
59 #[inline]
60 fn head(&self) -> usize {
61 self.head.get()
62 }
63
64 #[inline]
65 fn tail(&self) -> usize {
66 self.tail.get()
67 }
68}
69
70impl<T, C: Container<T>> RbRead<T> for LocalRb<T, C> {
71 #[inline]
72 unsafe fn set_head(&self, value: usize) {
73 self.head.set(val:value);
74 }
75}
76
77impl<T, C: Container<T>> RbWrite<T> for LocalRb<T, C> {
78 #[inline]
79 unsafe fn set_tail(&self, value: usize) {
80 self.tail.set(val:value);
81 }
82}
83
84impl<T, C: Container<T>> Rb<T> for LocalRb<T, C> {}
85
86impl<T, C: Container<T>> Drop for LocalRb<T, C> {
87 fn drop(&mut self) {
88 self.clear();
89 }
90}
91
92impl<T, C: Container<T>> LocalRb<T, C> {
93 /// Constructs ring buffer from container and counters.
94 ///
95 /// # Safety
96 ///
97 /// The items in container inside `head..tail` range must be initialized, items outside this range must be uninitialized.
98 /// `head` and `tail` values must be valid (see [`RbBase`](`crate::ring_buffer::RbBase`)).
99 pub unsafe fn from_raw_parts(container: C, head: usize, tail: usize) -> Self {
100 Self {
101 storage: SharedStorage::new(container),
102 head: Cell::new(head),
103 tail: Cell::new(tail),
104 }
105 }
106
107 /// Destructures ring buffer into underlying container and `head` and `tail` counters.
108 ///
109 /// # Safety
110 ///
111 /// Initialized contents of the container must be properly dropped.
112 pub unsafe fn into_raw_parts(self) -> (C, usize, usize) {
113 let (head, tail) = (self.head(), self.tail());
114 let self_ = ManuallyDrop::new(self);
115 (ptr::read(&self_.storage).into_inner(), head, tail)
116 }
117
118 /// Splits ring buffer into producer and consumer.
119 ///
120 /// This method consumes the ring buffer and puts it on heap in [`Rc`]. If you don't want to use heap the see [`Self::split_ref`].
121 #[cfg(feature = "alloc")]
122 pub fn split(self) -> (Producer<T, Rc<Self>>, Consumer<T, Rc<Self>>)
123 where
124 Self: Sized,
125 {
126 let rc = Rc::new(self);
127 unsafe { (Producer::new(rc.clone()), Consumer::new(rc)) }
128 }
129
130 /// Splits ring buffer into producer and consumer without using the heap.
131 ///
132 /// In this case producer and consumer stores a reference to the ring buffer, so you also need to store the buffer somewhere.
133 pub fn split_ref(&mut self) -> (Producer<T, &Self>, Consumer<T, &Self>)
134 where
135 Self: Sized,
136 {
137 unsafe { (Producer::new(self), Consumer::new(self)) }
138 }
139}
140