免费注册 查看新帖 |

Chinaunix

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

[其他] 【(LUA相关)一个支持yield的server能避免掉轮询检查coroutine状态的命运吗?】 [复制链接]

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
71 [报告]
发表于 2013-02-24 23:41 |只看该作者
回复 68# linux_c_py_php


    我完全懂了………………


epoll的fd不是跟poll/select一样,是直接返回的?是epoll函数返回以后,遍历读事件列表/写事件列表/错误事件列表去依次处理有请求的fd?而是你自己搞了一个回调?

不是!不是做回调哥哥啊!!!

直接for循环那个事件列表,在循环里面根据fd查询对应coroutine,然后resume,跟回调没有半毛钱关系的!!

回调是你自己的框架搞得啊,coroutine完全不需要回调啊。

如果你坚持要回调,很简单:你做一个通用的回调,干下面的事情:

1. 根据fd查到coroutine
2. resume这个coroutine
3. 根据resume返回值爱咋地咋地

然后对所有事件都注册这唯一一个回调即可。

明白啦?

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
72 [报告]
发表于 2013-02-24 23:47 |只看该作者
回复 69# linux_c_py_php


    这种情况下,我直接说了吧。connect里面注册那个事件(你总得注册吧?)注册的时候userdata填lua_State*(就是那个coroutine的指针),回调函数是统一的,我写个代码你就明白了:

my_connect(fwk_handler, common_callback, L);


然后common_callback是这样的:

void common_callback(void *ud, ... /*datas*/) {
   lua_State *L = (lua_State*)ud;
   /* push datas */
   lua_resume(L, NULL, n);
   /* do any thing you want */
}

所有的异步事件(不止connect)全部使用这一个回调即可。

但是这样还是很绕,推荐你直接在epoll循环里面搞= =跟我上面说的一样= =
   

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
73 [报告]
发表于 2013-02-24 23:51 |只看该作者
starwing83 发表于 2013-02-24 23:41
回复 68# linux_c_py_php


不懂-,- 怎么感觉你说的lua把整个server的事情都干了...

我框架做的事情(2,3,4作为一个循环):

1, accept
2, read/write
3, parse request
4, call lua to handle the request

我要给lua提供的仅仅是一个叫做server:connect的api, 这个api不能阻塞connect吧, 于是我就自己写个callback给Epoll注册上然后就yield出去了, 啥时候resume回来呢? 等那个callback被Epoll回调的时候, 我在那个callback里就这么干:

lua_newuserdata:创建一个Socket对象, 里面存了连接成功的fd等.
lua_resume:恢复这个coroutine的执行, 同时传入Socket对象.

接下来发生了:

server:connect内部从yield返回, 得到了Socket对象, return返回给lua用户使用.


是我的框架不对吗- -, 我做的就这种屌事.

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
74 [报告]
发表于 2013-02-24 23:52 |只看该作者
starwing83 发表于 2013-02-24 23:47
回复 69# linux_c_py_php


这和我刚说的过程应该一样吧...

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
75 [报告]
发表于 2013-02-24 23:58 |只看该作者
本帖最后由 windoze 于 2013-02-25 00:01 编辑
linux_c_py_php 发表于 2013-02-24 23:51
我要给lua提供的仅仅是一个叫做server:connect的api, 这个api不能阻塞connect吧, 于是我就自己写个callback给Epoll注册上然后就yield出去了, 啥时候resume回来呢?

server::connect/read/write负责注册fd到epoll对应的fd set,句号,完了,木有回调
server有一个main loop,检查epoll是否有IO事件,如果有,做一次非阻塞的connect/read/write,然后选择发生IO事件对应的coroutine,调用resume,检查resume的返回值是LUA_OK还是LUA_YIELD,
如果是LUA_OK,那就说明这个connection不需要了,清理。
就酱

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
76 [报告]
发表于 2013-02-24 23:59 |只看该作者
回复 74# linux_c_py_php


    如果是回调,那就只有这样了。虽然是回调,但是大家干的事情都是一样的= =无论你的请求是什么。

在Lua层面回调转coroutine也是这么干的,用通用的回调干活。

luvit(http://luvit.io)是一个基于Lua的coroutine的框架,优势就在于= =可以不用回调= =(当然你可以用……)恩……

懂了吧?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
77 [报告]
发表于 2013-02-25 11:29 |只看该作者
本帖最后由 linux_c_py_php 于 2013-02-25 11:38 编辑

这个问题纠结于你到底是以C为主还是以LUA为主, luvit我看了是以LUA为主, 目的是仿node.js, 在思想上是有差别的, 不过两者都会遇到我说的这个问题, 我自己去看看它怎么在框架做到统一回调简化编程的吧.

1, 我是写C server, 然后开放lua api让用户处理请求, 我相当于nginx与nginx module的概念.

2, luvit是Lua server, 用户用纯lua语法就可以跑起一个server, 用户只要提供一个lua callback即可, 所以主程变成了lua, 即lua生命期就是server的生命期, 它会调用Listen, 然后底层就开始跑epoll了, 比如跑HTTP那个框架, Listen底层Epoll解析到一个http请求, 框架就会调用用户设置的callback来处理, 这个callback可能异步(比如发起连接其他server), 框架还是需要适时的resume回到lua脚本继续执行用户的未完的callback, 这个适时到底是怎么做到的, 我需要去读读它的代码, 这是我唯一关系的设计问题:
  1. local net = require('net')

  2. local server
  3. server = net.createServer(function (client)

  4.   -- Echo everything the client says back to itself
  5.   client:pipe(client)

  6.   -- Also log it to the server's stdout
  7.   client:pipe(process.stdout)

  8. end):listen(8080)

  9. print("TCP echo server listening on port 8080")
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP