Swift引用计数管理二

Swift引用计数

  • Swift引用计数官方文档描述如下

    Strong and unowned variables point at the object.
     Weak variables point at the object's side table.
    
    
     Storage layout:
    
     HeapObject {
       isa
    /// 只存储 strong unowned 引用计数
       InlineRefCounts {
         atomic {
           strong RC + unowned RC + flags
           OR
           HeapObjectSideTableEntry*
         }
       }
     }
    /// 存储 weak 以及 strong unowned的引用计数
     HeapObjectSideTableEntry {
       SideTableRefCounts {
         object pointer
         atomic {
           strong RC + unowned RC + weak RC + flags
         }
       }   
     }
    
  • 获取class-refcount的swift源码提供的函数如下,直接粘贴进项目可以直接打印:(纯Swift-class)

    /// 获取强引用计数
    @_silgen_name("swift_retainCount")
    public func _getRetainCount(_ Value: AnyObject) -> UInt
      
    /// 获取unowned引用计数
    @_silgen_name("swift_unownedRetainCount")
    public func _getUnownedRetainCount(_ Value : AnyObject) -> UInt
      
    /// 获取weak引用计数
    @_silgen_name("swift_weakRetainCount")
    public func _getWeakRetainCount(_ Value : AnyObject) -> UInt
    
  • 一个swift-class初始化的时候weak-refcountunowned-refcount以及strong-refcount默认都是1

  • 一个Class引用计数存储位置的

    /// RefCountNotInline 当使用weak时的标识
    /// RefCountIsInline  当前未使用weak
    enum RefCountInlinedness { RefCountNotInline = false, RefCountIsInline = true };
    
  • 如果当前class没有使用weak引用计数,存储的bits标识是RefCountBitsT InlineRefCountBits

    typedef RefCountBitsT InlineRefCountBits;
    
  • 如果当前class中使用的weak引用计数, 存储的bits标识是class SideTableRefCountBits : public RefCountBitsT

    /// sideTable  主要记录weak的引用及时
    class SideTableRefCountBits : public RefCountBitsT
    {
      /// weak 引用计数
      uint32_t weakBits;
    
      public:
      SideTableRefCountBits() = default;
      
      constexpr
      SideTableRefCountBits(uint32_t strongExtraCount, uint32_t unownedCount)
        : RefCountBitsT(strongExtraCount, unownedCount)
        // weak refcount starts at 1 on behalf of the unowned count
          /// Weak 引用计数 如果 SideTableRefCountBits初始化 默认是1
        , weakBits(1)
      { }
    
      LLVM_ATTRIBUTE_ALWAYS_INLINE
      SideTableRefCountBits(HeapObjectSideTableEntry* side) = delete;
    
      LLVM_ATTRIBUTE_ALWAYS_INLINE
      SideTableRefCountBits(InlineRefCountBits newbits)
        : RefCountBitsT(&newbits), weakBits(1)
      { }
    
      
      LLVM_ATTRIBUTE_ALWAYS_INLINE
      void incrementWeakRefCount() {
        weakBits++;
      }
    
      LLVM_ATTRIBUTE_ALWAYS_INLINE
        /// 标识是否需要释放
      bool decrementWeakRefCount() {
        assert(weakBits > 0);
        weakBits--;
        return weakBits == 0;
      }
    
      LLVM_ATTRIBUTE_ALWAYS_INLINE
      uint32_t getWeakRefCount() {
        return weakBits;
      }
    
      // Side table ref count never has a side table of its own.
      LLVM_ATTRIBUTE_ALWAYS_INLINE
      bool hasSideTable() {
        return false;
      }
    };
    
  • bits的的模板类,主要记录class的一些标识,包括是否存在side-table,是否是静态变量 ,还包含好引用计数的增加和减少

    // Basic encoding of refcount and flag data into the object's header.
    ///  RefCountBitsT
    template 
    class RefCountBitsT {
    
      friend class RefCountBitsT;
      friend class RefCountBitsT;
      
      static const RefCountInlinedness Inlinedness = refcountIsInline;
    
       /// 萃取 type的 bits位数
      typedef typename RefCountBitsInt::Type
        BitsType;
      typedef typename RefCountBitsInt::SignedType
        SignedBitsType;
    
        ///  根据 type 萃取 偏移量
      typedef RefCountBitOffsets
        Offsets;
    
      BitsType bits;
      
      /// 获取side-table
      HeapObjectSideTableEntry *getSideTable() const {
        assert(hasSideTable());
    
        // Stored value is a shifted pointer.
        return reinterpret_cast
          (uintptr_t(getField(SideTable)) << Offsets::SideTableUnusedLowBits);
      }
      
      /// 增加strong引用计数
      void setStrongExtraRefCount(uint32_t value) {
        assert(!hasSideTable());
        setField(StrongExtraRefCount, value);
      }
      
      /// 增加strong引用计数
      bool incrementStrongExtraRefCount(uint32_t inc) {
        // This deliberately overflows into the UseSlowRC field.
        bits += BitsType(inc) << Offsets::StrongExtraRefCountShift;
        return (SignedBitsType(bits) >= 0);
      }
    }
    
  • 其中RefCountBitsInt模板类负责适配不同的机型,如果32位机型overflow就是用64位

    template 
    struct RefCountBitsInt;
    
    /// 64 位
    template 
    struct RefCountBitsInt {
      typedef uint64_t Type;
      typedef int64_t SignedType;
    };
    
    // 32-bit out of line
    // 32 位
    template <>
    struct RefCountBitsInt {
      typedef uint64_t Type;
      typedef int64_t SignedType;
    };
    
    // 32-bit inline
    template <>
    struct RefCountBitsInt {
      typedef uint32_t Type;
      typedef int32_t SignedType;  
    };
    
  • RefCountsRefCountBits使用的模板实体类
/// strong unowned 引用计数
typedef RefCounts InlineRefCounts;

/// weak strong unowned 引用计数
typedef RefCounts SideTableRefCounts;
  • RefCounts内存模型

    ///模板类
    template 
    class RefCounts {
      /// strong unknown 引用计数
      std::atomic refCounts;
      
      public:
      /// 是否初始化
      enum Initialized_t { Initialized };
      /// 是否是常量, 不需要使用内存管理
      enum Immortal_t { Immortal };
      
      /// Return true if the object can be freed directly right now.
      /// (transition DEINITING -> DEAD)
      /// This is used in swift_deallocObject().
      /// Can be freed now means:  
      ///   no side table
      ///   unowned reference count is 1
      /// The object is assumed to be deiniting with no strong references already.
      
      /// 判断当前对象是否需要释放
      bool canBeFreedNow() const {
        auto bits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
        return (!bits.hasSideTable() &&
                /// 释放可以被释放
                bits.getIsDeiniting() &&
                /// 额外的引用计数
                bits.getStrongExtraRefCount() == 0 &&
                /// 这里的unknown的引用计数为1也会被释放
                bits.getUnownedRefCount() == 1);
      }
      
      /// Weak 存储的位置
      // WEAK
      
      public:
      // Returns the object's side table entry (creating it if necessary) with
      // its weak ref count incremented.
      // Returns nullptr if the object is already deiniting.
      // Use this when creating a new weak reference to an object.
      
      /// weak 引用计数管理
      HeapObjectSideTableEntry* formWeakReference();
      
      /// 判断对象是否需要释放
      template 
      bool doDecrementSlow(RefCountBits oldbits, uint32_t dec) {
        RefCountBits newbits;
        
        bool deinitNow;
        do {
          ///记录
          newbits = oldbits;
          
          /// 获取有没有使用引用计数的地方
          bool fast =
            newbits.decrementStrongExtraRefCount(dec);
          if (fast) {
            // Decrement completed normally. New refcount is not zero.
            deinitNow = false;
          }
          /// 判断是否是常量
          else if (oldbits.isImmortal()) {
            return false;
            /// 判断是否存在side-Table
          } else if (oldbits.hasSideTable()) {
            // Decrement failed because we're on some other slow path.
            return doDecrementSideTable(oldbits, dec);
          }
          else {
            // Decrement underflowed. Begin deinit.
            // LIVE -> DEINITING
            deinitNow = true;
            assert(!oldbits.getIsDeiniting());  // FIXME: make this an error?
            newbits = oldbits;  // Undo failed decrement of newbits.
            newbits.setStrongExtraRefCount(0);
            newbits.setIsDeiniting(true);
          }
        } while (!refCounts.compare_exchange_weak(oldbits, newbits,
                                                  std::memory_order_release,
                                                  std::memory_order_relaxed));
        if (performDeinit && deinitNow) {
          /// 原子性的加锁----非原子性释放 不用使用栅栏函数
          std::atomic_thread_fence(std::memory_order_acquire);
          
          /// 调用swift对象释放
          ///getHeapObject() 获取当前对象的内存地址
          _swift_release_dealloc(getHeapObject());
        }
    
        return deinitNow;
      }
    }
    
  • 关于HeapObjectSideTableEntry的定义

    class HeapObjectSideTableEntry {
      // FIXME: does object need to be atomic?
      
      /// 存储的对象
      std::atomic object;
      
      /// 引用计数
      SideTableRefCounts refCounts;
    
      public:
      HeapObjectSideTableEntry(HeapObject *newObject)
        : object(newObject), refCounts()
      { }
    }
    

你可能感兴趣的:(Swift引用计数管理二)