LUA Coroutine

简介:

由于我们伟大的策划要求在游戏脚本中支持system.wait_second(20) 这样的功能,于是确定实现的方法成了一个需要解决的问题。众多前辈指出,使用LUA Coroutine可以达到我们的要求,可是我在LUA这块可以说是一窍不通,只好硬着头皮强上了。

听说《游戏编程精粹5》有一篇文章不错,我就把文章看了一遍,把光盘上的代码弄下来Compile,嘿,果然不错。

问题就这么轻松的解决了?NO!

我继续试验,从原代码的3个Coroutine增加到100个,程序马上就挂了,有各种奇怪的错误,什么stack overflow等等……

最关键的是,由lua_newthread出来的state奇怪的消失了。原来的创建代码如下:

LUASCRIPT::LUASCRIPT( LUAMANAGER*     mgr)
{
    manager             = mgr;
    state               = LSS_NOTLOADED;
    time             = 0;
    strcpy(lastErrorString, "No error.\n"); 

    // create a thread/state for this object
    threadState = lua_newthread(manager->masterState);
    // save a pointer to the thread manager object in the global table
    
// using the new thread's vm pointer as a key
    lua_pushlightuserdata(manager->masterState, threadState);
    lua_pushlightuserdata(manager->masterState, this );
    lua_settable(manager->masterState, LUA_GLOBALSINDEX );
}
 


这里隐含着一个严重的Bug,lua_pushlightuserdata其实是一个很RAW的API,换句话说,它并不知道你push的是什么。表面上看来,threadState被放在了表里面,也就有了引用不会被自动回收,实际上表里面存的只是一个RAW c pointer!当LUA觉得需要GC的时候,可怜的threadState就被回收了,于是整个程序就crash了。

改起来很简单:

     // lua_pushlightuserdata(manager->masterState, threadState);
    lua_pushthread(threadState);   // 换成这个
    lua_pushlightuserdata(manager->masterState,  this );
    lua_settable(manager->masterState, LUA_GLOBALSINDEX ); 

原书代码中还有几处类似的错误,还有导致stack不平衡的代码,大家看《游戏编程精粹5》的时候,不可不信,不可全信啊。

另外,Coroutine好用,但是不是没有代价的,每次lua_newthread出来一个新的thread state,需要大约4K的内存消耗。客户端上没什么,在服务器端这是个需要权衡的地方。

目录
相关文章
|
应用服务中间件
LUA 协程 Coroutine
协程 Coroutine 协程(coroutine)并不是 Lua 独有的概念,如果让我用一句话概括,那么大概就是:一种能够在运行途中主动中断,并且能够从中断处恢复运行的特殊函数。(嗯,其实不是函数。
2551 0
|
7月前
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
254 1
|
6月前
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
230 0
|
2月前
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
31 2
|
3月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
4月前
|
存储 NoSQL Redis
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
|
6月前
|
JSON 监控 数据格式
使用Lua代码扩展上网行为管理软件的脚本功能
本文介绍了如何使用Lua脚本增强上网行为管理,包括过滤URL、记录用户访问日志、控制带宽和自动提交监控数据到网站。Lua是一种轻量级语言,适合编写扩展脚本。文中提供多个示例代码,如URL过滤器、用户活动日志记录器和带宽控制器,帮助用户根据需求定制网络管理功能。通过这些示例,用户可以快速掌握Lua在上网行为管理中的应用。
177 4