1
1
use alloc:: borrow;
2
- use alloc:: boxed:: Box ;
3
- use core:: cell:: UnsafeCell ;
4
2
use core:: fmt;
5
3
use core:: hash;
6
4
use core:: iter:: FusedIterator ;
7
5
use core:: marker:: PhantomData ;
8
6
use core:: mem:: ManuallyDrop ;
9
7
use core:: ops:: { Deref , DerefMut } ;
10
- use core:: ptr;
11
8
use core:: ptr:: NonNull ;
12
9
13
10
use super :: AutoreleasePool ;
11
+ use super :: { Owned , Ownership , Shared } ;
14
12
use crate :: Message ;
15
13
16
- /// A type used to mark that a struct owns the object(s) it contains,
17
- /// so it has the sole references to them.
18
- pub enum Owned { }
19
-
20
- /// A type used to mark that the object(s) a struct contains are shared,
21
- /// so there may be other references to them.
22
- pub enum Shared { }
23
-
24
- mod private {
25
- pub trait Sealed { }
26
-
27
- impl Sealed for super :: Owned { }
28
- impl Sealed for super :: Shared { }
29
- }
30
-
31
- /// A type that marks what type of ownership a struct has over the object(s)
32
- /// it contains; specifically, either [`Owned`] or [`Shared`].
33
- ///
34
- /// This trait is sealed and not meant to be implemented outside of the this
35
- /// crate.
36
- pub trait Ownership : private:: Sealed + ' static { }
37
-
38
- impl Ownership for Owned { }
39
- impl Ownership for Shared { }
40
-
41
14
/// An pointer for Objective-C reference counted objects.
42
15
///
43
16
/// [`Id`] strongly references or "retains" the given object `T`, and
@@ -539,148 +512,18 @@ impl<T, O: Ownership> Unpin for Id<T, O> {}
539
512
/// A convenient alias for a shared [`Id`].
540
513
pub type ShareId < T > = Id < T , Shared > ;
541
514
542
- /// A pointer type for a weak reference to an Objective-C reference counted
543
- /// object.
544
- ///
545
- /// Allows breaking reference cycles and safely checking whether the object
546
- /// has been deallocated.
547
- #[ repr( transparent) ]
548
- pub struct WeakId < T > {
549
- /// We give the runtime the address to this box, so that it can modify it
550
- /// even if the `WeakId` is moved.
551
- ///
552
- /// Loading may modify the pointer through a shared reference, so we use
553
- /// an UnsafeCell to get a *mut without self being mutable.
554
- inner : Box < UnsafeCell < * mut T > > ,
555
- /// TODO: Variance and dropck
556
- item : PhantomData < T > ,
557
- }
558
-
559
- impl < T : Message > WeakId < T > {
560
- /// Construct a new [`WeakId`] referencing the given shared [`Id`].
561
- #[ doc( alias = "objc_initWeak" ) ]
562
- pub fn new ( obj : & Id < T , Shared > ) -> Self {
563
- // Note that taking `&Id<T, Owned>` would not be safe since that would
564
- // allow loading an `Id<T, Shared>` later on.
565
-
566
- // SAFETY: `obj` is valid
567
- unsafe { Self :: new_inner ( & * * obj as * const T as * mut T ) }
568
- }
569
-
570
- /// # Safety
571
- ///
572
- /// The object must be valid or null.
573
- unsafe fn new_inner ( obj : * mut T ) -> Self {
574
- let inner = Box :: new ( UnsafeCell :: new ( ptr:: null_mut ( ) ) ) ;
575
- // SAFETY: `ptr` will never move, and the caller verifies `obj`
576
- objc2_sys:: objc_initWeak ( inner. get ( ) as _ , obj as _ ) ;
577
- Self {
578
- inner,
579
- item : PhantomData ,
580
- }
581
- }
582
-
583
- /// Load a shared (and retained) [`Id`] if the object still exists.
584
- ///
585
- /// Returns [`None`] if the object has been deallocated.
586
- #[ doc( alias = "upgrade" ) ]
587
- #[ doc( alias = "objc_loadWeak" ) ]
588
- #[ doc( alias = "objc_loadWeakRetained" ) ]
589
- #[ inline]
590
- pub fn load ( & self ) -> Option < Id < T , Shared > > {
591
- let ptr: * mut * mut objc2_sys:: objc_object = self . inner . get ( ) as _ ;
592
- let obj = unsafe { objc2_sys:: objc_loadWeakRetained ( ptr) } as * mut T ;
593
- NonNull :: new ( obj) . map ( |obj| unsafe { Id :: new ( obj) } )
594
- }
595
- }
596
-
597
- impl < T > Drop for WeakId < T > {
598
- /// Drops the `WeakId` pointer.
599
- #[ doc( alias = "objc_destroyWeak" ) ]
600
- fn drop ( & mut self ) {
601
- unsafe {
602
- objc2_sys:: objc_destroyWeak ( self . inner . get ( ) as _ ) ;
603
- }
604
- }
605
- }
606
-
607
- impl < T > Clone for WeakId < T > {
608
- /// Makes a clone of the `WeakId` that points to the same object.
609
- #[ doc( alias = "objc_copyWeak" ) ]
610
- fn clone ( & self ) -> Self {
611
- let ptr = Box :: new ( UnsafeCell :: new ( ptr:: null_mut ( ) ) ) ;
612
- unsafe {
613
- objc2_sys:: objc_copyWeak ( ptr. get ( ) as _ , self . inner . get ( ) as _ ) ;
614
- }
615
- Self {
616
- inner : ptr,
617
- item : PhantomData ,
618
- }
619
- }
620
- }
621
-
622
- impl < T : Message > Default for WeakId < T > {
623
- /// Constructs a new `WeakId<T>` that doesn't reference any object.
624
- ///
625
- /// Calling [`Self::load`] on the return value always gives [`None`].
626
- fn default ( ) -> Self {
627
- // SAFETY: The pointer is null
628
- unsafe { Self :: new_inner ( ptr:: null_mut ( ) ) }
629
- }
630
- }
631
-
632
- /// This implementation follows the same reasoning as `Id<T, Shared>`.
633
- unsafe impl < T : Sync + Send > Sync for WeakId < T > { }
634
-
635
- /// This implementation follows the same reasoning as `Id<T, Shared>`.
636
- unsafe impl < T : Sync + Send > Send for WeakId < T > { }
637
-
638
- // Unsure about the Debug bound on T, see std::sync::Weak
639
- impl < T : fmt:: Debug > fmt:: Debug for WeakId < T > {
640
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
641
- write ! ( f, "(WeakId)" )
642
- }
643
- }
644
-
645
- // Underneath this is just a `Box`
646
- impl < T > Unpin for WeakId < T > { }
647
-
648
515
#[ cfg( test) ]
649
516
mod tests {
650
- use core:: mem:: size_of;
651
517
use core:: ptr:: NonNull ;
652
518
653
- use super :: { Id , Owned , ShareId , Shared , WeakId } ;
519
+ use super :: { Id , Shared } ;
654
520
use crate :: runtime:: Object ;
655
521
use crate :: { class, msg_send} ;
656
522
657
523
fn retain_count ( obj : & Object ) -> usize {
658
524
unsafe { msg_send ! [ obj, retainCount] }
659
525
}
660
526
661
- pub struct TestType {
662
- _data : [ u8 ; 0 ] , // TODO: `UnsafeCell`?
663
- }
664
-
665
- #[ test]
666
- fn test_size_of ( ) {
667
- assert_eq ! ( size_of:: <Id <TestType , Owned >>( ) , size_of:: <& TestType >( ) ) ;
668
- assert_eq ! ( size_of:: <Id <TestType , Shared >>( ) , size_of:: <& TestType >( ) ) ;
669
- assert_eq ! (
670
- size_of:: <Option <Id <TestType , Owned >>>( ) ,
671
- size_of:: <& TestType >( )
672
- ) ;
673
- assert_eq ! (
674
- size_of:: <Option <Id <TestType , Shared >>>( ) ,
675
- size_of:: <& TestType >( )
676
- ) ;
677
-
678
- assert_eq ! (
679
- size_of:: <Option <WeakId <TestType >>>( ) ,
680
- size_of:: <* const ( ) >( )
681
- ) ;
682
- }
683
-
684
527
#[ test]
685
528
fn test_clone ( ) {
686
529
let cls = class ! ( NSObject ) ;
@@ -701,31 +544,4 @@ mod tests {
701
544
drop ( obj) ;
702
545
assert ! ( retain_count( & cloned) == 1 ) ;
703
546
}
704
-
705
- #[ test]
706
- fn test_weak ( ) {
707
- let cls = class ! ( NSObject ) ;
708
- let obj: ShareId < Object > = unsafe {
709
- let obj: * mut Object = msg_send ! [ cls, alloc] ;
710
- let obj: * mut Object = msg_send ! [ obj, init] ;
711
- Id :: new ( NonNull :: new_unchecked ( obj) )
712
- } ;
713
-
714
- let weak = WeakId :: new ( & obj) ;
715
- let strong = weak. load ( ) . unwrap ( ) ;
716
- let strong_ptr: * const Object = & * strong;
717
- let obj_ptr: * const Object = & * obj;
718
- assert ! ( strong_ptr == obj_ptr) ;
719
- drop ( strong) ;
720
-
721
- drop ( obj) ;
722
- assert ! ( weak. load( ) . is_none( ) ) ;
723
- }
724
-
725
- #[ test]
726
- fn test_weak_default ( ) {
727
- let weak: WeakId < Object > = WeakId :: default ( ) ;
728
- assert ! ( weak. load( ) . is_none( ) ) ;
729
- drop ( weak) ;
730
- }
731
547
}
0 commit comments