You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
4.4 KiB
218 lines
4.4 KiB
//! Traits and types used for mapping a R^W send-recv buffer `(tx, rx)`
|
|
//!
|
|
//! See `MappedFile::try_new_buffer()`
|
|
use super::*;
|
|
use std::{
|
|
borrow::Borrow,
|
|
ops,
|
|
sync,
|
|
rc,
|
|
};
|
|
|
|
pub trait TwoBufferProvider<T: ?Sized>
|
|
{
|
|
type ControlWrapper: Borrow<T>;
|
|
|
|
fn as_wrapper(&self) -> &Self::ControlWrapper;
|
|
fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self>;
|
|
|
|
#[inline(always)]
|
|
fn from_wrapper(r: &Self::ControlWrapper) -> Self
|
|
where Self: Sized {
|
|
*Self::from_wrapper_boxed(r)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn inner(&self) -> &T
|
|
{
|
|
self.as_wrapper().borrow()
|
|
}
|
|
|
|
fn from_boxed(value: Box<T>) -> Box<Self>;
|
|
|
|
#[inline(always)]
|
|
fn from_value(value: T) -> Self
|
|
where T: Sized,
|
|
Self: Sized
|
|
{
|
|
*Self::from_boxed(Box::new(value))
|
|
}
|
|
}
|
|
|
|
/// For thread-sharable buffer holds
|
|
#[derive(Debug)]
|
|
pub struct Shared<T: ?Sized>(sync::Arc<T>);
|
|
|
|
/// For non thread-sharable buffer holds
|
|
#[derive(Debug)]
|
|
pub struct Private<T: ?Sized>(rc::Rc<T>);
|
|
|
|
impl<T: ?Sized> TwoBufferProvider<T> for Shared<T> {
|
|
type ControlWrapper = sync::Arc<T>;
|
|
|
|
#[inline(always)]
|
|
fn as_wrapper(&self) -> &Self::ControlWrapper {
|
|
&self.0
|
|
}
|
|
|
|
#[inline]
|
|
fn from_boxed(value: Box<T>) ->Box<Self> {
|
|
Box::new(Self(From::from(value)))
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn from_value(value: T) -> Self
|
|
where T: Sized,
|
|
Self: Sized {
|
|
Self(sync::Arc::new(value))
|
|
}
|
|
|
|
#[inline]
|
|
fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self> {
|
|
Box::new(Self(r.clone()))
|
|
}
|
|
#[inline(always)]
|
|
fn from_wrapper(r: &Self::ControlWrapper) -> Self
|
|
where Self: Sized {
|
|
Self(r.clone())
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized + AsRawFd> AsRawFd for Shared<T>
|
|
{
|
|
#[inline(always)]
|
|
fn as_raw_fd(&self) -> RawFd {
|
|
self.as_wrapper().as_raw_fd()
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> TwoBufferProvider<T> for Private<T> {
|
|
type ControlWrapper = rc::Rc<T>;
|
|
|
|
#[inline(always)]
|
|
fn as_wrapper(&self) -> &Self::ControlWrapper {
|
|
&self.0
|
|
}
|
|
|
|
#[inline]
|
|
fn from_boxed(value: Box<T>) ->Box<Self> {
|
|
Box::new(Self(From::from(value)))
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn from_value(value: T) -> Self
|
|
where T: Sized,
|
|
Self: Sized {
|
|
Self(rc::Rc::new(value))
|
|
}
|
|
|
|
#[inline]
|
|
fn from_wrapper_boxed(r: &Self::ControlWrapper) -> Box<Self> {
|
|
Box::new(Self(r.clone()))
|
|
}
|
|
#[inline(always)]
|
|
fn from_wrapper(r: &Self::ControlWrapper) -> Self
|
|
where Self: Sized {
|
|
Self(r.clone())
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized + AsRawFd> AsRawFd for Private<T>
|
|
{
|
|
#[inline(always)]
|
|
fn as_raw_fd(&self) -> RawFd {
|
|
self.as_wrapper().as_raw_fd()
|
|
}
|
|
}
|
|
|
|
impl<T: ?Sized> Shared<T>
|
|
{
|
|
/// Check if the connected mapping has not been dropped.
|
|
#[inline]
|
|
pub fn is_connected(&self) -> bool
|
|
{
|
|
sync::Arc::strong_count(&self.0) > 1
|
|
}
|
|
|
|
/// Consume into an `Arc` instance over the file handle.
|
|
#[inline]
|
|
pub fn into_arc(self) -> sync::Arc<T>
|
|
{
|
|
self.0
|
|
}
|
|
|
|
/// Get a reference of the file handle.
|
|
#[inline]
|
|
pub fn inner(&self) -> &T
|
|
{
|
|
&self.0
|
|
}
|
|
}
|
|
impl<T: ?Sized> Private<T>
|
|
{
|
|
/// Check if the connected mapping has not been dropped.
|
|
#[inline]
|
|
pub fn is_connected(&self) -> bool
|
|
{
|
|
rc::Rc::strong_count(&self.0) > 1
|
|
}
|
|
|
|
/// Consume into an `Rc` instance over the file handle.
|
|
#[inline]
|
|
pub fn into_rc(self) -> rc::Rc<T>
|
|
{
|
|
self.0
|
|
}
|
|
|
|
/// Get a reference of the file handle.
|
|
#[inline]
|
|
pub fn inner(&self) -> &T
|
|
{
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
//TODO: use `dup()` to turn (MappedFile<B>, MappedFile<B>) -> (MappedFile<impl FromRawFd>, MappedFile<impl FromRawFd>)
|
|
|
|
pub trait BufferExt<T>
|
|
{
|
|
fn detach(txrx: Self) -> (MappedFile<T>, MappedFile<T>);
|
|
}
|
|
|
|
impl<B, T> BufferExt<T> for (MappedFile<B>, MappedFile<B>)
|
|
where B: TwoBufferProvider<T> + AsRawFd,
|
|
T: FromRawFd,
|
|
{
|
|
/// Detach a mapped dual buffer 2-tuple into regular mapped inner types.
|
|
#[inline]
|
|
fn detach((itx, irx): Self) -> (MappedFile<T>, MappedFile<T>) {
|
|
#[cold]
|
|
#[inline(never)]
|
|
fn _panic_bad_dup(fd: RawFd) -> !
|
|
{
|
|
panic!("Failed to dup({fd}): {}", io::Error::last_os_error())
|
|
}
|
|
let tx = itx.file.as_raw_fd();
|
|
let rx = irx.file.as_raw_fd();
|
|
|
|
let (f0, f1) = unsafe {
|
|
let fd1 = libc::dup(tx);
|
|
if fd1 < 0 {
|
|
_panic_bad_dup(tx);
|
|
}
|
|
let fd2 = libc::dup(rx);
|
|
if fd2 < 0 {
|
|
_panic_bad_dup(rx);
|
|
}
|
|
(T::from_raw_fd(fd1), T::from_raw_fd(fd2))
|
|
};
|
|
(MappedFile {
|
|
map: itx.map,
|
|
file: f0,
|
|
}, MappedFile {
|
|
map: irx.map,
|
|
file: f1
|
|
})
|
|
}
|
|
}
|