+关注继续查看

协程 Coroutine

举个最原始的例子：

function greet()
print "hello world"
end

co = coroutine.create(greet) -- 创建 coroutine

print(coroutine.status(co))  -- 输出 suspended
print(coroutine.resume(co))  -- 输出 hello world
-- 输出 true (resume 的返回值)
print(coroutine.resume(co))  -- 输出 false    cannot resume dead coroutine (resume 的返回值)


函数 coroutine.yield(...)

OK，总结一下：当 co = coroutine.create(f) 时，yield 和 resume 的关系如下图：

How coroutine makes life easier

传统做法

-- 每帧的逻辑
function Monster:frame()
self:state_func()
self.state_frame_count = self.state_frame_count + 1
end

-- 切换状态
function Monster:set_next_state(state)
self.state_func = state
self.state_frame_count = 0
end

-- 首先向右走 30 帧
function Monster:state_walk_1()
local frame = self.state_frame_count
self:walk(DIRECTION_RIGHT)
if frame > 30 then
self:set_next_state(state_wait_for_player)
end
end

-- 等待玩家进入视野
function Monster:state_wait_for_player()
if self:get_distance(player) < self.range then
self.direction = -self:get_direction_to(player)
self:set_next_state(state_walk_2)
end
end

-- 向反方向走 15 帧
function Monster:state_walk_2()
local frame = self.state_frame_count;
self:walk(self.direction)
if frame > 15 then
self:set_next_state(state_wait_for_player)
end
end


协程做法

-- 每帧的逻辑
function Monster:frame()
-- 首先向右走 30 帧
for i = 1, 30 do
self:walk(DIRECTION_RIGHT)
self:wait()
end

while true do
-- 等待玩家进入视野
while self:get_distance(player) >= self.range do
self:wait()
end

-- 向反方向走 15 帧
self.direction = -self:get_direction_to(player)
for i = 1, 15 do
self:walk(self.direction)
self:wait()
end
end
end

-- 该帧结束
function Monster:wait()
coroutine.yield()
end


Lua 把关于协程的所有函数放在一个名为 “coroutine” 的 table 里，coroutine 里具有以下几个内置函数：

-coroutine-yield [function: builtin#34]
|         -wrap [function: builtin#37]
|         -status [function: builtin#31]
|         -resume [function: builtin#35]
|         -running [function: builtin#32]
|         -create [function: builtin#33]


coroutine.create - 创建协程

co = coroutine.create(function()
io.write("coroutine create!\n")
end)
print(co)


coroutine.status - 查看协程状态

print(coroutine.status(co))


coroutine.resume - 执行协程

coroutine.resume(co)


co = coroutine.create(function(a, b, c)
print("co", a, b, c)
end)
coroutine.resume(co, 1, 2, 3)


co = coroutine.create(function()
return 3, 4
end)
print(coroutine.resume(co))


coroutine.yield - 中断协程运行

coroutine.yield 函数可以让一个运行中的协程中断挂起

co = coroutine.create(function()
for i = 1, 3 do
print("before coroutine yield", i)
coroutine.yield()
print("after coroutine yield", i)
end
end)
coroutine.resume(co)


coroutine.resume(co)

resume 执行完协程主函数或者中途被挂起（yield）时，会有返回值返回，第一个值是 true，表示执行没有错误。如果是被 yield 挂起暂停，yield 函数有参数传入的话，这些参数会接着第一个值后面一并返回

co = coroutine.create(function(a, b, c)
coroutine.yield(a, b, c)
end)
print(coroutine.resume(co, 1, 2, 3))


以 coroutine.wrap 的方式创建协程

function wrap(param)
print("Before yield", param)
obtain = coroutine.yield()
print("After yield", obtain)
return 3
end
resumer = coroutine.wrap(wrap)

print(resumer(1))

print(resumer(2))


coroutine.running - 返回正在运行中的协程

print(coroutine.running())

co = coroutine.create(function()
print(coroutine.running())
print(coroutine.running() == co)
end)
coroutine.resume(co)

print(coroutine.running())


resume-yield 交互

function receive(prod)
local status, value = coroutine.resume(prod)
return value
end

function send(x)
coroutine.yield(x)
end

function producer()
return coroutine.create(function()
while true do
send(x)
end
end)
end

function filter(prod)
return coroutine.create(function()
--      for line = 1, math.huge do
for line = 1, 5 do
x = string.format("%5d Enter is %s", line, x)
send(x)
end
end)
end

function consumer(prod)
--  repeat
--      print(type(x))
--      if x then
--          io.write(x, "\n")
--      end
--  until x == nil
while true do
if obtain then
io.write(obtain, "\n\n")
else
break
end
end
end

p = producer()
f = filter(p)
consumer(f)


|
19天前
|

【实战】使用Lua脚本怎么清理redis中的数据【实战】使用Lua脚本怎么清理redis中的数据

15 0
|
20天前
|
C# Python
[√]lua 协程
[√]lua 协程
22 1
|
7月前
Lua笔记协程
Lua笔记协程
35 0
|
Java API
|

Lua 协程coroutine
协程和一般多线程的区别是，一般多线程由系统决定该哪个线程执行，是抢占式的，而协程是由每个线程自己决定自己什么时候不执行，并把执行权主动交给下一个线程。 协程是用户空间线程，操作系统其存在一无所知，所以需要用户自己去做调度，用来执行协作式多任务非常合适。
1427 0
Lua中的协同程序 coroutine
Lua中的协程和多线程很相似，每一个协程有自己的堆栈，自己的局部变量，可以通过yield-resume实现在协程间的切换。不同之处是：Lua协程是非抢占式的多线程，必须手动在不同的协程间切换，且同一时刻只能有一个协程在运行。
854 0