use std::{
any::Any,
num::NonZeroUsize,
sync::{
atomic::{AtomicPtr, Ordering},
Arc,
},
};
use api::common::types::ProtocolID;
use metadata::descriptor::MetadataDescriptor;
use watchdog::confirmator::ConfirmedDescriptor;
use zenoh_buffers::ZSliceBuffer;
#[macro_export]
macro_rules! tested_module {
($module:ident) => {
#[cfg(feature = "test")]
pub mod $module;
#[cfg(not(feature = "test"))]
mod $module;
};
}
#[macro_export]
macro_rules! tested_crate_module {
($module:ident) => {
#[cfg(feature = "test")]
pub mod $module;
#[cfg(not(feature = "test"))]
pub(crate) mod $module;
};
}
pub mod api;
mod cleanup;
pub mod header;
pub mod init;
pub mod metadata;
pub mod posix_shm;
pub mod reader;
pub mod version;
pub mod watchdog;
tested_crate_module!(shm);
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ShmBufInfo {
pub data_len: NonZeroUsize,
pub metadata: MetadataDescriptor,
pub generation: u32,
}
impl ShmBufInfo {
pub fn new(
data_len: NonZeroUsize,
metadata: MetadataDescriptor,
generation: u32,
) -> ShmBufInfo {
ShmBufInfo {
data_len,
metadata,
generation,
}
}
}
pub struct ShmBufInner {
pub(crate) metadata: Arc<ConfirmedDescriptor>,
pub(crate) buf: AtomicPtr<u8>,
pub info: ShmBufInfo,
}
impl PartialEq for ShmBufInner {
fn eq(&self, other: &Self) -> bool {
self.buf.load(Ordering::Relaxed) == other.buf.load(Ordering::Relaxed)
&& self.info.data_len == other.info.data_len
}
}
impl Eq for ShmBufInner {}
impl std::fmt::Debug for ShmBufInner {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ShmBufInner")
.field("metadata", &self.metadata)
.field("buf", &self.buf)
.field("info", &self.info)
.finish()
}
}
impl ShmBufInner {
pub fn protocol(&self) -> ProtocolID {
self.metadata
.owned
.header()
.protocol
.load(Ordering::Relaxed)
}
pub fn len(&self) -> NonZeroUsize {
self.info.data_len
}
fn is_valid(&self) -> bool {
let header = self.metadata.owned.header();
!header.watchdog_invalidated.load(Ordering::SeqCst)
&& header.generation.load(Ordering::SeqCst) == self.info.generation
}
fn is_unique(&self) -> bool {
self.ref_count() == 1
}
pub fn ref_count(&self) -> u32 {
self.metadata.owned.header().refcount.load(Ordering::SeqCst)
}
pub unsafe fn inc_ref_count(&self) {
self.metadata
.owned
.header()
.refcount
.fetch_add(1, Ordering::SeqCst);
}
fn as_slice(&self) -> &[u8] {
tracing::trace!("ShmBufInner::as_slice() == len = {:?}", self.info.data_len);
let bp = self.buf.load(Ordering::SeqCst);
unsafe { std::slice::from_raw_parts(bp, self.info.data_len.get()) }
}
unsafe fn dec_ref_count(&self) {
self.metadata
.owned
.header()
.refcount
.fetch_sub(1, Ordering::SeqCst);
}
unsafe fn as_mut_slice_inner(&mut self) -> &mut [u8] {
let bp = self.buf.load(Ordering::SeqCst);
std::slice::from_raw_parts_mut(bp, self.info.data_len.get())
}
}
impl Drop for ShmBufInner {
fn drop(&mut self) {
unsafe { self.dec_ref_count() };
}
}
impl Clone for ShmBufInner {
fn clone(&self) -> Self {
unsafe { self.inc_ref_count() };
let bp = self.buf.load(Ordering::SeqCst);
ShmBufInner {
metadata: self.metadata.clone(),
buf: AtomicPtr::new(bp),
info: self.info.clone(),
}
}
}
impl AsRef<[u8]> for ShmBufInner {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for ShmBufInner {
fn as_mut(&mut self) -> &mut [u8] {
unsafe { self.as_mut_slice_inner() }
}
}
impl ZSliceBuffer for ShmBufInner {
fn as_slice(&self) -> &[u8] {
self.as_ref()
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}