美文网首页
Swift引用计数管理二

Swift引用计数管理二

作者: Smile_Later | 来源:发表于2020-07-17 10:03 被阅读0次

    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<InlineRefCountBits> {
             strong RC + unowned RC + flags
             OR
             HeapObjectSideTableEntry*
           }
         }
       }
      /// 存储 weak 以及 strong unowned的引用计数
       HeapObjectSideTableEntry {
         SideTableRefCounts {
           object pointer
           atomic<SideTableRefCountBits> {
             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<RefCountIsInline> InlineRefCountBits

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

      /// sideTable  主要记录weak的引用及时
      class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline>
      {
        /// weak 引用计数
        uint32_t weakBits;
      
        public:
        SideTableRefCountBits() = default;
        
        constexpr
        SideTableRefCountBits(uint32_t strongExtraCount, uint32_t unownedCount)
          : RefCountBitsT<RefCountNotInline>(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<RefCountNotInline>(&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 <RefCountInlinedness refcountIsInline>
      class RefCountBitsT {
      
        friend class RefCountBitsT<RefCountIsInline>;
        friend class RefCountBitsT<RefCountNotInline>;
        
        static const RefCountInlinedness Inlinedness = refcountIsInline;
      
         /// 萃取 type的 bits位数
        typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::Type
          BitsType;
        typedef typename RefCountBitsInt<refcountIsInline, sizeof(void*)>::SignedType
          SignedBitsType;
      
          ///  根据 type 萃取 偏移量
        typedef RefCountBitOffsets<sizeof(BitsType)>
          Offsets;
      
        BitsType bits;
        
        /// 获取side-table
        HeapObjectSideTableEntry *getSideTable() const {
          assert(hasSideTable());
      
          // Stored value is a shifted pointer.
          return reinterpret_cast<HeapObjectSideTableEntry *>
            (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 <RefCountInlinedness refcountIsInline, size_t sizeofPointer>
      struct RefCountBitsInt;
      
      /// 64 位
      template <RefCountInlinedness refcountIsInline>
      struct RefCountBitsInt<refcountIsInline, 8> {
        typedef uint64_t Type;
        typedef int64_t SignedType;
      };
      
      // 32-bit out of line
      // 32 位
      template <>
      struct RefCountBitsInt<RefCountNotInline, 4> {
        typedef uint64_t Type;
        typedef int64_t SignedType;
      };
      
      // 32-bit inline
      template <>
      struct RefCountBitsInt<RefCountIsInline, 4> {
        typedef uint32_t Type;
        typedef int32_t SignedType;  
      };
      
    • RefCountsRefCountBits使用的模板实体类
    /// strong unowned 引用计数
    typedef RefCounts<InlineRefCountBits> InlineRefCounts;
    
    /// weak strong unowned 引用计数
    typedef RefCounts<SideTableRefCountBits> SideTableRefCounts;
    
    • RefCounts内存模型

      ///模板类
      template <typename RefCountBits>
      class RefCounts {
        /// strong unknown 引用计数
        std::atomic<RefCountBits> 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 <PerformDeinit performDeinit>
        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<performDeinit>(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<HeapObject*> object;
        
        /// 引用计数
        SideTableRefCounts refCounts;
      
        public:
        HeapObjectSideTableEntry(HeapObject *newObject)
          : object(newObject), refCounts()
        { }
      }
      

    相关文章

      网友评论

          本文标题:Swift引用计数管理二

          本文链接:https://www.haomeiwen.com/subject/yshxqktx.html