前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swift-强引用&弱引用

Swift-强引用&弱引用

原创
作者头像
Wilbur-L
修改2021-03-08 14:22:24
8280
修改2021-03-08 14:22:24
举报
文章被收录于专栏:iOS底层原理iOS底层原理

强引用

Strong-RefCount

class Test{

var age: Int = 20

}

var t = Test()

var t1 = t

var t2= t

那么就有三个强引用指向当前的实例对象

InlineRefCountBits

引用计数里专门为了两个类型起了别名

typedef typename RefCountBitsInt<refcountIsInline, sizeof(void *)>::Type BitsType

typedef typename RefCountBitsInt<refcountIsInline, sizeof(void *)>::Type SingedType SignedBitsType

那么结构体里的是什么有价值的东西,值得swift另起别名

typedef uint64_t Type;

typedef int64_t SignedType;

//"Bitfield" accessors bit文件访问者

BiteType bits

那么bits就是一个64位整型的数据

在上一篇Swift文章中,列举过Swift对象初始化会传递的两个参数,一个是metadata,另一个是refCount

enum Initialized_t

// Refcount of a new object is 1 为新对象添加1引用计数

constexpr RefCounts(Initialized_t):refCounts(RefCountBits(0,1))

RefCountBits传入了0,1 这两个参数有什么作用?

RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)

RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)

:bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift) | (BitsType(unownedCount) << Offsets::UnownedRefCountShift))

可以发现,传入的两个参数0,1做了位操作

那么上面这步复杂的操作为了下面这张图的存放位置

1-1
1-1

在lldb上输入

po t

x/8g $0

那么第二段内存地址所表达的东西就很明显了,分别是UnownedRefCount,StrongExtraRefCount

increment

static HeapObject *_swift_retain_ (HeapObject *object){

object->refCounts.increment(1)

那么increment方法做了什么事情?

increment

oldbits = refCounts.load(memory_order_consume) //传入一个内存指定的消费对象

RefCountBits newbits

newbits = oldbits

fast = newbits.incrementStrongExtraRefCount(inc)

if oldbits.isImmortal(){ return }

if SWIFT_UNLIKEY(!fast){return incrementSlow(oldbits ,inc)

}while(!refCounts.compare_exchange_weak(oldbits,newbits,memory_order_relaxed))

绕了一大圈,回到了RefCounts,

incrementStrongExtraRefCount

bits((BitsType(strongExtraCount) << Offsets::StrongExtraRefCountShift)

bt打印的堆栈0x0000020000002 说明了就是上诉两个函数调用,位操作的结果

弱引用

NativeInit

side = object ? object->refCount.formWeakReferenct : nullptr

formWeakReference

auto side = allocateSideTable()

side->incrementWeak()

创建一个散列表allocateSideTable

HeapObjectSideTableEntry *side= new HeapObjectSideTabelEntry()

auto newbits = InlineRefCountBits(side)

好家伙,把side传给了在强引用时看见的InlineRefCountBits

回到强引用

RefCountBitsT

bits((reinterpret_cast<BitsType>(side) >> Offsets::SideTableUnusedLowBits)

| (BitsType(1) << Offsets::UseSlowRCShift)

| (BitsType(1) << Offsets::SideTableMarkShift)

)

位域操作想表达什么?

把散列表存到64位的某个位置

1-2
1-2

发现一对同兄难弟

typedef RefCounts<InlineRefCountBits> InlineRefCounts

typedef RefCounts<SideTableRefCountBits> SideTableRefCounts

强引用和弱应用一同指向了一个位置 RefCountBitsT 类型为uint64_t的bits

uint32_t weakBits

说明了RefCountBitsT存了强引用的bits也存储了弱引用计数

1-3
1-3

那么81e8存放的是对象,20087e02就是存放图1-2的地址

拿到该地址

1-4
1-4

把保留位63 62去掉

1-5
1-5

左移三位

1-6
1-6

拿到lldb里查看该地址信息

1-7
1-7

我们发现 43eff0 与对象地址是一样的

那么结果就出来了

0x10043f020 的前32位是强引用计数保存位置,后32位保存的是弱引用计数

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 强引用
    • Strong-RefCount
      • InlineRefCountBits
        • enum Initialized_t
          • RefCountBitsT(uint32_t strongExtraCount, uint32_t unownedCount)
            • increment
              • increment
                • incrementStrongExtraRefCount
                • 弱引用
                  • NativeInit
                    • formWeakReference
                      • 创建一个散列表allocateSideTable
                        • RefCountBitsT
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档