文档章节

利用Lua协程实现Future模式

follitude
 follitude
发布于 2016/09/17 12:04
字数 850
阅读 43
收藏 1

1. Future模式:

参见http://www.cnblogs.com/zhiranok/archive/2011/03/26/Future_Pattern.html

使用future的好处是即利用了异步的并行能力,又保证主逻辑串行执行,保持简单。

2. Lua 协程

sina Timyang 的介绍 http://timyang.net/lua/lua-coroutine/

lua coroutine 通过create创建一个伪线程,该“线程”通过yield可以挂起自己,通过调用resume可以使该“线程”从挂起位置继续执行。

3. Lua coroutine 实现 Future

假设有如下应用场景:

1. 用户登录系统,需要将用户数据从Mysql中获取用户数据,然后在Lua中实例化user_t对象。

2. 用户登录事件由C++触发,将uid参数传递给lua

3. lua 并不存在mysql接口,必须委托c++完成mysql操作,而且Lua state必须被单线程操作,故我们期望Lua不能被阻塞,在单个user从mysql 载入数据时其他user应该能够继续接受请求

我们设计了如下解决方案:

1. lua中的user_t对象每个实例拥有两个主要数据,

 a. request_cache,在user未初始化完成时该uid的请求将被缓存起来(我们将请求封装成function)。

    b. coroutine ,该协程尝试将request_cache中的所有请求执行完毕,当出现如下情况该协程将挂起自己

    (1)request_cache 为空,挂起等待新的请求

    (2)需要执行mysql时挂起,等待mysql执行完毕被唤醒。

示例代码:

     

复制代码

1 user_t = {}
 2 user_t.__index = user_t
 3 
 4 function user_t:new()
 5     local funjc = function() print("TODO exe all request in request_cache") end
 6     local ret =
 7     {
 8         ["request_cache"] = {},
 9         ["coroutine_obj"] = coroutine.create(funjc),
10     }
11     setmetatable(ret, self)
12     return ret
13 end

复制代码

 

2. C++ 封装异步调用Mysql的接口,注册接口到Lua

1. future_t 用于LUA和C++传递数据

复制代码

1 class future_t
2 {
3 public:
    void   set_result(const string& v_) { m_result = v_;   }
4     string get_result() const           { return m_result; }
5 private:
6     string m_result;
7 };

复制代码

2. async_load_data_from_db 用于异步执行mysql操作

复制代码

1 void async_load_data_from_db(future_t* ret_)
 2 {
 3     //! post another thread, async exe load data from db
 4     thread.post(boost::bind(do_load_data_from_db, ret_));    
 5 }
 6 
 7 void do_load_data_from_db(future_t* ret_)
 8 {
 9     //! TODO exe sql opertion
10     lua_pcall("resume_routine")
11 }

复制代码

 

lua 调用C++的接口async_load_data_from_db,async_load_data_from_db 将请求post另外的线程,执行mysql请求,将请求结果赋值到future中,调用lua的resume函数唤醒
lua协程继续执行

3. Lua 示例代码

复制代码

1 user_t = {}
 2 user_t.__index = user_t
 3 
 4 function user_t:new(uid_)
 5     local ret =
 6     {
 7         ["uid"]              = uid_,
 8         ["request_cache"] = {},
 9         ["coroutine_obj"] = true,
10         ["runing_flag"]      = true,
11     }
12     setmetatable(ret, self)
13 
14     local func = function()
15         while true == runing_flag do
16             if 0 == #ret.request_cache
17             then
18                 coroutine.yield()
19             else
20                 local todo_func = ret.request_cache[1]
21                 local tmp = {}
22                 for k = 2, #ret.request_cache
23                 do
24                     table.insert(tmp, ret.request_cache[k])
25                 end
26                 ret.request_cache = tmp
27                 todo_func()
28             end
29         end
30     end
31     ret.coroutine_obj = coroutine.create(func)
32     return ret
33 end
34 
35 function user_t:init()
36     local func = function()
37         local future = future_t:new()
38         async_load_data_from_db(future)
39         coroutine.yield()
40         print("user_t:init ok", self.uid, future:get_result())
41         future:delete()
42     end
43     table.insert(self.request_cache, func)
44     coroutine.resume(self.coroutine_obj)
45 end
46 
47 function user_t:resume_routine()
48     coroutine.resume(self.coroutine_obj)
49 end
50 
51 local test_user = user_t:new(1122334)
52 
53 function user_login()
54     return test_user:init()
55 end
56 
57 function resume_routine()
58     return test_user:resume_routine()
59 end

复制代码

4. 注意事项:

尽管一个Lua state是串行执行的,使用Lua coroutine时仍然要注意数据一致性,比如在coroutine执行时使用了全局变量,yield挂起后全局变量有可能被修改了,

所以协程适合于例子中的user_t对象,各个user是互不干扰的,相同的user请求会被单个协程串行化。

本文转载自:http://www.cnblogs.com/zhiranok/archive/2012/02/04/lua_coroutine_future.html

follitude
粉丝 6
博文 118
码字总数 4956
作品 0
浦东
私信 提问
利用LUA协程实现FUTURE模式

1. Future模式: 参见http://www.cnblogs.com/zhiranok/archive/2011/03/26/Future_Pattern.html 使用future的好处是即利用了异步的并行能力,又保证主逻辑串行执行,保持简单。 2. Lua 协程...

晨曦之光
2012/06/07
714
0
go语言之并发

简介 多核处理器越来越普及,那有没有一种简单的办法,能够让我们写的软件释放多核的威力?答案是:Yes。随着Golang, Erlang, Scale等为并发设计的程序语言的兴起,新的并发模式逐渐清晰。正...

黑神领主
2016/12/10
110
0
Lua 协程coroutine

  协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程。 协程是用户空间线程,操...

jeffjade
2014/11/24
0
0
OpenResty 最佳实践 (1)

此文已由作者汤晓静授权网易云社区发布。 欢迎访问网易云社区,了解更多网易技术产品运营经验。 OpenResty 发展起源 OpenResty(也称为 ngx_openresty)是一个全功能的 Web 应用服务器。它打包...

网易云
2018/10/31
0
0
Lua Web快速开发指南(9) - 使用cf内置的异步库

API 介绍 cf框架提供内置的异步库, 需要使用的时候我们必须先导入API: . 定时器与循环定时器 cf库内置了一些定时器方法, 这些方法为开发者提供了对时间事件的控制能力. 、、. 方法是一个的定...

水果糖的小铺子
06/23
18
0

没有更多内容

加载失败,请刷新页面

加载更多

【2019年8月版本】OCP 071认证考试最新版本的考试原题-第5题

choose the best answer The CUSTOMERS table has a CUST_LAST_NAME column of data type VARCHAR2. The table has two rows whose COST_LAST_MANE values are Anderson and Ausson. Which q......

oschina_5359
22分钟前
2
0
电脑怎样制作流程图?分享绘制流程图方法

流程图的绘制可以用很多方法来实现,小编经常使用电脑对流程图进行绘制,即简单又便利,相信很多朋友都因为不知道怎样绘制流程图而选择了放弃,今天这篇文章希望可以让大家重拾绘制流程图的信...

干货趣分享
24分钟前
2
0
Elasticsearch 7.x 之文档、索引和 REST API 【基础入门篇】

前几天写过一篇《Elasticsearch 7.x 最详细安装及配置》,今天继续最新版基础入门内容。这一篇简单总结了 Elasticsearch 7.x 之文档、索引和 REST API。 什么是文档 文档Unique ID 文档元数据...

泥瓦匠BYSocket
28分钟前
2
0
TL665x-EasyEVM开发板处理器、flash、RAM

TL665x-EasyEVM是广州创龙基于SOM-TL665x核心板研发的一款TI C66x多核定点/浮点高性能DSP开发板,采用核心板+底板方式,底板尺寸为200mm*106.65mm,采用4*50pin和1*80pin B2B工业级连接器,稳...

Tronlong创龙
32分钟前
2
0
DevExpress Report-XRTable绑定数据

将从跳转前的页面(A)中获取传入的数据(dtOrd、BatchID、ModelID),绑定到Report报表对应的控件 ,代码如下: this.xrtBatchID.Text = sBatchID; this.xrtModel.Text ...

_Somuns
33分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部