Preface
The synergy program is similar to the thread, that is, an execution sequence. It has its own independent stack, local variables, and command pointers, and shares global variables with other coders and most other things. In terms of concept, the main difference between a thread and a collaborative program is that a program with multiple threads can run several threads at the same time, but a collaborative program needs to run in collaboration with each other. That is to say, a program with multiple collaborators can only run one program at any time, and the running program will only explicitly suspend when it explicitly requires that, its execution will be paused.
Collaboration program Basics
Lua places all functions related to the coprocessor in a table named coroutine. The create function is used to create a new collaborative program. It has only one parameter and is a function. The code of this function is the content that the coprocessor needs to execute. Create returns a value of the thread type to indicate the new coprocessor. Generally, the create parameter is an anonymous function, for example, the following code:
1 |
local co = coroutine.create(function () print( "Hello WOrld" ) end) |
A collaboration program can be in four different States: suspended, running, dead, and normal ). When a new collaboration program is created, it is suspended. The implication is that the collaboration program does not automatically execute its content when it is created. We can check the status of the collaboration program through the function status.
12 |
local co = coroutine.create(function () print( "Hello WOrld" ) end) print(coroutine.status(co)) -- suspended |
The coroutine. Resume function is used to start or restart the execution of a collaborative program and change its status from suspended to running:
123 |
local co = coroutine.create(function () print( "Hello WOrld" ) end) print(coroutine.status(co)) -- suspended coroutine.resume(co) -- Hello World |
In the above code, I called the Resume function and changed the coprocessor Co from sushortded to running. After the Hello world is printed, the coprocessor Co is in the dead state.
So far, a collaborative program is a function call. In fact, the real strength of a collaborative program lies in the use of the yield function. This function can suspend a running collaborative program and resume its running. For example, the following code:
123456789101112131415161718192021222324252627282930313233 |
local co = coroutine.create(function () for i = 1, 10 do print( "co" , i) coroutine.yield() end end) -- Print the initial status print(coroutine.status(co)) -- suspended -- Wake up the coprocessor Co Coroutine. Resume (CO) -- print Co 1 -- Print the status of the collaboration program print(coroutine.status(co)) -- suspended -- Wake up cool again Coroutine. Resume (CO) -- print CO 2 -- Print the status of the collaboration program print(coroutine.status(co)) -- suspended Coroutine. Resume (CO) -- print CO 3 Coroutine. Resume (CO) -- print Co 4 Coroutine. Resume (CO) -- print Co 5 Coroutine. Resume (CO) -- print Co 6 Coroutine. Resume (CO) -- print Co 7 Coroutine. Resume (CO) -- print Co 8 Coroutine. Resume (CO) -- print Co 9 Coroutine. Resume (CO) -- print Co 10 Coroutine. Resume (CO) -- do not print anything print(coroutine.status(co)) -- dead coroutine.resume(co) |
When any errors occur during the execution of the coprocessor, Lua does not display an error message, but returns the execution permission to resume for calling. When the first return value of coroutine. Resume is false, it indicates that the coprocessor has encountered an error while running. If the value is true, it indicates that the coprocessor program runs normally.
When a collaborative program a wakes up another collaborative program B, it is in a special State, neither suspended state (unable to continue the execution of ), it is not the running status (B is running ). Therefore, the status is called "normal.
Lua's collaboration program also has a useful mechanism, that is, it can exchange data through a pair of resume-yield. When resume is called for the first time, no corresponding yield is waiting for it. Therefore, all additional parameters passed to resume are considered as parameters of the main function of the coprocessor. See the following code:
If no yield exists in the coprocessor, call resume for the first time. All additional parameters passed to resume are considered as parameters of the main function of the coprocessor, as shown in the following code:
12345 |
local co = coroutine.create(function (a, b, c) print( "co" , a, b, c) end) coroutine.resume(co, 1, 2, 3) -- co 1 2 3 |
When yield exists in the synergy program, everything becomes more complicated. Let's first analyze the process:
1. Call resume to wake up the coprocessor;
2. The program runs collaboratively;
3. Run the yield statement;
4. Yield suspends the coprocessor and the first resume is returned (Note: Here yield returns the parameter resume );
5. For the second resume, wake up the coprocessor again (Note: Except for the first parameter, the remaining parameter will be used as the yield parameter in the resume parameter );
6. Yield return;
7. The Collaborative Program continues to run;
Some of the Code referenced in other blogs can be described as follows:
123456789101112131415161718192021222324 |
function foo (a) print( "foo" , a) -- foo 2 return coroutine.yield(2 * a) -- return 2 * a end co = coroutine.create(function (a , b) print( "co-body" , a, b) -- co-body 1 10 local r = foo(a + 1) print( "co-body2" , r) local r, s = coroutine.yield(a + b, a - b) print( "co-body3" , r, s) return b, "end" 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" )) -- false cannot resume dead coroutine print( "------" ) |
The output result is as follows:
1234567891011121314 |
>lua -e "io.stdout:setvbuf ‘no‘" "test.lua" co-body 1 10 foo 2 main true 4 ------ co-body2 r main true 11 -9 ------ co-body3 x y main true 10 end ------ main false cannot resume dead coroutine ------ >Exit code: 0 |
The combination of resume and yield is powerful in that the resume is in the main process, and it transmits the external State (data) to the inside of the collaboration program; while yield transfers the internal state (data) return to the main process.
Producer-consumer problems
Now I will use the Lua collaborative program to solve the typical producer-consumer problem. Producers produce things and consumers consume things produced by producers.
1234567891011121314151617181920212223242526272829 |
local newProductor function productor() local i = 0 while true do i = i + 1 Send (I) -- send the produced item to the consumer end end function consumer() while true do Local I = receive () -- get the item from the producer print(i) end end function receive() local status, value = coroutine.resume(newProductor) return value end function send(x) Coroutine. Yield (x) -- X indicates the value to be sent. After the value is returned, the coprocessor will be suspended. end -- Start the program newProductor = coroutine.create(productor) consumer()
|
Http://cn.cocos2d-x.org/tutorial/show? Id = 1155