「iOS」————SideTable

iOS學習

  • 前言
  • sideTable
    • SlideTables
    • SideTableBuf
    • SideTable


前言

我們在上一篇中,簡單的介紹了weak的實現原理。其中弱引用表就是存儲在SideTable中的,這里我們來學習了解一下SideTable

sideTable

sideTable主要用于存儲和管理對象的額外信息,特別是弱引用相關的數據。該表的設計和使用時OC運行時實現弱引用的基礎,使得ARC能夠正確的處理弱引用的生命周期。

SlideTables

定義

static StripedMap<SideTable>& SideTables() {return *reinterpret_cast<StripedMap<SideTable>*>(SideTableBuf);
}

SideTables的實質類型時StripedMap。在StripedMap類中有StripeCount定義存儲sidetable的最大數量。所以每個SideTable可以對應多個對象,而每個對象對應一個sideTable。

img

SideTableBuf

// We cannot use a C++ static initializer to initialize SideTables because
// libc calls us before our C++ initializers run. We also don't want a global 
// pointer to this struct because of the extra indirection.
// Do it the hard way.alignas(StripedMap<SideTable>) static uint8_t SideTableBuf[sizeof(StripedMap<SideTable>)];
  • SideTables 在 C++ 的 initializers 函數之前被調用,所以不能使用 C++ 初始化函數來初始化 SideTables,而 SideTables 本質就是 SideTableBuf;
  • 不能使用全局指針來指向這個結構體,因為涉及到重定向問題;

而SideTableBuf本質上就是一個長度為Sizeof(StripedMap)的char類型的數組;所以有:

SideTableBuf 本質上就是一個大小為和 StripedMap<SideTable> 對象一致的內存塊;

這也是為什么 SideTableBuf 可以用來表示 StripedMap<SideTable> 對象。本質上而言,SideTableBuf 就是指一個 StripedMap<SideTable>對象;

StripedMap < SideTable >

StripedMap是一個模板類,該類中有一個array成員,用來存儲PaddedT對象,并且其中對于[]符號的重載定義中,會返回這個PaddedT的value成員,這個value就是我們傳入的T泛型成員,也就是Side Table對象。在array的下標中,這里使用了indexForPointer方法通過位運算計算下標,實現了靜態的Hash Table。而在weak_table中,其成員weak_entry會將傳入對象的地址加以封裝起來,并且其中也有訪問全局弱引用表的入口。

T模板類型參數(泛型),它代表 “任意類型”,具體類型由使用 StripedMap 時指定。此處就是SideTable

  • T:泛型參數,在運行時中實際代表 SideTable,讓 StripedMap 成為管理 SideTable 的通用容器。
  • PaddedT:對 T(即 SideTable)的包裝,通過內存對齊(alignas)避免多線程訪問時的 CPU 緩存沖突,提升性能。
template<typename T>
class StripedMap {
#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATORenum { StripeCount = 8 };
#elseenum { StripeCount = 64 };
#endifstruct PaddedT {T value alignas(CacheLineSize);};PaddedT array[StripeCount];static unsigned int indexForPointer(const void *p) {uintptr_t addr = reinterpret_cast<uintptr_t>(p);return ((addr >> 4) ^ (addr >> 9)) % StripeCount;}public:T& operator[] (const void *p) { return array[indexForPointer(p)].value; }const T& operator[] (const void *p) const { return const_cast<StripedMap<T>>(this)[p]; }...省略了對象方法...
}
  • 首先根據是否為 iphone 定義了一個 StripeCount,iphone 下為 8;即最多為八個sidetable

  • 源碼中 CacheLineSize 為 64,使用 T 定義了一個結構體,而 T 就是 SideTable 類型;

  • 生成了一個長度為 8 類型為 SideTable 的數組;

  • indexForPointer() 邏輯為根據傳入的指針,經過一定的算法,計算出一個存儲該指針的位置,因為使用了取模運算,所以值的范圍是 0 ~ (StripeCount-1),所以不會出現數組越界;

  • 后面的 operator 表示重寫了運算符 [] 的邏輯,調用了 indexForPointer() 方法,這樣使用起來更像一個數組;

SideTables可以理解成一個類型為StripeMap< Side Table>靜態全局對象,內部以數組的形式存儲了StripeCount個SideTable

SideTable

struct SideTable {
// 保證原子操作的自旋鎖    spinlock_t slock;
// 引用計數的 hash 表RefcountMap refcnts;
// weak 引用全局 hash 表weak_table_t weak_table;//構造函數SideTable() {memset(&weak_table, 0, sizeof(weak_table));}//析構函數~SideTable() {_objc_fatal("Do not delete SideTable.");}...省略對象方法...
}

slock是一個自旋鎖,就是為了保證多線程訪問安全性

refcnts本質是一個存儲對象引用計數的hash表,key為對象,value為引用計數(優化過得isa中,引用計數主要存在isa中)

weak_table是存儲對象弱引用的一個結構體,該結構體內的成員如下

/**全局的弱引用表, 保存object作為key, weak_entry_t作為value* The global weak references table. Stores object ids as keys,* and weak_entry_t structs as their values.*/
struct weak_table_t {// 保存了所有指向特地對象的 weak指針集合weak_entry_t *weak_entries;// weak_table_t中有多少個weak_entry_tsize_t    num_entries;// weak_entry_t數組的countuintptr_t mask;// hash key 最大偏移值,// 采用了開放定制法解決hash沖突,超過max_hash_displacement說明weak_table_t中不存在要找的weak_entry_tuintptr_t max_hash_displacement;
};

下面是refcnts的定義:

typedef objc::DenseMap<DisguisedPtr<objc_object>,size_t,RefcountMapValuePurgeable> RefcountMap;

DenseMap 是一個 hash Map,基類 DenseMapBase 中的部分代碼,如下,DenseMapBase中重寫了操作符 []:

ValueT &operator[](const KeyT &Key) {return FindAndConstruct(Key).second;}

通過傳入的 Key 尋找對應的 Value。而 Key 是 DisguisedPtr<objc_object> 類型,Value 是 size_t 類型。即使用 obj.address :refCount 的形式來記錄引用計數器;

回到最初的 sidetable_addExtraRC_nolock 方法中:

size_t& refcntStorage = table.refcnts[this];

通過 this ,即 object 對象的地址,取出 refcnts 這個哈希表中存儲的引用計數器;

refcnts 可以理解成一個 Map,使用 address:refcount 的形式存儲了很多個對象的引用計數器;看不太懂這里

總結一下吧

img

  • iphone中Side Tables()本質上返回一個Side TableBuf對象,該對象存儲8個SideTable;(StripeCount)
  • 涉及到多線程和效率問題,有多個SideTable來存儲對象相關的引用計數器和弱引用
  • Apple通過對object的地址進行運算之后,對Side Table的個數進行取模運算,以次來決定將對象分配到哪個SideTable進行信息存儲,因為有取模運算,所以不會出現數組溢出。范圍為0-StripeCount-1
  • 當對象需要使用到Side Table時,會被分配到到 8/64 個全局 sideTables 中的某一個表中存儲相關的引用計數器或者弱引用信息;

這里再附上一張上一篇的弱引用表關系圖:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/917389.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/917389.shtml
英文地址,請注明出處:http://en.pswp.cn/news/917389.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【PHP】CURL請求第三方API接口

當我們需要調用第三方接口時&#xff0c;就需要使用CURL&#xff0c;通過CURL操作去請求第三方API接口&#xff0c;有的是通過POST方式&#xff0c;有的是通過GET方式&#xff0c;下面介紹一個通用的使用CURL調用API接口的方法。一、CURL操作共兩個方法&#xff0c;分別是CURL操…

對于考研數學的理解

文章目錄高等數學總結補充說明1. 微分方程與無窮級數的特殊性2. 隱藏的邏輯鏈條3. 向量代數的橋梁作用核心框架為什么這樣設計&#xff1f;結論線性代數核心邏輯框架各講之間的本質聯系1. 行列式 → 矩陣2. 矩陣 → 向量組3. 矩陣 向量組 → 線性方程組4. 矩陣 → 特征值與特征…

基于 Hadoop 生態圈的數據倉庫實踐 —— OLAP 與數據可視化(四)

目錄 四、數據可視化與 Hue 簡介 1. 數據可視化簡介 &#xff08;1&#xff09;數據可視化的重要性 &#xff08;2&#xff09;數據可視化的用途 &#xff08;3&#xff09;實施數據可視化需要考慮的問題 &#xff08;4&#xff09;幾種主要的數據可視化工具 2. Hue 簡介…

HarmonyOS 開發:基于 ArkUI 實現復雜表單驗證的最佳實踐

摘要 在現代應用開發中&#xff0c;表單是最常見的交互方式之一。不管是用戶注冊、信息錄入&#xff0c;還是登錄驗證&#xff0c;表單的可靠性直接影響用戶體驗。而在鴻蒙 ArkUI 開發中&#xff0c;雖然表單結構清晰&#xff0c;但要實現 復雜驗證&#xff08;比如&#xff1a…

高效游戲狀態管理:使用雙模式位運算與數學運算

在游戲開發中&#xff0c;狀態管理是一個核心問題。無論是任務系統、成就系統還是玩家進度跟蹤&#xff0c;我們都需要高效地存儲和查詢大量狀態。本文將深入分析一個創新的游戲狀態管理工具類 GameStateUtil&#xff0c;它巧妙結合了位運算和數學運算兩種模式&#xff0c;在存…

linux-process-control

Linux進程控制 1. 進程終止 1.1. 進程終止的本質是回收資源 1.1 釋放資源 內存資源&#xff1a; 釋放進程的地址空間&#xff08;mm_struct&#xff09;&#xff0c;包括代碼段、數據段、堆、棧等&#xff0c;通過寫時復制&#xff08;CoW&#xff09;共享的頁會減少引用計數&a…

Autoswagger:揭露隱藏 API 授權缺陷的開源工具

Autoswagger 是一款免費的開源工具&#xff0c;用于掃描 OpenAPI 文檔中列出的 API&#xff0c;查找授權漏洞。 即使在擁有成熟安全團隊的大型企業中&#xff0c;這類漏洞仍然很常見&#xff0c;而且尤其危險&#xff0c;因為即使技術水平不高的人也能利用它們。 Autoswagger…

Golang 語言 Channel 的使用方式

一、無緩存 channel無緩沖channel 可用于兩個goroutine 之間 傳遞信號&#xff0c;比如以下示例&#xff1a;順序打印1 至 100 的奇數和偶數&#xff1a;import ("fmt""time" )func main() {block : make(chan struct{})go odd(block)go even(block)time.S…

Element Plus常見基礎組件(一)

基礎組件 Button 按鈕 一、基礎用法 <el-button>默認按鈕</el-button> <el-button type"primary">主要按鈕</el-button>二、按鈕類型 (type) 類型說明示例代碼default默認按鈕<el-button>默認</el-button>primary主要按鈕&a…

sdxl量化加速筆記

文章目錄一、量化加速sdxl模型1&#xff09;涉及模型2&#xff09;環境安裝3&#xff09;轉換模型safetensor to pytorch文件4&#xff09;tensorRT的環境準備&#xff08;1&#xff09;下載tensorRT 10.10&#xff08;2&#xff09;下載cuda一、量化加速sdxl模型 1&#xff0…

西門子 G120 變頻器全解析:從認知到參數設置

在工業自動化領域&#xff0c;變頻器作為電機驅動的核心設備&#xff0c;其穩定運行與精準控制直接影響生產效率。西門子 G120 變頻器憑借可靠性能與靈活配置&#xff0c;成為眾多工業場景的優選。本文將從基礎認知、操作面板到參數設置&#xff0c;全方位帶你掌握 G120 變頻器…

【自動化運維神器Ansible】YAML支持的數據類型詳解:構建高效Playbook的基石

目錄 1 YAML數據類型概述 1.1 為什么數據類型很重要&#xff1f; 1.2 YAML數據類型分類 2 標量類型&#xff08;Scalars&#xff09; 2.1 字符串&#xff08;String&#xff09; 2.2 布爾值&#xff08;Boolean&#xff09; 2.3 數值&#xff08;Numbers&#xff09; 2…

基于崗位需求的康養休閑旅游服務實訓室建設方案

一、康養休閑旅游服務實訓室建設方案建設需求分析康養休閑旅游服務行業的快速發展對技能人才提出了精準化、場景化的能力要求&#xff0c;康養休閑旅游服務實訓室建設方案需緊密對接健康咨詢、接待服務、康樂服務等核心崗位群的實際需求。從崗位技能來看&#xff0c;健康咨詢崗…

MES 與工業物聯網(IIoT)的化學反應:為何是智能工廠的 “神經中樞”?

從“被動救火”到“主動預警”的工廠革命想象一下&#xff0c;當你正在家中熟睡時&#xff0c;智能手環突然震動&#xff0c;提醒你心率異常&#xff1b;早上出門前&#xff0c;手機 APP 告訴你愛車的某個零件即將達到磨損極限&#xff0c;建議及時更換。這些日常生活中的智能預…

工作好用小工具積累

1、內部環境太多&#xff0c;網站導航git地址&#xff1a;https://github.com/hslr-s/sun-panel/releases gitee地址&#xff1a;https://gitee.com/luofei1284999247/sun-panel

智能Agent場景實戰指南 Day 26:Agent評估與性能優化

【智能Agent場景實戰指南 Day 26】Agent評估與性能優化 開篇 歡迎來到"智能Agent場景實戰指南"系列的第26天&#xff01;今天我們將深入探討智能Agent的評估方法與性能優化技術。構建高效、可靠的智能Agent系統需要完善的評估體系和優化策略&#xff0c;本文將系統…

機器學習——下采樣(UnderSampling),解決類別不平衡問題,案例:邏輯回歸 信用卡欺詐檢測

過采樣&#xff1a; 機器學習——過采樣&#xff08;OverSampling&#xff09;&#xff0c;解決類別不平衡問題&#xff0c;案例&#xff1a;邏輯回歸 信用卡欺詐檢測-CSDN博客 &#xff08;完整代碼在底部&#xff09; 使用下采樣解決類別不平衡問題 —— 以信用卡欺詐識別為…

Qt 槽函數被執行多次,并且使用Qt::UniqueConnection無效【已解決】

Qt 槽函數被執行多次&#xff0c;并且使用Qt::UniqueConnection無效引言一、問題描述二、解決方案三、深入了解信號和槽綁定機制引言 之前剛遇到 - 信號和槽正常連接返回true&#xff0c;但發送信號后槽函數無響應問題&#xff0c;現在又遇到槽函數執行多次&#xff0c;使用Qt…

Autosar Nm-網管報文PNC停發后無法休眠問題排查

文章目錄前言Autosar CanNm標準中的相關參數CanNmAllNmMessagesKeepAwakePN過濾功能CanNm_ConfirmPnAvailability問題描述問題原因排查解決方案擴展總結前言 Autosar Nm中針對于支持PN功能的收發器&#xff0c;要求PNC停發后允許進入休眠模式&#xff0c;開發過程中遇到PNC停發…

RK3568下的進程間通信:基于UDP的mash網絡節點通信

基于UDP的mash網絡節點通信系統實現: 最近的項目中需要實現一個功能,類似mash網絡的功能,比如 類似下圖中的多個節點之間,相互之間通信, 節點A自身的通信列表中,只有B和C,所以A發出的消息給B和C,依次類推,A發送的消息所有節點都能收到,同理,其他節點比如K節點發送的…