@ -2,11 +2,55 @@ use std::sync::{
mpsc ,
Mutex ,
Arc ,
PoisonError ,
} ;
use std ::fmt ;
use std ::error ;
use std ::cell ::UnsafeCell ;
use std ::{ slice ::SliceIndex , ops ::RangeBounds } ;
#[ derive(Debug) ]
#[ repr(transparent) ]
struct StateInner
{
map : UnsafeCell < super ::map ::MemoryMapMut > ,
}
// SAFETY: The whole point of this is internal mutablility across thread boundaries.
unsafe impl Sync for StateInner { }
#[ derive(Debug, Clone) ]
pub struct State ( Arc < StateInner > ) ;
impl State
{
/// Create a new state from this map
#[ inline ] pub fn new ( map : super ::map ::MemoryMapMut ) -> Self
{
Self ( Arc ::new ( StateInner { map : UnsafeCell ::new ( map ) } ) )
}
/// Try to consume this instance into its map. This will only succeed if there are no more references to the state than this one.
#[ inline ] pub fn try_into_inner ( self ) -> Result < super ::map ::MemoryMapMut , Self >
{
match Arc ::try_unwrap ( self . 0 ) {
Ok ( v ) = > Ok ( v . map . into_inner ( ) ) ,
Err ( e ) = > Err ( Self ( e ) ) ,
}
}
/// Slice the map directly.
///
/// # Safety
/// The caller must make sure *no* slices of this map overlap with eachother.
// SAFETY: The map structure itself is never mutated, only its backing memory is accessed. This is fine, I think. If not, we can switch to using raw pointers and volatile writes. The backing memory itself is flushed to file when the map is dropped.
pub unsafe fn slice < R : RangeBounds < usize > + SliceIndex < [ u8 ] , Output = [ u8 ] > > ( & self , range : R ) -> & mut [ u8 ]
{
let slice = ( * ( self . 0. map . get ( ) ) ) . as_slice_mut ( ) ;
& mut slice [ range ]
}
}
/// A multi-consumer message receiver
#[ derive(Debug) ]