Latest web development tutorials

Lua coroutines (coroutine)

What is a synergistic (coroutine)?

Lua coroutines (coroutine) Thread relatively similar: an independent stack, local variables separate, independent instruction pointer, but also shared global variables, and most other things and other collaborative programs.

Synergy is very powerful, but also very complicated to use.

The difference between threads and coroutines

The main difference between threads and coroutines that a program has multiple threads can run several threads simultaneously, while cooperative program would need about another collaboration.

At any given time there is only one cooperative program is running, and the running coroutine only be required to clear the suspended time will be suspended.

Collaborative program somewhat similar to synchronize multiple threads in the same thread waiting for the lock several threads somewhat similar collaboration.

The basic syntax

method description
coroutine.create () Create a coroutine, return coroutine, argument is a function, when used in conjunction with, and resume when the wake-up function calls
coroutine.resume () Restart coroutine, and create with the use of
coroutine.yield () Suspended coroutine, the coroutine to pending state and resume with the use of this to have a lot of useful effect
coroutine.status () Check the status of coroutine NOTE: coroutine state, there are three: dead, suspend, running, particularly when there is such a state, please refer to the following procedures
coroutine.wrap () Create a coroutine, returns a function that once you call this function, enter coroutine, and create repeat function
coroutine.running () Returns are running coroutine, a coroutine is a thread, when running when the thread is to return a number of corouting

The following example demonstrates the use of each of the above methods:

-- coroutine_test.lua 文件
co = coroutine.create(
    function(i)
        print(i);
    end
)
 
coroutine.resume(co, 1)   -- 1
print(coroutine.status(co))  -- dead
 
print("----------")
 
co = coroutine.wrap(
    function(i)
        print(i);
    end
)
 
co(1)
 
print("----------")
 
co2 = coroutine.create(
    function()
        for i=1,10 do
            print(i)
            if i == 3 then
                print(coroutine.status(co2))  --running
                print(coroutine.running()) --thread:XXXXXX
            end
            coroutine.yield()
        end
    end
)
 
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
 
print(coroutine.status(co2))   -- suspended
print(coroutine.running())
 
print("----------")

Examples of the implementation of the above output is:

1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868	false
suspended
thread: 0x7fb801c04c88	true
----------

coroutine.running can be seen, coroutine implementation is a thread at the bottom.

When create a coroutine when an event is registered in the new thread.

When a resume event is triggered when, create a coroutine function is executed, and when faced with the yield on behalf suspends the current thread to wait again resume triggering event.

Next, we analyze a more detailed example:

function foo (a)
    print("foo 函数输出", a)
    return coroutine.yield(2 * a) -- 返回  2*a 的值
end
 
co = coroutine.create(function (a , b)
    print("第一次协同程序执行输出", a, b) -- co-body 1 10
    local r = foo(a + 1)
     
    print("第二次协同程序执行输出", r)
    local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入
     
    print("第三次协同程序执行输出", r, s)
    return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
end)
        
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

Examples of the implementation of the above output is:

第一次协同程序执行输出	1	10
foo 函数输出	2
main	true	4
--分割线----
第二次协同程序执行输出	r
main	true	11	-9
---分割线---
第三次协同程序执行输出	x	y
main	true	10	结束协同程序
---分割线---
main	false	cannot resume dead coroutine
---分割线---

Examples took over as follows:

  • Call resume, will coordinate wakeup, resume the operation successful return true, otherwise return false;
  • Collaborative program runs;
  • Run to yield statements;
  • yield suspended coroutine first resume returns; (Note: yield return here to resume parameters are parameters)
  • Second resume, wake up again coroutines; (Note: This resume parameters, in addition to the first argument, the remaining parameters will yield as a parameter)
  • yield returns;
  • Collaborative program continues to run;
  • If you continue to run the cooperative program uses the method continues to call resume after the completion of the output: can not resume dead coroutine

The power of place with that resume and yield, resume in the main program, it will be outside the state (data) passed to the internal coordination procedures; and will yield internal state (data) returns to the main process.


Producer - consumer issues

Consumers of this classic problem - I will now complete the producers use Lua coroutines.

local newProductor

function productor()
     local i = 0
     while true do
          i = i + 1
          send(i)     -- 将生产的物品发送给消费者
     end
end

function consumer()
     while true do
          local i = receive()     -- 从生产者那里得到物品
          print(i)
     end
end

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

function send(x)
     coroutine.yield(x)     -- x表示需要发送的值,值返回以后,就挂起该协同程序
end

-- 启动程序
newProductor = coroutine.create(productor)
consumer()

Examples of the implementation of the above output is:

1
2
3
4
5
6
7
8
9
10
11
12
13
……