gpt4 book ai didi

ios - 为什么 weak_table_t 在 Objective-C 运行时是 SideTable 的成员?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:34:01 26 4
gpt4 key购买 nike

我正在阅读 https://github.com/opensource-apple/objc4 的 objc 代码.

在代码中,有一个struct SideTable,其中包含对应对象的引用计数和一个weak_table_t。

struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;

SideTable() {
memset(&weak_table, 0, sizeof(weak_table));
}

~SideTable() {
_objc_fatal("Do not delete SideTable.");
}

void lock() { slock.lock(); }
void unlock() { slock.unlock(); }
bool trylock() { return slock.trylock(); }

// Address-ordered lock discipline for a pair of side tables.

template<bool HaveOld, bool HaveNew>
static void lockTwo(SideTable *lock1, SideTable *lock2);
template<bool HaveOld, bool HaveNew>
static void unlockTwo(SideTable *lock1, SideTable *lock2);
};

而一个对象的SideTable可以通过SideTables()[obj]获取,因为每个对象的SideTable都存储在一个StripedMap中,StripedMap实际上是一个以对象地址的哈希值作为索引的数组。

但是根据weak_entry_for_referent的代码,runtime是通过检查weak_table->weak_entries[index].referent得到一个referent的weak_entry_t。

static weak_entry_t *
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent)
{
assert(referent);

weak_entry_t *weak_entries = weak_table->weak_entries;

if (!weak_entries) return nil;

size_t index = hash_pointer(referent) & weak_table->mask;
size_t hash_displacement = 0;
while (weak_table->weak_entries[index].referent != referent) {
index = (index+1) & weak_table->mask;
hash_displacement++;
if (hash_displacement > weak_table->max_hash_displacement) {
return nil;
}
}

return &weak_table->weak_entries[index];
}

这意味着 weak_table 包含多个单个对象的 weak 条目。那为什么weak_table_t是SideTable的成员而不是全局数据呢?

因为我找不到真正初始化对象 SideTable 的代码(storeStrong 只是使用 SideTable 而没有首先初始化它)和 weak_table,所以我不太明白事情在后台是如何工作的。

有人可以给我提示吗?

最佳答案

为什么 weak_table_t 是 SideTable 的成员

如果使用全局weak_table_t有两种情况应该解决。(refcnts有相同的情况)

  • 案例1:维护weak_table_t应该是线程安全的,所以我们需要锁
  • case 2:lock意味着慢,但是开发者希望系统运行的越快

只有一个全局weak_table_t无法解决上述两种情况。

实际上,class StripedMap 通过使用 lock striping,通过将 weak_table_trefcnts 包装在一起,解决了这两种情况在 SideTable 中。

让我们看一下下面的代码,从 objc-private.h 复制而来。

// StripedMap<T> is a map of void* -> T, sized appropriately 
// for cache-friendly lock striping.
// For example, this may be used as StripedMap<spinlock_t>
// or as StripedMap<SomeStruct> where SomeStruct stores a spin lock.
template<typename T>
class StripedMap {
// ... code for StripedMap
PaddedT array[StripeCount]; // There are 8 SideTables if define TARGET_OS_IPHONE
// ... code for StripedMap
}

8 个 SideTable 存储 8 个 weak_table_t 和 8 个 spinlock_t slock。系统最多可以为8个线程并发维护8个weak_table_t。我认为这在 iOS 设备上已经足够快了。

边表初始化

SideTablesMap.init();arr_init() 调用。您可以在 class ExplicitInitinit 上使用“Find Call Hierarchy”来查找调用层次结构

关于ios - 为什么 weak_table_t 在 Objective-C 运行时是 SideTable 的成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35427340/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com