lua6 coroutine2


文章轉自: http://blog.csdn.net/wusheng520/article/details/7954666html


1、基本環境:函數

Microsoft Windows XP/Service Pack 2
lua

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Riospa


2、 coroutine的接口:.net

(1) coroutine.create()線程

(2) coroutine.resume()code

(3) coroutine.yield()orm

(4) coroutine.status()htm

(5) coroutine.wrap()
blog

(6) coroutine.running()


3、coroutine的狀態分爲suspend, running, dead三種。


4、coroutine的基本流程

下面的代碼說明了coroutine的基本流程


co = coroutine.create(function(a, b)  
    print(coroutine.status(co), "start")   --執行代碼,coroutine狀態爲running--->(3)  
    print("co", a, b)  
    print(coroutine.status(co), "end")    --執行代碼,coroutine狀態爲running     --->(4)  
end)  
  
print(coroutine.status(co))       --剛建立的coroutine的狀態爲suspend   --->(1)  
coroutine.resume(co, 1, 2)       --啓動coroutine,將跳轉到coroutine的function執行   --->(2)  
print(coroutine.status(co))       --coroutine執行完畢,狀態爲dead    --->(5)


代碼的執行結果以下:

>lua -e "io.stdout:setvbuf 'no'" "cur.lua"   
suspended  
running    start  
co    1    2  
running    end  
dead  
>Exit code: 0



5、yield對coroutine流程的干預

若是沒有yield,coroutine的生老病死就是上面這樣一個流程了。

接下來輪到yield出場,它的做用是將一個running的coroutine掛起,相應的其狀態就會被切換成suspend。

先貼代碼,再解釋

co = coroutine.create(function(a, b)  
    print(coroutine.status(co), "start")                --->(2)  
    for i = 1, 10 do  
        print("co", a, b)                               --->(3)(6)  
        coroutine.yield()  
        print(coroutine.status(co), "after yield")      --->(5)  
    end  
    print(coroutine.status(co), "end")  
end)  
  
print(coroutine.status(co))                             --->(1)  
coroutine.resume(co, 1, 2)  
print(coroutine.status(co))                             --->(4)  
coroutine.resume(co, 1, 2)                                
print(coroutine.status(co))                             --->(7)

執行結果貼一下:

>lua -e "io.stdout:setvbuf 'no'" "cur.lua"   
suspended  
running start  
co  1   2  
suspended  
running after yield  
co  1   2  
suspended  
>Exit code: 0

在執行到yield以後,代碼跳轉到上一次resume代碼的後一條代碼執行

再次調用resume,代碼就跳轉到上一次yield代碼的後一條代碼執行。

通常來講,resume方法在主線程中調用;而yield則是在coroutine內調用,包括coroutine內部調用的函數內部。

固然了,在coroutine中調用resume沒有什麼問題,但這樣是沒有什麼意義的,由於若是代碼還在coroutine中執行的話,則說明其狀態必定是running的,這個時候的resume是沒有任何意義的。而在主線程中調用yield,會致使 「lua: attempt to yield across metamethod/C-call boundary」的錯誤。


6、resume, function()以及yield之間的參數傳遞和返回值傳遞

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

執行結果以下:

>lua -e "io.stdout:setvbuf 'no'" "cur.lua"   
co  1   nil  
co  1   2  
co  1   2  
>Exit code: 0



這個說明resume的參數除了coroutine句柄(第一個參數)之外,都傳遞給了function,關係跟表達式賦值是一致的,少的以nil補足,多的捨棄。

若是在coroutine中包含有yield,狀況會複雜一些。咱們進一步挖掘coroutine的流程:

1 resume 

2 function

3 yield

4 yield掛起,第一次 resume返回

5 第二次resume

6 yield返回

7 function 繼續執行

在這個流程的第一步的時候,resume的參數會傳遞給function,做爲參數(具體如上);到了第三步的時候,yield的參數會做爲resume返回值的一部分;而第二次resume(第五步)的時候,resume的參數的做用發生了改變,resume的參數會傳遞給yield,作爲yield的返回值。

這個過程很精巧,在coroutine執行的過程當中返回,必然須要告訴外部如今coroutine這個時候的內部的的狀況,經過惟一的接口yield的參數做爲resume的返回值,高;到了第二次resume的時候,外部的環境必然發生了改變, 怎麼通知coroutine內部呢,一樣的想法,將惟一的接口resume的參數經過yield的返回的途徑返回到coroutine內部,同樣的高明。

貼一個引用的代碼,代碼源出處見參考:

function foo (a)  
    print("foo", a)  -- foo 2  
    return coroutine.yield(2 * a) -- return: a , b  
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("------")



結果以下:

>lua -e "io.stdout:setvbuf 'no'" "cur.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

剛看有點繞,你們靜心看看, 必有收穫,畢竟代碼不長。

參考:

1 programming in Programming in Lua

2 lua-5.1中文手冊

http://www.cnblogs.com/yjf512/archive/2012/05/28/2521412.html

相關文章
相關標籤/搜索