免费注册 查看新帖 |

Chinaunix

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

[其他] 【(LUA相关)一个支持yield的server能避免掉轮询检查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
11 [报告]
发表于 2013-02-24 17:40 |只看该作者
本帖最后由 linux_c_py_php 于 2013-02-24 17:42 编辑

嗯, 我理解你的意思, 就是coroutine对于我来说, 我是明确知道哪时候开始哪时候结束的.

我知道coroutine的道理, 包括怎么实现来lua看来阻塞在宿主看来异步的接口, 但要做一个通用漂亮的设计, 在实现的每个lua函数里都考虑检查coroutine是否结束感觉是蛋疼的做法.

我说个实际的例子, 我是一个单线程epoll, 然后解析到一个request, 然后创建coroutine加载lua代码执行, 然后lua里调用了我实现的connect函数, connect里注册了非阻塞connect fd的事件后就yield了, 然后宿主获得了执行权, 但发现resume返回YIELD而不是OK, 说明LUA还没执行完, 所以宿主不等待继续event loop干其他的, 然后等非阻塞connect fd触发完成事件, 在其事件回调里resume coroutine继续执行lua脚本, 然后lua脚本又调用write/read等接口, 其底层都是借助event loop异步的, 而实现read/write的时候是都和检查connect里resume返回值一样, 重复的去判断resume返回OK还是YIELD.

当这个resume返回值的检查在每个API的实现里都必须出现的时候, 我觉得就需要一个通用的办法来让宿主获知coroutine的执行状况, 比如通过管道通知到event loop触发server的状态机推进到等待下一个request, 或者服务端轮询来获知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
12 [报告]
发表于 2013-02-24 17:46 |只看该作者
本帖最后由 linux_c_py_php 于 2013-02-24 17:54 编辑
linux_c_py_php 发表于 2013-02-24 17:40
嗯, 我理解你的意思, 就是coroutine对于我来说, 我是明确知道哪时候开始哪时候结束的.

我知道coroutine的 ...


我想说的是, 并不是每个api的底层实现都想关注coroutine是否结束, 它们仅仅想让coroutine按照自己的api设计继续resume而已, 至于resume返回的coroutine是死是活(是return了还是yield了, 对于connect api来说不重要了, 我已经把connection相关的userdata resume与结果resume给lua了, lua继续怎么去玩与connect没关系了, connect的底层实现干嘛要关心resume的返回值呢), 与api设计根本没关系, 谁知道lua脚本调用完我的API还会调用谁的API做什么事情.

这就是我对这个观点的一个思考, 纠结的地方, 不是说不会, 只是想知道面对这个与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
13 [报告]
发表于 2013-02-24 17:48 |只看该作者
本帖最后由 linux_c_py_php 于 2013-02-24 17:50 编辑
linux_c_py_php 发表于 2013-02-24 17:46
我想说的是, 并不是每个api的底层实现都想关注coroutine是否结束, 它们仅仅想让coroutine按照自己的api ...


所以我说让event loop来轮询是一个对api开发者非常透明的方案, api_1的开发者只需要做自己的底层实现, 至于完成了api_1的任务接下来coroutine是死是活, api_1根本不需要关心, 我想表达的是这个理念...

不知道我是否进入了什么理解误区.

论坛徽章:
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
14 [报告]
发表于 2013-02-24 18:18 |只看该作者
就拿GUI那段代码来问一下, wait和redraw都是底层异步的, 会使用到yield, 那么你在实现这两个接口的时候, 是否需要在每个接口内部resume的返回值处做判断coroutine是否结束, 并且如果结束就从注册表里取来main thread, 从中清理掉coroutine呢? 如果不这样做, 也就没有机会判定coroutine结束了吧. 所以这个责任落到了每个api实现之内, GUI方面都是这样做的吗?

论坛徽章:
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
15 [报告]
发表于 2013-02-24 18:26 |只看该作者
linux_c_py_php 发表于 2013-02-24 18:18
就拿GUI那段代码来问一下, wait和redraw都是底层异步的, 会使用到yield, 那么你在实现这两个接口的时候, 是 ...




@starwing83 速速来救... 直接说一下GUI里这一点是否是这样做的: 就是每个接口在resume后都要做OK/YIELD的检测, 如果OK那么说明coroutine结束, 该API需要负责清理相关变量的状态以及垃圾回收该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
16 [报告]
发表于 2013-02-24 18:32 |只看该作者
回复 14# linux_c_py_php


    先说几个通用策略吧。

1. 如果你想要实现的逻辑是“如果没有coroutine存在,那么main loop退出”,一个注册表就能完成。
2. lua_resume的调用成本,取决于你到底想做什么,事实上lua_resume的调用和lua_pcall一模一样——你管他yield不yield,因为阻塞函数本身就已经注册信息(或者没有注册信息,有什么关系呢?),resume以后直接返回事件循环即可。如果想知道事件循环什么时候退出,参见1
3. 可能你会想问,我想做些高级特性, 比如在coroutine上面pcall里面再resume(resume内部的代码如果error,会导致这个coroutine整体不可用),提供stack dump等等功能,我的看法,是包装一个,比如说,framework_resume的这样的函数做所有的繁杂事情,然后其他的接口直接调用这个函数。举个例子,其实pcall是很复杂的,需要推入traceback,还需要从object的userdata中解析出回调函数名等等,所以在我的gui框架里面,我有一个lga_self函数,这个函数负责处理好所有的pcall细节,然后我push所有参数,直接pcall即可。
4. 如果你真的觉得麻烦了,我可以告诉你:直接给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
17 [报告]
发表于 2013-02-24 18:46 |只看该作者
1. 如果你想要实现的逻辑是“如果没有coroutine存在,那么main loop退出”,一个注册表就能完成。

  这一句是什么意思呢.

论坛徽章:
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
18 [报告]
发表于 2013-02-24 18:47 |只看该作者
本帖最后由 linux_c_py_php 于 2013-02-24 18:54 编辑
linux_c_py_php 发表于 2013-02-24 18:46
1. 如果你想要实现的逻辑是“如果没有coroutine存在,那么main loop退出”,一个注册表就能完成。

  这一 ...


你的意思是你全局只有一个lua_State, 然后有全局唯一的table记录各个连接的状态,  各个连接是Userdata, 然后使用lightuserdata作为key索引table保存真正的userdata, 然后每个  coroutine也保存到table对应的连接之下, 从而保持全局唯一的lua_State的栈是干净管理的。

论坛徽章:
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
19 [报告]
发表于 2013-02-24 18:47 |只看该作者
回复 17# linux_c_py_php


    你可以做一个表(lua_newtable),有一个coroutine,就放里面一个,每次事件之前检查这个表是不是空(检查lua_next调用返回的值),如果是空证明不再需要继续执行了。

论坛徽章:
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
20 [报告]
发表于 2013-02-24 18:49 |只看该作者
1. 如果你想要实现的逻辑是“如果没有coroutine存在,那么main loop退出”,一个注册表就能完成。
2. lua_resume的调用成本,取决于你到底想做什么,事实上lua_resume的调用和lua_pcall一模一样——你管他yield不yield,因为阻塞函数本身就已经注册信息(或者没有注册信息,有什么关系呢?),resume以后直接返回事件循环即可。如果想知道事件循环什么时候退出,参见1



标红部分, 我现在就是想让框架及时的知道coroutine完了没有, 你没完我没法处理下一个请求啊, 就像GUI, 你这次对窗口A的处理没结束的时候又触发事件想让A动是不对的啊, 我总得知道lua脚本哪时候结束的, 这个事件对我很重要。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP