@@ -125,11 +125,7 @@ impl<T: Send> TripleBuffer<T> {
125125 /// Construct a triple buffer, using a functor to generate initial values
126126 fn new_impl ( mut generator : impl FnMut ( ) -> T ) -> Self {
127127 // Start with the shared state...
128- let mut new_buffer = || CachePadded :: new ( UnsafeCell :: new ( generator ( ) ) ) ;
129- let shared_state = Arc :: new ( SharedState {
130- buffers : [ new_buffer ( ) , new_buffer ( ) , new_buffer ( ) ] ,
131- back_info : AtomicBackBufferInfo :: new ( 0 ) ,
132- } ) ;
128+ let shared_state = Arc :: new ( SharedState :: new ( |_i| generator ( ) , 0 ) ) ;
133129
134130 // ...then construct the input and output structs
135131 TripleBuffer {
@@ -452,24 +448,32 @@ struct SharedState<T: Send> {
452448 buffers : [ CachePadded < UnsafeCell < T > > ; 3 ] ,
453449
454450 /// Information about the current back-buffer state
455- back_info : AtomicBackBufferInfo ,
451+ back_info : CachePadded < AtomicBackBufferInfo > ,
452+ }
453+ //
454+ #[ doc( hidden) ]
455+ impl < T : Send > SharedState < T > {
456+ /// Given (a way to generate) buffer contents and the back info, build the shared state
457+ fn new ( mut gen_buf_data : impl FnMut ( usize ) -> T , back_info : BackBufferInfo ) -> Self {
458+ let mut make_buf = |i| -> CachePadded < UnsafeCell < T > > {
459+ CachePadded :: new ( UnsafeCell :: new ( gen_buf_data ( i) ) )
460+ } ;
461+ Self {
462+ buffers : [ make_buf ( 0 ) , make_buf ( 1 ) , make_buf ( 2 ) ] ,
463+ back_info : CachePadded :: new ( AtomicBackBufferInfo :: new ( back_info) ) ,
464+ }
465+ }
456466}
457467//
458468#[ doc( hidden) ]
459469impl < T : Clone + Send > SharedState < T > {
460470 /// Cloning the shared state is unsafe because you must ensure that no one
461471 /// is concurrently accessing it, since &self is enough for writing.
462472 unsafe fn clone ( & self ) -> Self {
463- // The use of UnsafeCell makes buffers somewhat cumbersome to clone...
464- let clone_buffer = |i : usize | -> CachePadded < UnsafeCell < T > > {
465- CachePadded :: new ( UnsafeCell :: new ( ( * self . buffers [ i] . get ( ) ) . clone ( ) ) )
466- } ;
467-
468- // ...so better define some shortcuts before getting started:
469- SharedState {
470- buffers : [ clone_buffer ( 0 ) , clone_buffer ( 1 ) , clone_buffer ( 2 ) ] ,
471- back_info : AtomicBackBufferInfo :: new ( self . back_info . load ( Ordering :: Relaxed ) ) ,
472- }
473+ Self :: new (
474+ |i| ( * self . buffers [ i] . get ( ) ) . clone ( ) ,
475+ self . back_info . load ( Ordering :: Relaxed ) ,
476+ )
473477 }
474478}
475479//
@@ -504,6 +508,7 @@ unsafe impl<T: Send> Sync for SharedState<T> {}
504508/// the back-buffer, and reset to 0 when the consumer fetches the update.
505509///
506510type BufferIndex = u8 ;
511+ type BackBufferInfo = BufferIndex ;
507512//
508513type AtomicBackBufferInfo = AtomicU8 ;
509514const BACK_INDEX_MASK : u8 = 0b11 ; // Mask used to extract back-buffer index
@@ -512,16 +517,9 @@ const BACK_DIRTY_BIT: u8 = 0b100; // Bit set by producer to signal updates
512517/// Unit tests
513518#[ cfg( test) ]
514519mod tests {
515- use super :: {
516- AtomicBackBufferInfo , BufferIndex , SharedState , TripleBuffer , BACK_DIRTY_BIT ,
517- BACK_INDEX_MASK ,
518- } ;
519-
520- use crossbeam_utils:: CachePadded ;
520+ use super :: { BufferIndex , SharedState , TripleBuffer , BACK_DIRTY_BIT , BACK_INDEX_MASK } ;
521521
522- use std:: {
523- cell:: UnsafeCell , fmt:: Debug , ops:: Deref , sync:: atomic:: Ordering , thread, time:: Duration ,
524- } ;
522+ use std:: { fmt:: Debug , ops:: Deref , sync:: atomic:: Ordering , thread, time:: Duration } ;
525523
526524 use testbench:: {
527525 self ,
@@ -541,47 +539,24 @@ mod tests {
541539 #[ test]
542540 fn partial_eq_shared ( ) {
543541 // Let's create some dummy shared state
544- let dummy_state = SharedState :: < u16 > {
545- buffers : [ new_buffer ( 111 ) , new_buffer ( 222 ) , new_buffer ( 333 ) ] ,
546- back_info : AtomicBackBufferInfo :: new ( 0b10 ) ,
547- } ;
542+ let dummy_state = SharedState :: < u16 > :: new ( |i| [ 111 , 222 , 333 ] [ i] , 0b10 ) ;
548543
549544 // Check that the dummy state is equal to itself
550545 assert ! ( unsafe { dummy_state. eq( & dummy_state) } ) ;
551546
552547 // Check that it's not equal to a state where buffer contents differ
553- assert ! ( unsafe {
554- !dummy_state. eq( & SharedState :: <u16 > {
555- buffers: [ new_buffer( 114 ) , new_buffer( 222 ) , new_buffer( 333 ) ] ,
556- back_info: AtomicBackBufferInfo :: new( 0b10 ) ,
557- } )
558- } ) ;
559- assert ! ( unsafe {
560- !dummy_state. eq( & SharedState :: <u16 > {
561- buffers: [ new_buffer( 111 ) , new_buffer( 225 ) , new_buffer( 333 ) ] ,
562- back_info: AtomicBackBufferInfo :: new( 0b10 ) ,
563- } )
564- } ) ;
565- assert ! ( unsafe {
566- !dummy_state. eq( & SharedState :: <u16 > {
567- buffers: [ new_buffer( 111 ) , new_buffer( 222 ) , new_buffer( 336 ) ] ,
568- back_info: AtomicBackBufferInfo :: new( 0b10 ) ,
569- } )
570- } ) ;
548+ assert ! ( unsafe { !dummy_state. eq( & SharedState :: <u16 >:: new( |i| [ 114 , 222 , 333 ] [ i] , 0b10 ) ) } ) ;
549+ assert ! ( unsafe { !dummy_state. eq( & SharedState :: <u16 >:: new( |i| [ 111 , 225 , 333 ] [ i] , 0b10 ) ) } ) ;
550+ assert ! ( unsafe { !dummy_state. eq( & SharedState :: <u16 >:: new( |i| [ 111 , 222 , 336 ] [ i] , 0b10 ) ) } ) ;
571551
572552 // Check that it's not equal to a state where the back info differs
573553 assert ! ( unsafe {
574- !dummy_state. eq( & SharedState :: <u16 > {
575- buffers: [ new_buffer( 111 ) , new_buffer( 222 ) , new_buffer( 333 ) ] ,
576- back_info: AtomicBackBufferInfo :: new( BACK_DIRTY_BIT & 0b10 ) ,
577- } )
578- } ) ;
579- assert ! ( unsafe {
580- !dummy_state. eq( & SharedState :: <u16 > {
581- buffers: [ new_buffer( 111 ) , new_buffer( 222 ) , new_buffer( 333 ) ] ,
582- back_info: AtomicBackBufferInfo :: new( 0b01 ) ,
583- } )
554+ !dummy_state. eq( & SharedState :: <u16 >:: new(
555+ |i| [ 111 , 222 , 333 ] [ i] ,
556+ BACK_DIRTY_BIT & 0b10 ,
557+ ) )
584558 } ) ;
559+ assert ! ( unsafe { !dummy_state. eq( & SharedState :: <u16 >:: new( |i| [ 111 , 222 , 333 ] [ i] , 0b01 ) ) } ) ;
585560 }
586561
587562 /// Check that TripleBuffer's PartialEq impl works
@@ -619,20 +594,17 @@ mod tests {
619594 #[ test]
620595 fn clone_shared ( ) {
621596 // Let's create some dummy shared state
622- let dummy_state = SharedState :: < u8 > {
623- buffers : [ new_buffer ( 123 ) , new_buffer ( 231 ) , new_buffer ( 132 ) ] ,
624- back_info : AtomicBackBufferInfo :: new ( BACK_DIRTY_BIT & 0b01 ) ,
625- } ;
597+ let dummy_state = SharedState :: < u8 > :: new ( |i| [ 123 , 231 , 132 ] [ i] , BACK_DIRTY_BIT & 0b01 ) ;
626598
627599 // Now, try to clone it
628600 let dummy_state_copy = unsafe { dummy_state. clone ( ) } ;
629601
630602 // Check that the contents of the original state did not change
631603 assert ! ( unsafe {
632- dummy_state. eq( & SharedState :: <u8 > {
633- buffers : [ new_buffer ( 123 ) , new_buffer ( 231 ) , new_buffer ( 132 ) ] ,
634- back_info : AtomicBackBufferInfo :: new ( BACK_DIRTY_BIT & 0b01 ) ,
635- } )
604+ dummy_state. eq( & SharedState :: <u8 >:: new (
605+ |i| [ 123 , 231 , 132 ] [ i ] ,
606+ BACK_DIRTY_BIT & 0b01 ,
607+ ) )
636608 } ) ;
637609
638610 // Check that the contents of the original and final state are identical
@@ -946,11 +918,6 @@ mod tests {
946918 ) ;
947919 }
948920
949- /// Build data storage for a buffer
950- fn new_buffer < T > ( contents : T ) -> CachePadded < UnsafeCell < T > > {
951- CachePadded :: new ( UnsafeCell :: new ( contents) )
952- }
953-
954921 /// Range check for triple buffer indexes
955922 #[ allow( unused_comparisons) ]
956923 fn index_in_range ( idx : BufferIndex ) -> bool {
0 commit comments