1- use core:: alloc:: Allocator ;
1+ use core:: alloc:: { AllocError , Allocator } ;
22use core:: cell:: UnsafeCell ;
33#[ cfg( not( no_global_oom_handling) ) ]
44use core:: clone:: CloneToUninit ;
@@ -11,7 +11,7 @@ use core::ptr::NonNull;
1111use crate :: raw_rc:: RefCounter ;
1212use crate :: raw_rc:: raw_weak:: RawWeak ;
1313#[ cfg( not( no_global_oom_handling) ) ]
14- use crate :: raw_rc:: rc_layout:: RcLayout ;
14+ use crate :: raw_rc:: rc_layout:: { RcLayout , RcLayoutExt } ;
1515use crate :: raw_rc:: rc_value_pointer:: RcValuePointer ;
1616
1717/// Decrements strong reference count in a reference-counted allocation with a value object that is
@@ -347,3 +347,132 @@ where
347347 unsafe { self . weak . value_ptr_unchecked ( ) }
348348 }
349349}
350+
351+ impl < T , A > RawRc < T , A > {
352+ unsafe fn from_weak_with_value ( weak : RawWeak < T , A > , value : T ) -> Self {
353+ unsafe {
354+ weak. as_ptr ( ) . write ( value) ;
355+
356+ Self :: from_weak ( weak)
357+ }
358+ }
359+
360+ #[ inline]
361+ pub ( crate ) fn try_new ( value : T ) -> Result < Self , AllocError >
362+ where
363+ A : Allocator + Default ,
364+ {
365+ RawWeak :: try_new_uninit :: < 1 > ( )
366+ . map ( |weak| unsafe { Self :: from_weak_with_value ( weak, value) } )
367+ }
368+
369+ #[ inline]
370+ pub ( crate ) fn try_new_in ( value : T , alloc : A ) -> Result < Self , AllocError >
371+ where
372+ A : Allocator ,
373+ {
374+ RawWeak :: try_new_uninit_in :: < 1 > ( alloc)
375+ . map ( |weak| unsafe { Self :: from_weak_with_value ( weak, value) } )
376+ }
377+
378+ #[ cfg( not( no_global_oom_handling) ) ]
379+ #[ inline]
380+ pub ( crate ) fn new ( value : T ) -> Self
381+ where
382+ A : Allocator + Default ,
383+ {
384+ unsafe { Self :: from_weak_with_value ( RawWeak :: new_uninit :: < 1 > ( ) , value) }
385+ }
386+
387+ #[ cfg( not( no_global_oom_handling) ) ]
388+ #[ inline]
389+ pub ( crate ) fn new_in ( value : T , alloc : A ) -> Self
390+ where
391+ A : Allocator ,
392+ {
393+ unsafe { Self :: from_weak_with_value ( RawWeak :: new_uninit_in :: < 1 > ( alloc) , value) }
394+ }
395+
396+ #[ cfg( not( no_global_oom_handling) ) ]
397+ fn new_with < F > ( f : F ) -> Self
398+ where
399+ A : Allocator + Default ,
400+ F : FnOnce ( ) -> T ,
401+ {
402+ let ( ptr, alloc) = super :: allocate_with :: < A , _ , 1 > ( T :: RC_LAYOUT , |ptr| unsafe {
403+ ptr. as_ptr ( ) . cast ( ) . write ( f ( ) )
404+ } ) ;
405+
406+ unsafe { Self :: from_raw_parts ( ptr. as_ptr ( ) . cast ( ) , alloc) }
407+ }
408+
409+ pub ( crate ) unsafe fn into_inner < R > ( self ) -> Option < T >
410+ where
411+ A : Allocator ,
412+ R : RefCounter ,
413+ {
414+ let is_last_strong_ref = unsafe { decrement_strong_ref_count :: < R > ( self . value_ptr ( ) ) } ;
415+
416+ is_last_strong_ref. then ( || unsafe { self . weak . assume_init_into_inner :: < R > ( ) } )
417+ }
418+
419+ pub ( crate ) unsafe fn try_unwrap < R > ( self ) -> Result < T , RawRc < T , A > >
420+ where
421+ A : Allocator ,
422+ R : RefCounter ,
423+ {
424+ unsafe fn inner < R > ( value_ptr : RcValuePointer ) -> bool
425+ where
426+ R : RefCounter ,
427+ {
428+ unsafe {
429+ R :: from_raw_counter ( value_ptr. strong_count_ptr ( ) . as_ref ( ) ) . lock_strong_count ( )
430+ }
431+ }
432+
433+ let is_last_strong_ref = unsafe { inner :: < R > ( self . value_ptr ( ) ) } ;
434+
435+ if is_last_strong_ref {
436+ Ok ( unsafe { self . weak . assume_init_into_inner :: < R > ( ) } )
437+ } else {
438+ Err ( self )
439+ }
440+ }
441+
442+ pub ( crate ) unsafe fn unwrap_or_clone < R > ( self ) -> T
443+ where
444+ T : Clone ,
445+ A : Allocator ,
446+ R : RefCounter ,
447+ {
448+ /// Calls `RawRc::drop` on drop.
449+ struct Guard < ' a , T , A , R >
450+ where
451+ T : ?Sized ,
452+ A : Allocator ,
453+ R : RefCounter ,
454+ {
455+ rc : & ' a mut RawRc < T , A > ,
456+ _phantom_data : PhantomData < R > ,
457+ }
458+
459+ impl < T , A , R > Drop for Guard < ' _ , T , A , R >
460+ where
461+ T : ?Sized ,
462+ A : Allocator ,
463+ R : RefCounter ,
464+ {
465+ fn drop ( & mut self ) {
466+ unsafe { self . rc . drop :: < R > ( ) } ;
467+ }
468+ }
469+
470+ unsafe {
471+ self . try_unwrap :: < R > ( ) . unwrap_or_else ( |mut rc| {
472+ let guard = Guard :: < T , A , R > { rc : & mut rc, _phantom_data : PhantomData } ;
473+
474+ T :: clone ( guard. rc . as_ptr ( ) . as_ref ( ) )
475+ } )
476+ }
477+ }
478+ }
0 commit comments