当前位置: 首页 > news >正文

iOS - 消息机制

1. 基本数据结构

// 方法结构
struct method_t {SEL name;       // 方法名const char *types;  // 类型编码IMP imp;       // 方法实现
};// 类结构
struct objc_class {Class isa;Class superclass;cache_t cache;        // 方法缓存class_data_bits_t bits;  // 类的方法、属性等信息
};// 方法缓存
struct cache_t {struct bucket_t *_buckets;  // 散列表mask_t _mask;              // 容量掩码mask_t _occupied;          // 已使用数量
};

2. 消息发送流程

2.1 基本流程

// 消息发送入口
id objc_msgSend(id self, SEL _cmd, ...) {if (!self) return nil;// 1. 查找方法缓存IMP imp = cache_getImp(self->isa, _cmd);if (imp) return imp(self, _cmd, ...);// 2. 完整查找流程return _objc_msgSend_uncached(self, _cmd, ...);
}

2.2 方法查找

IMP lookUpImpOrForward(id obj, SEL sel) {Class cls = obj->getIsa();// 1. 查找当前类的方法Method method = class_getInstanceMethod(cls, sel);if (method) {// 加入缓存cache_fill(cls, sel, method->imp);return method->imp;}// 2. 查找父类方法for (Class tcls = cls->superclass; tcls; tcls = tcls->superclass) {method = class_getInstanceMethod(tcls, sel);if (method) {cache_fill(cls, sel, method->imp);return method->imp;}}// 3. 动态方法解析if (resolveInstanceMethod(cls, sel)) {return lookUpImpOrForward(obj, sel);}// 4. 消息转发return _objc_msgForward;
}

3. 方法缓存机制

3.1 缓存结构

struct cache_t {// 缓存桶struct bucket_t {SEL _sel;   // 方法名IMP _imp;   // 方法实现} *_buckets;// 查找方法IMP imp(SEL sel) {bucket_t *b = buckets();mask_t m = mask();mask_t begin = cache_hash(sel, m);mask_t i = begin;do {if (b[i].sel() == sel) {return b[i].imp();}} while ((i = cache_next(i, m)) != begin);return nil;}
};

3.2 缓存优化

// 缓存哈希算法
static inline mask_t cache_hash(SEL sel, mask_t mask) {return (mask_t)(uintptr_t)sel & mask;
}// 缓存扩容
void cache_t::expand() {uint32_t oldCapacity = capacity();uint32_t newCapacity = oldCapacity ? oldCapacity * 2 : INIT_CACHE_SIZE;if (newCapacity > MAX_CACHE_SIZE) {newCapacity = MAX_CACHE_SIZE;}reallocate(oldCapacity, newCapacity);
}

4. 消息转发机制

4.1 动态方法解析

+ (BOOL)resolveInstanceMethod:(SEL)sel {if (sel == @selector(someMethod:)) {class_addMethod(self,sel,(IMP)dynamicMethodIMP,"v@:");return YES;}return [super resolveInstanceMethod:sel];
}

4.2 快速转发

- (id)forwardingTargetForSelector:(SEL)aSelector {if (aSelector == @selector(someMethod:)) {return alternateObject;  // 转发给其他对象}return [super forwardingTargetForSelector:aSelector];
}

4.3 完整转发

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {if (aSelector == @selector(someMethod:)) {return [NSMethodSignature signatureWithObjCTypes:"v@:"];}return [super methodSignatureForSelector:aSelector];
}- (void)forwardInvocation:(NSInvocation *)anInvocation {if ([alternateObject respondsToSelector:[anInvocation selector]]) {[anInvocation invokeWithTarget:alternateObject];} else {[super forwardInvocation:anInvocation];}
}

5. 性能优化

5.1 方法缓存

// 缓存命中检查
static ALWAYS_INLINE IMP cache_getImp(Class cls, SEL sel) {cache_key_t key = cache_key(sel);bucket_t *buckets = cls->cache.buckets();mask_t mask = cls->cache.mask();bucket_t *bucket = &buckets[key & mask];if (bucket->key() == key) {return bucket->imp();}return nil;
}

5.2 方法内联

// 编译器优化
static ALWAYS_INLINE id 
objc_msgSendSuper2(struct objc_super2 *super, SEL op, ...) {return ((id (*)(struct objc_super2 *, SEL, ...))objc_msgSendSuper2_fixup)(super, op, ...);
}

6. 特殊情况处理

6.1 nil 消息

if (!self) return nil;  // 发送给 nil 的消息返回 nil

6.2 Tagged Pointer

if (objc_isTaggedPointer(obj)) {// 特殊处理 Tagged Pointerreturn objc_msgSend_tagged(obj, sel, ...);
}

7. 线程安全

7.1 缓存更新

static void cache_fill(Class cls, SEL sel, IMP imp) {cache_t *cache = &cls->cache;cache->mutex.lock();// 更新缓存cache->insert(sel, imp);cache->mutex.unlock();
}

7.2 方法添加

static IMP addMethod(Class cls, SEL name, IMP imp, const char *types) {mutex_locker_t lock(runtimeLock);IMP result = nil;if (addMethodNoLock(cls, name, imp, types, &result)) {// 更新方法缓存flushCaches(cls);}return result;
}

这个消息机制设计的关键点:

  1. 高效的方法查找
  2. 灵活的消息转发
  3. 优秀的缓存策略
  4. 完善的线程安全
  5. 特殊情况的处理

这些特性使得 Objective-C 的消息机制既灵活又高效。

相关文章:

iOS - 消息机制

1. 基本数据结构 // 方法结构 struct method_t {SEL name; // 方法名const char *types; // 类型编码IMP imp; // 方法实现 };// 类结构 struct objc_class {Class isa;Class superclass;cache_t cache; // 方法缓存class_data_bits_t bits; // 类的方法…...

ChatGPT 是通用人工智能吗

ChatGPT 目前并不是通用人工智能(AGI, Artificial General Intelligence)。它是一种专用人工智能(Narrow AI),具体来说是一种基于大规模语言模型(如 GPT-4)的生成式人工智能,专注于处…...

Bash语言的函数实现

Bash语言的函数实现 引言 Bash(Bourne Again SHell)是一种在Unix和类Unix系统中广泛使用的命令行解释器。它不仅作为命令行工具使用,同时也被广泛应用于自动化脚本的编写。通过Bash,用户可以创建复杂的脚本,以执行一…...

Haskell语言的多线程编程

Haskell语言的多线程编程 在现代计算机科学中,多线程编程已经成为了提升程序性能的一个重要手段。尤其在我们处理计算密集型任务或 I/O 密集型任务时,合理地利用多核 CPU 的能力可以显著提升程序的执行效率。Haskell作为一种纯函数式编程语言&#xff0…...

Unity的四种数据持久化方式

目录 什么是数据持久化 数据持久化之PlayerPrefs 概述 API及用法 电脑中存放的位置 优缺点 主要用处 封装PlayerPrefs 数据持久化之XML XML是什么 读取XML信息 C#读取XML的方法有几种 读取xml文件信息 读取元素和属性信息 总结 写入XML信息 选择存储目录 存储…...

“霍普夫分岔”理论

庞加莱-安德罗诺夫-霍普夫分岔理论,通称为“霍普夫分岔”理论1,是首先由庞加莱在1892年对平面系统进行研究的2,然后由亚历山大安德罗诺夫(Aleksandr Andronov,1901-1952)及其合作者在1930年进行了完善和细化…...

10-C语言项目池

C语言项目池 《个人通讯录》 《火车订票系统》 管理员用户1录入火车票信息区间查询/购票2显示火车票信息打印购票信息3查询火车票信息退票4修改火车票信息5添加火车票信息 《学生学籍管理系统》 1录入学生信息2添加学生信息3显示学生信息4查找学生信息5删除学生信息6修改学…...

03、MySQL安全管理和特性解析(DBA运维专用)

03、MySQL安全管理和特性解析 本节主要讲MySQL的安全管理、角色使用、特定场景下的数据库对象、各版本特性以及存储引擎 目录 03、MySQL安全管理和特性解析 1、 用户和权限管理 2、 MySQL角色管理 3、 MySQL密码管理 4、 用户资源限制 5、 忘记root密码处理办法 6、 SQ…...

Ubuntu 下测试 NVME SSD 的读写速度

在 Ubuntu 系统下,测试 NVME SSD 的读写速度,有好多种方法,常用的有如下几种: 1. Gnome-disks Gnome-disks(也称为“Disks”)是 GNOME 桌面环境中的磁盘管理工具,有图形界面,是测试…...

C++编程进阶:标准库中的迭代器库解析

1. 迭代器库介绍 本文主要聚焦于C++的迭代器库,涵盖了迭代器的概念、分类、相关类型、原语操作、定制点、算法概念与实用工具、适配器、流迭代器、操作以及范围访问等内容,为C++编程中迭代器的使用提供了全面的参考。迭代器是一种抽象概念,它允许以统一的方式处理不同的数据…...

深入解析 JDK Lock:为什么必须在同一线程加锁和解锁?

前言 在多线程编程中,锁是一种常用的机制,用于控制对共享资源的访问,防止竞态条件的出现。Java 中的 Lock 接口提供了比 synchronized 关键字更灵活的锁机制。我们通常会使用 Lock 来确保同一时刻只有一个线程能访问某个共享资源。但是&#…...

下载b站高清视频

需要使用的edge上的一个扩展插件,所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站,登录自己账号(登录后才能下载到高清!!)。打开一个视频,选择自…...

采用标准化的方式开展设计-研发中运用设计模式

概述 实现规范化、标准化的引导式设计,以业务需求为输入,识别业务特点,并通过引导式设计,找到最适合的设计模式、具体方案,汇总成为应用的设计,拉齐各应用的设计一的致性。 采用标准化的方式开展设计…...

粒子的动力学和约束

本文先介绍单粒子的力学(mechanics of a particle),然后再介绍粒子系的力学(mechanics of particle system),最后介绍约束(constraints)。 1. 单粒子的动力学 从原点出发有一个失径,记为 r \bm{r} r,速度矢量记为 v \bm{v} v,则: v = d r d t ( 1.1 ) \bm{v} = \frac{…...

PCL点云库入门——PCL库点云特征之PFH点特征直方图(Point Feature Histograms -PHF)

1、算法原理 PFH点(Point Feature Histogram)特征直方图的原理涉及利用参数化查询点与邻域点之间的空间差异,并构建一个多维直方图以捕捉点的k邻域几何属性。这个高维超空间为特征表示提供了一个可度量的信息空间,对于点云对应曲面…...

基于vue的商城小程序的毕业设计与实现(源码及报告)

环境搭建 ☞☞☞ ​​​Vue入手篇(一),防踩雷(全网最详细教程)_vue force-CSDN博客 目录 一、功能介绍 二、登录注册功能 三、首页 四、项目截图 五、源码获取 一、功能介绍 用户信息展示:页面顶部设有用户头像和昵称展示区,方便用户识别…...

04-Linux系统编程之进程

一、进程的概述 1.什么是进程 进程:即进行中的程序,可执行文件从开始运行到结束运行这段过程就叫进程。 2.程序和进程的区别 程序:存储在磁盘上、占磁盘空间、静态的。如:我们编写的C语言代码就是程序,存储在我们电…...

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述,其缺点是有状态(多副本隔离时,依赖手动配置workId和datacenterId),代码如下: /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...

在Linux系统上使用nmcli命令配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)

1、更新于2024/5/13,新增Veth Pair配置 2、更新于2024/5/19,修复NetworkManager接管网络配置无效的错误 3、更新于2024/5/20,新增Ubuntu两种版本下NetworkManager接管网络的配置 目录 一、配置NetworkManager接管网络(选&…...

计算机网络 (25)IPV6

前言 IPv6,全称为“互联网协议第6版”(Internet Protocol Version 6),是由互联网工程任务组(IETF)设计的用于替代IPv4的下一代IP协议。 一、产生背景 IPv4,即互联网协议第4版,是现行…...

Git 安装 操作 命令 远程仓库 多人协作

Git作用 Git诞生史 很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在…...

线性回归的改进-岭回归

2.10 线性回归的改进-岭回归 学习目标 知道岭回归api的具体使用 1 API sklearn.linear_model.Ridge(alpha1.0, fit_interceptTrue,solver"auto", normalizeFalse) 具有l2正则化的线性回归alpha:正则化力度,也叫 λ λ取值:0~1 1~10solver:会根…...

【LC】2469. 温度转换

题目描述: 给你一个四舍五入到两位小数的非负浮点数 celsius 来表示温度,以 摄氏度(Celsius)为单位。 你需要将摄氏度转换为 开氏度(Kelvin)和 华氏度(Fahrenheit),并以…...

【在安卓平台上,Unity与C/C++编写的.so动态库交互的实现】

在安卓平台上,Unity与C/C++编写的.so动态库交互的实现,通常通过JNI(Java Native Interface)和P/Invoke机制来完成。通过这种方式,C#脚本可以调用C/C++代码中的函数,并与本地库进行交互。 以下是一个简单的步骤演示,展示如何在Unity中与安卓平台上的.so动态库交互。 步…...

【llm/ollama/qwen】在本地部署qwen2.5-coder并在vscode中集成使用代码提示功能

说在前面 操作系统:windows11ollama版本:0.5.4vscode版本:1.96.2continue插件版本:0.8.66 ollama安装 访问官网,点击下载安装即可 默认装在了C盘,比较蛋疼;但是可以指定路径安装:Ol…...

C语言练习:求数组的最大值与最小值

文章目录 1. 提出任务2. 完成任务2.1 方法一:通过返回结构体指针来间接返回结果2.1.1 编写程序,实现功能2.1.2 运行程序,查看结果 2.2 方法二:通过参数传递数组,并在函数中修改传入的参数2.2.1 编写程序,实…...

【TCP】SYN、ACK、FIN、RST、PSH、URG的全称

在 TCP 协议中,SYN、ACK、FIN、RST、PSH 和 URG 都是控制标志位(Flags),每个标志位对应不同的功能。它们的全称如下: URG:(URGent)紧急 ACK:(ACKnowledgment)确认 PSH:(PuSH)推送 RS…...

Re77 读论文:LoRA: Low-Rank Adaptation of Large Language Models

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名:LoRA: Low-Rank Adaptation of Large Language Models ArXiv网址:https://arxiv.org/abs/2106.09685 官方GitHub网站(包含在RoBERTa、DeBERTa、GPT-2上用Lora微调…...

《OpenCV 4.10.0 实例:开启图像处理新世界》

《OpenCV 4.10.0 实例:开启图像处理新世界》 一、OpenCV 4.10.0 初印象二、环境搭建:开启 OpenCV 之旅(一)不同系统安装指南(二)配置细节与技巧 三、基础图像处理实例(一)图像读取、…...

硬件电路(3)-PT100温度采集电路

一、概述 PT100是铂热电阻,它的阻值会随着温度的变化而改变。PT后的100即表示它在0℃时阻值为100欧姆,在100℃时它的阻值约为138.5欧姆。它的工作原理:当PT100在0摄氏度的时候它的阻值为100欧姆,它的阻值会随着温度上升而成匀速增…...

计算机网络——数据链路层-流量控制和可靠传输

一、流量控制 流量控制是指由接收方及时控制发送方发送数据的速率,使接收方来得及接受。 • 停止等待流量控制 • 滑动窗口流量控制 1、停止—等待流量控制 停止-等待流量控制的基本原理是发送方每发出一帧后,就要等待接收方的应答信号&#xff…...

sqlserver数据库备份和还原

一、备份 打开smss,选中数据库-任务-备份 地址选择默认如:C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Backup\ (远程服务器文件夹,非本机文件夹) PS:备份后编辑下数据 二、还原 PS:如果提示数…...

Python爬虫基础——认识网页结构(各种标签的使用)

1、添加<div>标签的代码定义了两个区块的宽度和高度均为100px&#xff0c;边框的格式也相同&#xff0c;只是区块中显示的内容不同&#xff1b; 2、添加<ul>和<ol>标签分别用于定义无序列表和有序列表。<il>标签位于<ul>标签或<ol>标签之…...

Linux双端口服务器:端口1的文件系统目录挂载到端口2

目录 一、服务器安装NFS服务并配置二、文件挂载三、持久化挂载总结为什么服务器配置多个端口 目前有一台服务器&#xff0c;不过他设置了两个SSH的端口&#xff0c;通过下面方法可以让这两个端口连接的主机能够共享同一个文件系统&#xff0c;原本这两个端口的文件系统是隔离的…...

unity学习11:地图相关的一些基础

目录 1 需要从 unity的 Asset Store 下载资源 1.1 下载资源 1.2 然后可以从 package Manager 里选择下载好的包&#xff0c;import到项目里 2 创建地形 2.1 创建地形 2.2 地形 Terrain大小 2.3 各种网格的尺寸大小 2.4 比较这个地形尺寸和创建的其他物体的大小对比 3 …...

如何在 Spring Cloud Gateway 中创建全局过滤器、局部过滤器和自定义条件过滤器

Spring Cloud Gateway 是一个功能强大的 API 网关&#xff0c;能够处理 HTTP 请求、响应及路由。通过过滤器机制&#xff0c;您可以在请求和响应过程中进行各种处理操作&#xff0c;如记录日志、身份验证、限流等。Spring Cloud Gateway 提供了三种主要类型的过滤器&#xff1a…...

总分支机构跨网文件交换解决方案几个关键要点

跨国公司和国内大型集团的日常运营中&#xff0c;总分支机构之间的文件交换已成为必不可少的环节。然而&#xff0c;跨网文件交换面临着诸多挑战&#xff0c;比如安全性、效率、合规性、管理便捷性、技术兼容性和成本效益等。 为了解决这些问题&#xff0c;在挑选总分支机构跨网…...

机器人手眼标定

机器人手眼标定 一、机器人手眼标定1. 眼在手上标定基本原理2. 眼在手外标定基本原理 二、眼在手外标定实验三、标定精度分析 一、机器人手眼标定 要实现由图像目标点到实际物体上抓取点之间的坐标转换&#xff0c;就必须拥有准确的相机内外参信息。其中内参是相机内部的基本参…...

将 Docker 数据迁移到新磁盘:详细操作指南

将 Docker 数据迁移到新磁盘&#xff1a;详细操作指南 背景 在容器化应用的部署中&#xff0c;Docker 通常将数据存储在默认的 /var/lib/docker 目录。然而&#xff0c;随着容器数量的增加和镜像的累积&#xff0c;该目录可能会迅速占满系统磁盘空间&#xff0c;从而影响系统…...

AWS re:Invent 的创新技术

本月早些时候&#xff0c;Amazon 于 12 月 1 日至 5 日在内华达州拉斯维加斯举行了为期 5 天的 re&#xff1a;Invent 大会。如果您从未参加过 re&#xff1a;Invent 会议&#xff0c;那么最能描述它的词是“巨大”——不仅从与会者人数&#xff08;60,000 人&#xff09;来看&…...

无人机低小慢探测难题!

一、探测难度增加 由于无人机的雷达散射面积小&#xff0c;雷达在探测时接收到的反射信号相对较弱。这使得雷达系统需要更高的灵敏度和更先进的信号处理算法才能有效捕捉到无人机的信号。在复杂环境中&#xff0c;如城市、山区或海洋&#xff0c;背景噪声和干扰源众多&#xf…...

第2章:Go语言基础语法

第2章&#xff1a;Go语言基础语法 1. 变量和数据类型 1.1 基本数据类型 Go语言提供了以下基本数据类型&#xff1a; // 整数类型 var intVar1 int // 根据系统位数&#xff0c;32或64位 var intVar2 int8 // -128 到 127 var intVar3 int16 // -32768 到 32767 var i…...

RP2K:一个面向细粒度图像的大规模零售商品数据集

这是一种用于细粒度图像分类的新的大规模零售产品数据集。与以往专注于相对较少产品的数据集不同&#xff0c;我们收集了2000多种不同零售产品的35万张图像&#xff0c;这些图像直接在真实的零售商店的货架上拍摄。我们的数据集旨在推进零售对象识别的研究&#xff0c;该研究具…...

pnpm安装与使用

pnpm官网 全局安装 npm install pnpm -g设置源 // 查看源 pnpm config get registry // 切换淘宝源 pnpm config set registry https://registry.npmmirror.com/ 移除 pnpm remove 包名称 // 移除包 pnpm remove 包名称 --global // 移除全局包 更新 pnpm up // 更新所有…...

c# 服务中启动exe窗体程序

Windows服务默认在会话0&#xff08;Session 0&#xff09;中运行&#xff0c;这是一个隔离的环境&#xff0c;旨在防止服务与应用程序和用户会话交互&#xff0c;从而提高系统的稳定性和安全性。由于这个原因&#xff0c;直接从服务启动的GUI应用程序将不会显示&#xff0c;因…...

使用pip-chill清理pip依赖包,清理不使用的包

最近需要精简python项目的依赖&#xff0c;需要清理一下哪些代码里面没有使用的包&#xff0c;查询了一下&#xff0c;记录 pip-chill 是一个用于管理 Python 项目中依赖项的工具&#xff0c;可以帮助您保持所需依赖项的清单简洁明了&#xff0c;并删除不必要的依赖。 1. 安装 …...

【算法题系列】LeetCode 5.最长回文子串|JavaScript 5种思路实现

题目描述 给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 示例 1&#xff1a; 输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2&#xff1a; 输入: "cbbd" 输出: &q…...

QT6编程入门(一)

1、QT6介绍 1.1、QT6概述 Qt 是一个跨平台的 C 应用程序框架&#xff0c;它被广泛用于开发图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;同时也可以用于开发非GUI程序&#xff0c;如控制台工具和服务器。Qt 被设计成能够在多种操作系统上运行&#xff0c;包括…...

串口通信控制LED、马达、蜂鸣器、风扇

1.STM32U575RITx 设置引脚 编写main.c //对fputc重写&#xff0c;方便调用printf函数 int fputc(int ch, FILE* F){HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 10);return ch; } //main函数的主要循环while (1){char whole_buf[128];memset(whole_buf, 0, siz…...

每日一题:BM2 链表内指定区间反转

文章目录 链表区间反转教学内容1. 任务描述2. 题目分析例子 3. 思路4. 详细步骤4.1 创建虚拟头节点4.2 寻找反转区间的前一个节点4.3 反转区间中的节点4.4 重新连接链表4.5 返回结果 5. 代码实现6. 代码解析6.1 初始化虚拟头节点6.2 寻找反转区间的前一个节点6.3 反转区间中的节…...