做了个玩具
#include <setjmp.h>
#include <stdio.h>
struct defer_t {
jmp_buf env1;
jmp_buf env2;
long rsp;
~defer_t() {
int n = setjmp(env2);
asm("mov %%rsp, %0\n" :"=m"(rsp) ::);
//printf("save rsp %p %p %p\n", (void *) rsp, this, __builtin_return_address(0));
if (n == 0) {
longjmp(env1, 1);
}
}
};
#define defer2(l, ...) \
({ \
defer_t* np = &defer_node_##l; \
if (1 == setjmp(np->env1)) { \
__asm__ __volatile ("mov %0, %%rsp\n" : :"m"(np->rsp) :"rsp"); \
__VA_ARGS__; \
longjmp(np->env2, 1); \
} \
np; \
})
#define defer1(l, ...) defer_t defer_node_##l, *dn_ptr_##l = defer2(l, ##__VA_ARGS__)
#define defer(...) defer1(__line__, ##__VA_ARGS__)
int tests()
{
struct a{
~a() {
printf("hello world\n");
}
};
int var = 9;
if (var == 9) {
puts("normal 1");
defer(delete (new a));
}
defer(printf("deffered %d\n", var));
puts("normal 2");
return 0;
}
int main()
{
tests();
puts("sss\n");
return 0;
}
clang 可以看起来正常运行, gcc 不带 -O 编译可以运行, 其他的失败
用go就行了,还折腾回来干嘛:luya: c++一个类析构+闭包不也一样 本帖最后由 zylthinking 于 2018-01-23 18:03 编辑
回复 3# cokeboL
lamda 写起来不自然, 而且
能这样?
defer(delete (new a))
我的里面不是函数调用, 是语句
回复 4# zylthinking
再怎么着,也不如go自然,直接写go好不好? 本帖最后由 zylthinking 于 2018-01-23 23:56 编辑
回复 5# cokeboL
我知道你转go了, 我没说go不好, 但你也不要随时随地go万岁行不行
go 也就是一个m:n线程库 + 变量生存期自动化 + 垃圾收集器 三方面内容; 反射性能低, cgo性能低; 因为它是m:n的, 除了能够像协程那样 switch to + 可以轻易创建大量的 go程而不明显拖累性能, 以及只要不调用标准库函数, 那么大概率不会被其他go程抢占外(说是大概率, 是因为我也不确定go编译器会不会偷偷摸摸在代码中插入时间相关的go程切换代码, 反正fmt.Printf 中肯定存在时间片耗尽被切换走类似的逻辑), 其他的和线程没分别, 该上的锁一个也漏不掉。
话说一次面试时让用一读一写两个go程来读写链表, 面试官失望的说我写的和线程没区别, 我就郁闷了, M:N 下可不你还真没办法写的有区别。
重要的是, 库现在还幼稚的很; 你找一个 gmime 类似的邮件解析库给我看看先
golang 的 defer 语法形式也就一般般, 我模拟它不是羡慕它, 只是想看看到底能不能实现。
再说, 你golang 能 defer close(file);就自然, 我 defer(close(file)) 就不自然?
我不就你比多一个括号吗?
我还能
int i = 9;
defer (i = 10);
呢
你golang 怎么写?
i := 9;
defer func() {i = 10} ()?
谁不自然?
golang 循环中的 defer 是大忌吧
我的没事
要说我的哪里不好, 就是严重依赖编译器的实现, 目前观察下来, gcc -O优化会挂,clang没事 gcc 不带 O 也没事; 另外clang 也不保险
但我都说这是玩具了, 就是弄着玩的;
假设编译器给力, 我的语法形式怎么也不会比 golang难看
何况, 我使用了 不到 40行代码模拟出了 golang 在编译器帮助下才实现的 defer 语义, 难道你就不表示佩服:mrgreen:
表示佩服:mrgreen::mrgreen::mrgreen::mrgreen: 说真的,看不懂。。。 回复 6# zylthinking
好的,我欠状元郎一个佩服,这里补上:五体投地,十分佩服!
到处go万岁也是为了用的人更多,圈子更强大,然后跟着享福:mrgreen:
说不自然只是为了忽悠大家在非极端领域(比如嵌入式等硬件资源受限或者要求极致性能的场景),尽量别再c/c++了,真的好累心
“反射性能低, cgo性能低”
本来就不鼓励用这些东西,何苦纠结它,而且反射有些地方没办法比如用到json的,cgo如果不是必须依赖c库比如oracle,也别用就好了
“因为它是m:n的, 除了能够像协程那样 switch to + 可以轻易创建大量的 go程而不明显拖累性能, 以及只要不调用标准库函数, 那么大概率不会被其他go程抢占外(说是大概率, 是因为我也不确定go编译器会不会偷偷摸摸在代码中插入时间相关的go程切换代码, 反正fmt.Printf 中肯定存在时间片耗尽被切换走类似的逻辑), 其他的和线程没分别, 该上的锁一个也漏不掉。”
我觉得协程最大的好处是在大部分场景可以愉快地写同步代码,从callback hell中解放出来,锁,函数式编程或者单线程逻辑才可以避免可是这两种模型更2b
go提供简单特性和通用的编程模型,工程性要强得多
“话说一次面试时让用一读一写两个go程来读写链表, 面试官失望的说我写的和线程没区别”
不知道为啥会有那么多如此的面试官,我总是看不懂很多这种问题,面试官到底想问啥,他想实现的需求我都搞不懂
每次看到这种问题,我都觉得,它们(它在语文里指代禽兽)要么是为了装逼但自己语文都没学好,要么就是故意刁难人压工资
“重要的是, 库现在还幼稚的很; 你找一个 gmime 类似的邮件解析库给我看看先”
又不是每个人都写邮件相关,其他很多强大的库,至少比c/c++方便的多:luya:
去年写了好多nodejs,蛋疼,工程性比go差多了