免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123
最近访问板块 发新帖
楼主: vupiggy
打印 上一主题 下一主题

[C] switch-case 非常规用法拾零 (1. 绝无原创 2. 非常重视代码规范者勿入) [复制链接]

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
21 [报告]
发表于 2010-12-18 05:36 |只看该作者
先说coroutine的状态

我上面的帖说coroutine必须提供一个机制来区分ternimate和yield。
lua有多返回值, 而python除了多返回值, 还有异常。

可能没说清楚, 我再说具体一点。
1. 代码中确实有个错误, 在10次调用后
2. 不是说C语言就解决不了这个问题
C确实不支持多返回值, 但需要多返回值时, C肯定有迂回的办法:

  1. struct { T1 y1; T2 y2; } f(P x);
  2. void f(P x, T1* y1, T2* y2);
复制代码
就是ugly而已。
一般情况下, 我设计api时都会尽可能不使用传出参数, 但有时候真没办法。



再看启动函数
留意上面的
  1. coroutine_create( ..., void (*f)(void* x), void* x);
复制代码
结合
  1. pthread_create( ..., void* (*f)(void* x), void* x);
复制代码
这是C语言另一个问题: 没有一种参数类型可以直接代表任意"函数参数"。
当需要的时候, 上面就是一个典型的迂回方式。

注意伪代码中, rc4_stream是unsigned char rc4_stream(char const* key, size_t len);
而实际代码中, rc4_stream需要是void rc4_stream(void* x);
范化的解决办法就是:


  1. typedef struct
  2. {
  3.       char const* key;
  4.       size_t len;
  5. } rc4_arg_t;

  6. void rc4_stream(void* x)
  7. {
  8.       rc4_arg_t* arg = (rc4_arg_t*)x;
  9.       rc4_stream(arg->key, arg->len);
  10. }

  11. rc4_arg_t arg = { "1212", 4 };
  12. coroutine_create( ..., &arg);
复制代码
实际代码中只是取巧使用strlen来减少一个参数。
对更一般的例子, 就必须迂回一次。


最后看yield的返回值

yield返回什么?
为了让那几个coroutine的api更范化一点, 我选择和pthread相同的, 返回void*。
若需要的返回值比void*窄, 直接通过void* 的值返回。
否则返回一个指向结构体的指针 —— 对更复杂的例子, 就需要再如此这般的迂回一次, 运气不好还需要动态分配。

所有的这些加起来, 得到的结果就是在C中使用coroutine会非常麻烦, 能避免,就尽量避免。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
22 [报告]
发表于 2010-12-18 05:58 |只看该作者
本帖最后由 OwnWaterloo 于 2010-12-18 06:08 编辑

你告诉他好了~  顺便也告诉我"充其量"应该如何翻译……

原文我很早以前就看过。 当时对coroutine理解不深, 所以肯定看得不够仔细。
再看老文, 总是缺乏耐心的……

例子当然是需要简化的, 但不能把问题的关键给简化了。
1. 生成不同的coroutine实例
2. 简化脑力计算, 更自然的表达算法
否则, 脑力计算出挂起点和context, 其实不用coroutine也可以编程了。

所以, "从他列出的代码来看", 我的评价就是上面的, 只是让语法稍微好看一点。
简单的没必要用, 复杂的又用不上。
可能也就"中不溜秋"的应用可以玩一玩, 但朴质的写法也一定可以完成的。
至于维护性就不好说了。


你提到putty的实现代码通过传入context的指针完成以解决static(本质是多个不同coroutine实例)的问题。
能否演示一下?
希望就用上面那个lua和rc4的例子, 而putty可能相关上下文更多。
我就偷个懒, 不去深研他的原文啦~


PS: 上面的使用fiber的程序还存在一些问题。

因为rc4的例子很特殊, 是一个无限循环中不断yield, 不需要terminate的判断。
本来想再修改一下, 改为:

  1. unsigend char rc4_stream(char const* filename, char const* key, size_t len);
复制代码
每次产生一个byte的密文。
也有一个很正当的需求: 因为将rc4算法对密文再执行一次恰好就得到明文, 所以这其实是一个增量"解密"程序……
用户不需要完整的明文, 只需要前面一部分, 可以调用几次rc4_stream并夺回控制权, 根据所得明文看是否需要继续解密余下密文。

同时还可以演示将参数打包到一个void*; 判断coroutine状态这些问题 —— 能体现使用coroutine不如其他语言那么爽。

但是……  我想上面的例子应该能体现coroutine避免脑力计算了。
而且, 手确实很僵啊……   银魂在等待啊……   看银魂去了……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP