欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > iOS - 弱引用表(Weak Reference Table)

iOS - 弱引用表(Weak Reference Table)

2025/1/10 17:15:17 来源:https://blog.csdn.net/Batac_Lee/article/details/144973593  浏览:    关键词:iOS - 弱引用表(Weak Reference Table)

1. 基本数据结构

// 弱引用表的基本结构
struct weak_table_t {weak_entry_t *weak_entries;      // 保存所有的弱引用对象size_t    num_entries;           // 当前存储的弱引用数量uintptr_t mask;                  // 哈希表大小掩码uintptr_t max_hash_displacement; // 最大哈希偏移值
};// 单个对象的弱引用信息
struct weak_entry_t {DisguisedPtr<objc_object> referent;  // 被引用的对象union {struct {weak_referrer_t *referrers;        // 动态数组uintptr_t        out_of_line : 1;  // 是否使用动态数组uintptr_t        num_refs : PTR_MINUS_1;  // 引用计数uintptr_t        mask;             // 容量掩码uintptr_t        max_hash_displacement;};struct {// 内联存储,用于优化少量弱引用的情况weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];};};
};

2. 核心操作

2.1 添加弱引用

id weak_register_no_lock(weak_table_t *weak_table, id referent, id *referrer, bool crashIfDeallocating) {// 1. 查找或创建 entryweak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) {entry = new_entry_for_referent(referent, referrer);weak_entry_insert(weak_table, entry);}// 2. 添加弱引用append_referrer(entry, referrer);return referent;
}

2.2 移除弱引用

void weak_unregister_no_lock(weak_table_t *weak_table, id referent, id *referrer) {weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) return;// 移除引用remove_referrer(entry, referrer);// 如果 entry 为空,则移除if (entry->out_of_line && entry->num_refs == 0) {weak_entry_remove(weak_table, entry);}
}

3. 存储优化

3.1 内联存储

#define WEAK_INLINE_COUNT 4struct weak_entry_t {union {// 当弱引用数量少时,使用内联数组struct {weak_referrer_t inline_referrers[WEAK_INLINE_COUNT];};// 当弱引用数量多时,使用动态数组struct {weak_referrer_t *referrers;uintptr_t out_of_line : 1;};};
};

3.2 动态扩展

static void grow_refs_and_insert(weak_entry_t *entry, objc_object **new_referrer) {assert(entry->out_of_line());size_t old_size = TABLE_SIZE(entry);size_t new_size = old_size ? old_size * 2 : 8;// 分配新空间weak_referrer_t *new_refs = (weak_referrer_t *)calloc(new_size, sizeof(weak_referrer_t));// 迁移数据for (size_t i = 0; i < old_size; i++) {weak_referrer_t oldref = entry->referrers[i];if (oldref) {weak_referrer_t *new_ref = new_refs + hash_pointer(oldref);*new_ref = oldref;}}
}

4. 线程安全

4.1 锁保护

struct SideTable {spinlock_t slock;      // 自旋锁RefcountMap refcnts;weak_table_t weak_table;void lock() { slock.lock(); }void unlock() { slock.unlock(); }
};// 使用示例
void weak_register_no_lock(weak_table_t *weak_table, id referent) {SideTable& table = SideTables()[referent];table.lock();// 操作 weak_tabletable.unlock();
}

4.2 原子操作

bool weak_entry_insert(weak_table_t *weak_table, weak_entry_t *new_entry) {return OSAtomicCompareAndSwapPtr(nil, new_entry, (void * volatile *)&weak_table->weak_entries);
}

5. 清理机制

5.1 对象释放时的清理

void weak_clear_no_lock(weak_table_t *weak_table, id referent) {weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);if (entry == nil) return;// 将所有弱引用置为 nilweak_referrer_t *referrers = entry->referrers;size_t count = entry->num_refs;for (size_t i = 0; i < count; ++i) {objc_object **referrer = referrers[i];if (referrer) {*referrer = nil;}}// 移除 entryweak_entry_remove(weak_table, entry);
}

5.2 表格清理

void weak_compact_maybe(weak_table_t *weak_table) {size_t old_size = TABLE_SIZE(weak_table);// 当表使用率低于 1/4 时进行收缩if (weak_table->num_entries < old_size / 4) {weak_resize(weak_table, old_size / 2);}
}

6. 性能优化

6.1 哈希优化

static inline uintptr_t hash_pointer(objc_object **p) {return ((uintptr_t)p) >> 3;  // 去除对齐位
}static inline size_t index_for_pointer(uintptr_t ptr, size_t mask) {return ptr & mask;  // 快速取模
}

6.2 空间优化

// 使用内联数组优化小对象
if (entry->num_refs < WEAK_INLINE_COUNT) {// 使用内联存储entry->inline_referrers[entry->num_refs++] = referrer;
} else {// 转换为动态数组move_to_dynamic_storage(entry);
}

7. 注意事项

1. 线程安全:

  • 所有操作都需要加锁保护
  • 使用原子操作进行关键更新
  • 内存管理:
  • 及时清理无用的 entry
  • 动态调整表大小避免内存浪费

3. 性能考虑:

  • 使用内联存储优化小对象
  • 哈希算法优化查找效率
  • 正确性保证:
  • 对象释放时正确清理所有弱引用
  • 维护引用计数的准确性

这个设计在保证功能正确的同时,通过多种优化手段提供了良好的性能。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com