mapped_file/ring/
buffer.rs

1//! Traits and types used for mapping a R^W send-recv buffer `(tx, rx)`
2//!
3//! See `MappedFile::try_new_buffer()`
4use super::*;
5use std::{
6    borrow::Borrow,
7    ops,
8    sync,
9    rc,
10};
11
12pub trait TwoBufferProvider<T: ?Sized>
13{
14    type ControlWrapper: Borrow<T>;
15
16    fn as_wrapper(&self) -> &Self::ControlWrapper;
17    fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self>;
18
19    #[inline(always)] 
20    fn from_wrapper(r: &Self::ControlWrapper) -> Self
21    where Self: Sized {
22	*Self::from_wrapper_boxed(r)
23    }
24
25    #[inline(always)] 
26    fn inner(&self) -> &T
27    {
28	self.as_wrapper().borrow()
29    }
30
31    fn from_boxed(value: Box<T>) -> Box<Self>;
32
33    #[inline(always)] 
34    fn from_value(value: T) -> Self
35    where T: Sized,
36	  Self: Sized
37    {
38	*Self::from_boxed(Box::new(value))
39    }
40}
41
42/// For thread-sharable buffer holds
43#[derive(Debug)]
44pub struct Shared<T: ?Sized>(sync::Arc<T>);
45
46/// For non thread-sharable buffer holds
47#[derive(Debug)]
48pub struct Private<T: ?Sized>(rc::Rc<T>);
49
50impl<T: ?Sized> TwoBufferProvider<T> for Shared<T> {
51    type ControlWrapper = sync::Arc<T>;
52
53    #[inline(always)] 
54    fn as_wrapper(&self) -> &Self::ControlWrapper {
55	&self.0
56    }
57
58    #[inline] 
59    fn from_boxed(value: Box<T>) ->Box<Self> {
60	Box::new(Self(From::from(value)))
61    }
62
63    #[inline(always)]
64    fn from_value(value: T) -> Self
65    where T: Sized,
66	  Self: Sized {
67	Self(sync::Arc::new(value))
68    }
69
70    #[inline] 
71    fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self> {
72	Box::new(Self(r.clone()))
73    }
74    #[inline(always)] 
75    fn from_wrapper(r: &Self::ControlWrapper) -> Self
76    where Self: Sized {
77	Self(r.clone())
78    }
79}
80
81impl<T: ?Sized + AsRawFd> AsRawFd for Shared<T>
82{
83    #[inline(always)] 
84    fn as_raw_fd(&self) -> RawFd {
85	self.as_wrapper().as_raw_fd()
86    }
87}
88
89impl<T: ?Sized> TwoBufferProvider<T> for Private<T> {
90    type ControlWrapper = rc::Rc<T>;
91
92    #[inline(always)] 
93    fn as_wrapper(&self) -> &Self::ControlWrapper {
94	&self.0
95    }
96    
97    #[inline] 
98    fn from_boxed(value: Box<T>) ->Box<Self> {
99	Box::new(Self(From::from(value)))
100    }
101    
102    #[inline(always)]
103    fn from_value(value: T) -> Self
104    where T: Sized,
105	  Self: Sized {
106	Self(rc::Rc::new(value))
107    }
108    
109    #[inline] 
110    fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self> {
111	Box::new(Self(r.clone()))
112    }
113    #[inline(always)] 
114    fn from_wrapper(r: &Self::ControlWrapper) -> Self
115    where Self: Sized {
116	Self(r.clone())
117    }
118}
119
120impl<T: ?Sized + AsRawFd> AsRawFd for Private<T>
121{
122    #[inline(always)] 
123    fn as_raw_fd(&self) -> RawFd {
124	self.as_wrapper().as_raw_fd()
125    }
126}
127
128impl<T: ?Sized> Shared<T>
129{
130    /// Check if the connected mapping has not been dropped.
131    #[inline] 
132    pub fn is_connected(&self) -> bool
133    {
134	sync::Arc::strong_count(&self.0) > 1
135    }
136
137    /// Consume into an `Arc` instance over the file handle.
138    #[inline] 
139    pub fn into_arc(self) -> sync::Arc<T>
140    {
141	self.0
142    }
143
144    /// Get a reference of the file handle.
145    #[inline] 
146    pub fn inner(&self) -> &T
147    {
148	&self.0
149    }
150}
151impl<T: ?Sized> Private<T>
152{
153    /// Check if the connected mapping has not been dropped.
154    #[inline] 
155    pub fn is_connected(&self) -> bool
156    {
157	rc::Rc::strong_count(&self.0) > 1
158    }
159
160    /// Consume into an `Rc` instance over the file handle.
161    #[inline] 
162    pub fn into_rc(self) -> rc::Rc<T>
163    {
164	self.0
165    }
166
167    /// Get a reference of the file handle.
168    #[inline] 
169    pub fn inner(&self) -> &T
170    {
171	&self.0
172    }
173}
174
175//TODO: use `dup()` to turn (MappedFile<B>, MappedFile<B>) -> (MappedFile<impl FromRawFd>, MappedFile<impl FromRawFd>)
176
177pub trait BufferExt<T>
178{
179    fn detach(txrx: Self) -> (MappedFile<T>, MappedFile<T>);
180}
181
182impl<B, T> BufferExt<T> for (MappedFile<B>, MappedFile<B>)
183where B: TwoBufferProvider<T> + AsRawFd,
184T: FromRawFd,
185{
186    /// Detach a mapped dual buffer 2-tuple into regular mapped inner types.
187    #[inline] 
188    fn detach((itx, irx): Self) -> (MappedFile<T>, MappedFile<T>) {
189	#[cold]
190	#[inline(never)]
191	fn _panic_bad_dup(fd: RawFd) -> !
192	{
193	    panic!("Failed to dup({fd}): {}", io::Error::last_os_error())
194	}
195	let tx = itx.file.as_raw_fd();
196	let rx = irx.file.as_raw_fd();
197	
198	let (f0, f1) = unsafe {
199	    let fd1 = libc::dup(tx);
200	    if fd1 < 0 {
201		_panic_bad_dup(tx);
202	    }
203	    let fd2 = libc::dup(rx);
204	    if fd2 < 0 {
205		_panic_bad_dup(rx);
206	    }
207	    (T::from_raw_fd(fd1), T::from_raw_fd(fd2))
208	};
209	(MappedFile {
210	    map: itx.map,
211	    file: f0,
212	}, MappedFile {
213	    map: irx.map,
214	    file: f1
215	})
216    }
217}