lua coroutine
Lua中协程都放在表coroutine中。
Lua协程的四个状态
- 挂起(suspended):一个协程被创建的时候,处于挂起状态,不会自动运行。
- 运行(running):coroutine.resume()用于启动或者再次启动一个协程,使其变成运行状态。
- 正常(normal):协程A唤醒协程B的时候,协程B处于运行状态,协程A就处于正常状态。
- 死亡(dead):协程中包含的函数执行完毕,协程就变成了死亡状态。
Lua协程的操作函数:
创建协程:coroutine.create(func)
该函数接受一个函数作为参数,返回一个thread类型的值。
例如:
local co = coroutine.create(function() print("hello") end)
print(type(co))
输出:
thread
启动协程:coroutine.resume(co, arg1, arg2, ...)
参数:可以分为两种情况。
1.协程中不包含yield():第一个参数是被启动的协程,后面的参数传递给协程封装的函数作为参数。
例如:
local co = coroutine.create(
function(a, b)
print("a + b =", a + b)
end
)
coroutine.resume(co, 1, 2)
输出:
a + b = 3
2.协程中包含yield():第一个参数还是被启动的线程,在首次调用resume时,后面的参数传递给协程封装的函数作为参数;而再次调用(非首次)resume()时,后面的参数将作为yield()的返回值。
例如:
local co = coroutine.create(
function(x)
print("co1", x)
print("co2", coroutine.yield())
end
)
coroutine.resume(co, "hello")
coroutine.resume(co, "world")
输出:
co1 hello
co2 world
返回值:分为三种情况。
1.协程没有结束,resume()第一个返回值是true,后面的返回值是yield(...)中的参数。
2.协程结束时,resume()第一个返回值是true,后面的返回值是协程中函数的返回值。
3.协程结束后,此时不应该继续调用resume,如果调用了,resume()第一个返回值是false,表示调用失败,第二个返回值是报错信息。
例如:
local co = coroutine.create(
function()
coroutine.yield("hello", "world")
return "hello", "lua"
end
)
print(coroutine.resume(co))
print(coroutine.resume(co))
print(coroutine.resume(co))
输出:
true hello world
true hello lua
false cannot resume dead coroutine
值得注意的是,resume运行在保护模式中,如果协程在执行过程中遇到了错误,Lua不会打印错误信息,而是把错误信息作为resume()的返回值。
挂起协程:coroutine.yield(arg1, arg2, ...)
参数:yield()将作为本次唤醒协程的resume()的返回值。
返回值:下次唤醒协程的resume()的参数,将作为yield()的返回值。
例如:
local co = coroutine.create(
function()
local ret = coroutine.yield("hello")
print(ret)
end
)
local state, ret = coroutine.resume(co)
print(state)
print(ret)
coroutine.resume(co, "world")
输出:
true
hello
world
Lua协程的特点
Lua协程是一种非对称协程(asymmetric coroutine),需要两个函数来控制协程的执行,一个用于挂起协程,一个用于恢复协程。
相对于其他语言提供的对称协程(symmetric coroutine),只提供一个函数用于切换不同协程之间的控制权。
Lua协程的一些应用
1.生产者消费者问题:
1.消费者驱动型
-- 消费者驱动型 consumer-driven
producer_co = coroutine.create(
function()
for i = 1, 5 do
print("produce:", i)
coroutine.yield(i)
end
end
)
function consumer()
while true do
local status, value = coroutine.resume(producer_co)
print("producer:", coroutine.status(producer_co))
if not value then
break
end
print("consume:", value)
end
end
consumer()
输出:
produce: 1
producer: suspended
consume: 1
produce: 2
producer: suspended
consume: 2
produce: 3
producer: suspended
consume: 3
produce: 4
producer: suspended
consume: 4
produce: 5
producer: suspended
consume: 5
producer: dead
2.生产者驱动型
-- 生产者驱动型 producer-driven
function producer()
for i = 1, 5 do
print("produce:", i)
coroutine.resume(consumer_co, i)
print("consumer:", coroutine.status(consumer_co))
end
coroutine.resume(consumer_co)
end
consumer_co = coroutine.create(
function(x)
while true do
print("consume:", x)
x = coroutine.yield()
if not x then
break
end
end
end
)
producer()
print("consumer:", coroutine.status(consumer_co))
输出:
produce: 1
consume: 1
consumer: suspended
produce: 2
consume: 2
consumer: suspended
produce: 3
consume: 3
consumer: suspended
produce: 4
consume: 4
consumer: suspended
produce: 5
consume: 5
consumer: suspended
consumer: dead
2.将协程用作迭代器:
-- 产生全排列的迭代器
function permutation_gen(a, n)
n = n or #a
if n < 1 then
coroutine.yield(a)
else
for i = 1, n do
a[n], a[i] = a[i], a[n]
permutation_gen(a, n - 1)
a[n], a[i] = a[i], a[n]
end
end
end
function permutations(a)
local co = coroutine.create(function() permutation_gen(a) end)
return function()
local code, res = coroutine.resume(co)
return res
end
end
function permutations_wrap(a)
return coroutine.wrap(function() permutation_gen(a) end)
end
for p in permutations({1, 2, 3}) do
for i = 1, #p do io.write(p[i], " ") end
io.write("\n")
end
print("----")
for p in permutations_wrap({1, 2, 3}) do
for i = 1, #p do io.write(p[i], " ") end
io.write("\n")
end
输出:
2 3 1
3 2 1
3 1 2
1 3 2
2 1 3
1 2 3
----
2 3 1
3 2 1
3 1 2
1 3 2
2 1 3
1 2 3
其中coroutine.warp(func)方法就是创建一个封装func的协程,然后返回一个调用该协程的函数。
lua coroutine的更多相关文章
- Lua Coroutine详解
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程 ...
- 【转】Lua coroutine 不一样的多线程编程思路
Lua coroutine 不一样的多线程编程思路 Sunday, Apr 26th, 2009 by Tim | Tags: coroutine, Lua 上周末开始看<Lua程序设计> ...
- lua coroutine for iterator
背景 前面的文章演示了使用闭包函数实现 状态的迭代器. 本文演示使用 coroutine来产生迭代器的例子. coroutine迭代器例子 -- 遍历二叉树 local binary_tree = { ...
- 生成lua的静态库.动态库.lua.exe和luac.exe
前些日子准备学习下关于lua coroutine更为强大的功能,然而发现根据lua 5.1.4版本来运行一段代码的话也会导致 "lua: attempt to yield across me ...
- 理解 Lua 的那些坑爹特性
按:最近看到了依云的文章,一方面,为Lua被人误解而感到十分难过,另一方面,也为我的好友, 依云没有能够体会到Lua的绝妙和优雅之处而感到很遗憾,因此我写了这篇文章,逐条款地说明了 依云理解中出现的一 ...
- C/C++ Lua Parsing Engine
catalog . Lua语言简介 . 使用 Lua 编写可嵌入式脚本 . VS2010编译Lua . 嵌入和扩展: C/C++中执行Lua脚本 . 将C++函数导出到Lua引擎中: 在Lua脚本中执 ...
- 跨平台高效率Lua网络库 ( 同步形式的API ,底层是异步非阻塞)
Joynet 项目地址:https://github.com/IronsDu/Joynet 介绍 high performance network library for lua, based on ...
- Openresty Lua协程调度机制
写在前面 OpenResty(后面简称:OR)是一个基于Nginx和Lua的高性能Web平台,它内部集成大量的Lua API以及第三方模块,可以利用它快速搭建支持高并发.极具动态性和扩展性的Web应用 ...
- Lua协程的一个例子
很久没记录笔记了,还是养成不了记录的习惯 下面是来自 programming in lua的一个协程的例(生产者与用户的例子) 帖代码,慢慢理解 -- Programming in Lua Corou ...
随机推荐
- 使用mongo shell和客户端连接至MongoDB Atlas
MongoDB Atlas是Mongo官方的一个集群服务,也可以注册并创建一个免费的集群,但DB的大小只有500M,如果数据量不是很大的应用,可以选择该集群方案 需要注意的是,目前我使用的这个集群,服 ...
- CSS3盒模型——box-sizing
box-sizing盒模型是CSS3的一个重要属性之一,常常被很多人给忽略了!CSS3出现之前box-sizing盒模型默认的宽高是指内容的宽高,css3之后可以用box-sizing来指定宽高. 目 ...
- 一个Apache安装多个版本的PHP
我的服务器centos6.5安装了xampp,php6.5版本的.已经有好几个网站在上面运行了,但是后面要安装该死的ecshop,无奈要装php5.2,因此就想如何能在一个apache上安装多个版本的 ...
- 转:攻击JavaWeb应用[1]-javaEE基础
http://www.cnblogs.com/oh3o/p/3224562.html JSP: 全名为java server page,其根本是一个简化的Servlet. Servlet:Servle ...
- Flume学习应用:Java写日志数据到MongoDB
概述 Windows平台:Java写日志到Flume,Flume最终把日志写到MongoDB. 系统环境 操作系统:win7 64 JDK:1.6.0_43 资源下载 Maven:3.3.3下载.安装 ...
- NGUI的异步场景加载进度条
1.直接创建三个场景,其中第二个场景是用来显示进度条加载的界面,进度条用UISlider,不会的看我前面的博文就可以了. 2.这里提供两种方法,建议使用第一种,加载比较平缓 方法一: using Sy ...
- ALL运算符
ALL在英文中的意思是“所有”,ALL运算符要求比较的值需要匹配子查询中的所有值.ALL运算符同样不能单独使用,必须和比较运算符共同使用. 下面的SQL语句用来检索在所有会员入会之前出版的图书: SE ...
- 2017icpc 乌鲁木齐网络赛
A .Banana Bananas are the favoured food of monkeys. In the forest, there is a Banana Company that pr ...
- 【DFS】佳佳的魔法阵
[vijos1284]佳佳的魔法阵 背景 也许是为了捕捉猎物(捕捉MM?),也许是因为其它原因,总之,佳佳准备设计一个魔法阵.而设计魔法阵涉及到的最关键问题,似乎就是那些带有魔力的宝石的摆放…… 描述 ...
- 【Heap-dijkstra】CDOJ1639 云中谁寄锦书来?雁字回时,月满西楼。
题意: 在n个点m条边的无向图上,有k个出口 从起点出发,每到一个点(包括起点),该点连出的边中有d条会被封锁 求最坏情况下到达出口的最短路 题解: 该题为dijkstra算法的拓展 由于求最坏情况下 ...