首页 > 其他分享 >__attribute__ ((cleanup(xxx)))

__attribute__ ((cleanup(xxx)))

时间:2023-04-05 19:25:09浏览次数:40  
标签:__ attribute void xxx cleanup strong block

编译器属性__attribute__用于向编译器描述特殊的标识、检查或优化.

(一)基本用法

__attribute__((cleanup(...))),用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法,如:
// 指定一个cleanup方法,注意入参是所修饰变量的地址,类型要一样
// 对于指向objc对象的指针(id *),如果不强制声明__strong默认是__autoreleasing,造成类型不匹配
static void stringCleanUp(__strong NSString **string) {
    NSLog(@"%@", *string);
}
// 在某个方法中:
{
    __strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"sunnyxx";
} // 当运行到这个作用域结束时,自动调用stringCleanUp

所谓作用域结束,包括大括号结束、return、goto、break、exception等各种情况。

当然,可以修饰的变量不止NSString,自定义Class基本类型都是可以的:

// 自定义的Class
static void sarkCleanUp(__strong Sark **sark) {
    NSLog(@"%@", *sark);
}
__strong Sark *sark __attribute__((cleanup(sarkCleanUp))) = [Sark new];
// 基本类型
static void intCleanUp(NSInteger *integer) {
    NSLog(@"%d", *integer);
}
NSInteger integer __attribute__((cleanup(intCleanUp))) = 1;

假如一个作用域内有若干个cleanup的变量,他们的调用顺序是先入后出的栈式顺序;
而且,cleanup是先于这个对象的dealloc调用的。

(二)进阶用法

既然__attribute__((cleanup(...)))可以用来修饰变量,block当然也是其中之一,写一个block的cleanup函数非常有趣:

// void(^block)(void)的指针是void(^*block)(void)
static void blockCleanUp(__strong void(^*block)(void)) {
    (*block)();
}

于是在一个作用域里声明一个block:

{
   // 加了个`unused`的attribute用来消除`unused variable`的warning
    __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^{
        NSLog(@"I'm dying...");
    };
} // 这里输出"I'm dying..."

这里不得不提万能的Reactive Cocoa中神奇的@onExit方法,其实正是上面的写法,简单定义个宏:

#define onExit\
    __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

用这个宏就能将一段写在前面的代码最后执行:

{
    onExit {
        NSLog(@"yo");
    };
} // Log "yo"

这样的写法可以将成对出现的代码写在一起,比如说一个lock:

NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
// 这里
//     有
//        100多万行
[aLock unlock]; // 看到这儿的时候早忘了和哪个lock对应着了

用了onExit之后,代码更集中了:

NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
onExit {
    [aLock unlock]; // 妈妈再也不用担心我忘写后半段了
};
// 这里
//    爱多少行
//           就多少行

 

标签:__,attribute,void,xxx,cleanup,strong,block
From: https://www.cnblogs.com/imreW/p/17290581.html

相关文章

  • [2021CCCC天梯赛] L3-1 森森旅游(30分)
    [2021CCCC天梯赛]L3-1森森旅游(30分)题目描述好久没出去旅游啦!森森决定去Z省旅游一下。Z省有n座城市(从1到n编号)以及m条连接两座城市的有向旅行线路(例如自驾、长途汽车、火车、飞机、轮船等),每次经过一条旅行线路时都需要支付该线路的费用(但这个收费标准可能不止一种,......
  • K8s集群搭建问题
    警告CgroupDriver不一致节点加入集群会警告docker和kubelet的CgroupDriver不一致,但是暂未发现影响,如图:解决办法:修改docker的CgroupDriver为systemdvim/etc/docker/daemon.json加下面配置,注意在上一行配置后加逗号。"exec-opts":["native.cgroupdriver=syst......
  • [2021CCCC天梯赛] L3-2 还原文件(30分)
    [2021CCCC天梯赛]L3-2还原文件(30分)一份重要文件被撕成两半,其中一半还被送进了碎纸机。我们将碎纸机里找到的纸条进行编号,如图1所示。然后根据断口的折线形状跟没有切碎的半张纸进行匹配,最后还原成图2的样子。要求你输出还原后纸条的正确拼接顺序。图1纸条编号图2还原......
  • [2022CCCC天梯赛] L3-1 千手观音(30分)
    [2022CCCC天梯赛]L3-1千手观音(30分)题目描述人类喜欢用10进制,大概是因为人类有一双手10根手指用于计数。于是在千手观音的世界里,数字都是10000进制的,因为每位观音有1000双手……千手观音们的每一根手指都对应一个符号(但是观音世界里的符号太难画了,我们暂且用小写英......
  • Springboot+Mysql 图书管理系统【源码+sql】
    java项目学生图书管理系统(源码+数据库文件)技术框架:java+springboot+mysql后端框架:SpringBoot、SpringMVC、MyBatisPlus前端界面:Thymeleaf、BootStrap、jQuery系统共分为三种用户系统主要功能:系统设计三个角色,学生端,管理员端,系统管理员端1.普通用户书籍查询、书籍借阅......
  • 2023_4_5 蓝桥杯练习
    《P8671[蓝桥杯2018国AC]约瑟夫环 循环(%)问题》   我尝试用STL中的list与vector进行模拟可以发现复杂度都是>=O(N*K)的,会超时只有通过数学推式来得到全部正确的答案这里简单说一下STLlist与vector中对插入,删除元素的用法:list:......
  • Kafka保证消息可靠性配置
    前言这篇内容是保证Kafka消息可靠性的相关配置,内容主要来自《Kafka权威指南》这本书,再根据Apache-Kafka文档2.8总结出来的。文中每个配置项是个超链接,可以定位到配置的官方文档。代码例子可以访问GitHub-fruitbasket-litchi-kafkaBroker配置复制系数指一个主题(Topic)......
  • [oeasy]python0127_中文系统_gbk_BIG5_南极星_内码转化
    中文系统bgk回忆上次内容汉字字形通过点阵式打字机像素级寻址的屏幕进入了计算机的世界 ​ 添加图片注释,不超过140字(可选) 在海峡对岸的台湾同胞也进入了汉字时代 他们会使用GB2312编码吗?能互通吗?......
  • Verilog中的real类型及注意事项
    Verilog中的real类型变量为双精度浮点数,且符合IEEEStd754-1985对双精度浮点数的规定,即双精度浮点数为64位,其中1位符号位,11位指数位,53位尾数(其中包含1位隐含位).在IEEEStd754-1985中一般用{S、E、M}对双精度浮点数进行描述,一个64位双精度浮点数的表示格式如下:其中S为符......
  • C 库函数
    (一)malloc()说明:C库函数 void*malloc(size_tsize) 分配所需的内存空间,并返回一个指向它的指针。原型:void*malloc(size_tsize)//内存块的大小,以字节为单位。//该函数返回一个指针,指向已分配大小的内存。如果请求失败,则返回NULL。例子:var=shared_ptr_new(malloc......