由于我们伟大的策划要求在游戏脚本中支持system.wait_second(20) 这样的功能,于是确定实现的方法成了一个需要解决的问题。众多前辈指出,使用LUA Coroutine可以达到我们的要求,可是我在LUA这块可以说是一窍不通,只好硬着头皮强上了。
听说《游戏编程精粹5》有一篇文章不错,我就把文章看了一遍,把光盘上的代码弄下来Compile,嘿,果然不错。
问题就这么轻松的解决了?NO!
我继续试验,从原代码的3个Coroutine增加到100个,程序马上就挂了,有各种奇怪的错误,什么stack overflow等等……
最关键的是,由lua_newthread出来的state奇怪的消失了。原来的创建代码如下:
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![InBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![ExpandedBlockEnd.gif](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
这里隐含着一个严重的Bug,lua_pushlightuserdata其实是一个很RAW的API,换句话说,它并不知道你push的是什么。表面上看来,threadState被放在了表里面,也就有了引用不会被自动回收,实际上表里面存的只是一个RAW c pointer!当LUA觉得需要GC的时候,可怜的threadState就被回收了,于是整个程序就crash了。
改起来很简单:
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![None.gif](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
原书代码中还有几处类似的错误,还有导致stack不平衡的代码,大家看《游戏编程精粹5》的时候,不可不信,不可全信啊。
另外,Coroutine好用,但是不是没有代价的,每次lua_newthread出来一个新的thread state,需要大约4K的内存消耗。客户端上没什么,在服务器端这是个需要权衡的地方。