@@ -522,10 +522,16 @@ impl<T> Clone for ArcData<T> {
522522}
523523
524524/// User-data wrapper analogous to a `Arc<RefCell<T>>`, that is restricted to the thread
525- /// where it was originally created.
525+ /// where it was originally created. The destructor of `T` is not guaranteed to be run if
526+ /// this is actually shared across multiple threads.
526527///
527528/// This works by checking `ThreadId` before touching the underlying reference. If the id
528529/// doesn't match the original thread, `map` and `map_mut` will return an error.
530+ ///
531+ /// Since it isn't possible to control where the last reference is dropped, the destructor
532+ /// isn't run if the last reference is dropped on a different thread than the one where the
533+ /// wrapper was originally created. To ensure that values are cleaned up properly, keep the
534+ /// game single-threaded, or use a real thread-safe wrapper such as [`MutexData`] instead.
529535#[ derive( Debug ) ]
530536pub struct LocalCellData < T > {
531537 inner : Arc < local_cell:: LocalCell < T > > ,
@@ -535,12 +541,23 @@ pub use self::local_cell::LocalCellError;
535541
536542mod local_cell {
537543 use std:: cell:: { Ref , RefCell , RefMut } ;
544+ use std:: mem:: ManuallyDrop ;
538545 use std:: thread:: { self , ThreadId } ;
539546
540547 #[ derive( Debug ) ]
541548 pub struct LocalCell < T > {
542549 thread_id : ThreadId ,
543- cell : RefCell < T > ,
550+ cell : RefCell < ManuallyDrop < T > > ,
551+ }
552+
553+ impl < T > Drop for LocalCell < T > {
554+ fn drop ( & mut self ) {
555+ if self . thread_id == thread:: current ( ) . id ( ) {
556+ unsafe {
557+ ManuallyDrop :: drop ( self . cell . get_mut ( ) ) ;
558+ }
559+ }
560+ }
544561 }
545562
546563 /// Error indicating that a borrow has failed.
@@ -578,12 +595,12 @@ mod local_cell {
578595 pub fn new ( val : T ) -> Self {
579596 LocalCell {
580597 thread_id : thread:: current ( ) . id ( ) ,
581- cell : RefCell :: new ( val) ,
598+ cell : RefCell :: new ( ManuallyDrop :: new ( val) ) ,
582599 }
583600 }
584601
585602 #[ inline]
586- fn inner ( & self ) -> Result < & RefCell < T > , LocalCellError > {
603+ fn inner ( & self ) -> Result < & RefCell < ManuallyDrop < T > > , LocalCellError > {
587604 let current = thread:: current ( ) . id ( ) ;
588605
589606 if self . thread_id == current {
@@ -597,13 +614,13 @@ mod local_cell {
597614 }
598615
599616 #[ inline]
600- pub fn try_borrow ( & self ) -> Result < Ref < T > , LocalCellError > {
617+ pub fn try_borrow ( & self ) -> Result < Ref < ManuallyDrop < T > > , LocalCellError > {
601618 let inner = self . inner ( ) ?;
602619 inner. try_borrow ( ) . map_err ( |_| LocalCellError :: BorrowFailed )
603620 }
604621
605622 #[ inline]
606- pub fn try_borrow_mut ( & self ) -> Result < RefMut < T > , LocalCellError > {
623+ pub fn try_borrow_mut ( & self ) -> Result < RefMut < ManuallyDrop < T > > , LocalCellError > {
607624 let inner = self . inner ( ) ?;
608625 inner
609626 . try_borrow_mut ( )
0 commit comments