Lua 的協同程序coroutine和線程比較相似,有獨立的堆棧、局部變量、獨立的指針指令,同時又能共享全局變量
但coroutine又和多線程程序不一樣,首先一個多線程程序能夠同時運行多個單線程,但協同程序只能串行,也就是說同一時刻只能有一個協同程序在運行,而且這個協同程序將一直佔用處理器直到被顯式的掛起。web
基本的函數緩存
coroutine.create(f) 建立一個協同程序,返回coroutine, f是該協同程序的註冊函數 coroutine.yield(a) 將當前運行的coroutine掛起,a是掛起後返回的值或表達式結果 coroutine.resume(co,a,...) 喚醒coroutine co,後面的a,...是對應註冊函數待輸入的參數,返回一個布爾值表示是否喚醒成功 coroutine.status(co) 返回協同程序co的狀態,協同程序的狀態包括dead,suspend和running coroutine.running() 返回當前正在運行的coroutine的線程號和一個boolean值表示是否是主線程
看個例子多線程
function foo(a)
print("foo 的函數輸出 ", a)
return coroutine.yield(2*a)
end
co=coroutine.create(function(a,b)
print("第一次協同程序執行輸出",a,b)
local r=foo(a+1)
a=a+1
print("第二次協同程序輸出",r)
local r,s=coroutine.yield(a+b,a-b)
print("第三次協同程序執行輸出",r,s)
return b
end
)
print('main',coroutine.resume(co,1,10))
print('--------分割線--------')
print('main',coroutine.resume(co))
print('--------分割線--------')
print("main",coroutine.resume(co,"x","y"))
print("--------分割線--------")
print("main",coroutine.resume(co,"x","y"))
print("--------分割線--------")
其輸出函數
第一次協同程序執行輸出 1 10 foo 的函數輸出 2 main true 4 --------分割線-------- 第二次協同程序輸出 nil main true 12 -8 --------分割線-------- 第三次協同程序執行輸出 x y main true 10 --------分割線-------- main false cannot resume dead coroutine --------分割線--------
分析一下:首先執行到print('main',coroutine.resume(co,1,10))這一行先執行裏面做爲參數的函數,即喚醒協同程序co,進入了對應的註冊函數,輸出一句,而後進入函數foo,foo的參數爲1,10
執行foo裏面的第一句輸出,而後返回 掛起線程操做的狀態,以及對應的返回值,這裏就是2*a
OK,這時候又回到了主線程,輸出 main 狀態 返回參數
輸出分割線
喚醒co,這個時候從上次掛起的階段繼續執行,此時resume的參數是coroutine.yield()的參數做爲返回值
。。。
最後若是co已經dead,則輸出false,即喚醒失敗,和cannot resume dead coroutine的信息,若是這個時候想再執行註冊函數的內容須要從新建立coroutine學習
生產者-消費者問題ui
local newProductor function productor() local i=0
while i<10 do
i=i+1
send(i)
end end function consumer() repeat local i=receive()
print(i)
until i>9
end function receive() local status,value=coroutine.resume(newProductor)
return value end function send(x) coroutine.yield(x) end newProductor=coroutine.create(productor)
consumer()
lua的文件輸入輸出包含兩種模式 簡單模式和徹底模式
簡單模式lua
file = io.open("moduleTest.lua",'r') io.input(file) print(io.read()) io.close(file) file=io.open("moduleTest.lua","a+") io.output(file) io.write("This is a sentense written in simple model") io.close(file)
複雜模式spa
file=io.open("moduleTest.lua","a+") print(file:read()) file:close() file=io.open("moduleTest.lua","a") file:write("This sentence is written in complete model") file:close
不一樣點在於簡單模式須要指定輸入輸出設備,而徹底模式直接經過文件句柄操做。線程
文件open的模式有debug
r 只讀模式,文件必須存在 w 清零重寫模式,若是沒有則新建 a 附加模式,沒有則新建 r+ 讀寫模式,文件必須存在 w+ 和w相似,可是可讀寫 a+ 和a相似,可是可讀寫 b 二進制模式,若是文件是二進制文件,可在上面的模式符後添加b
read()的參數有
空 讀取一行 "*n" 讀取一個數字 "*a" 從當前位置讀取整個文件 "*l"(默認) 都去下一行,文件結尾處返回nil number 讀取指定個數個字符,EOF時返回nil
io其餘方法
io.tmpfile() 返回一個臨時文件句柄,該文件以更新模式打開,程序結束時自動刪除 io.type(file) 檢測file是否是可用的文件句柄 io.flush() 向文件中寫入緩存區中全部數據 io.lines(optional filename) 返回一個由line組成的迭代器,文件結尾時返回nil,但不關閉文件 e.g. for line in io.lines("moduleTest.lua") do print(line) end
file的read,write,lines,close等方法和io相似,只不過使用的是":"符號
file的其餘方法
file:seek(optional whence,optional offset) 設定當前位置,第二個參數是偏置 第一個參數可選 "set" 文件頭 "cur" 當前位置(默認) "end" 文件尾 不帶參數,file:seek()返回當前位置 file:flush() 將緩衝區全部數據寫入文件 file:lines() 相似於io.lines(filename)返回一個迭代器,只是此處沒有輸入參數
斷言assert(arg1,arg2),首先檢查第一個參數,沒問題ok,有問題將第二個參數做爲錯誤信息拋出
error(message[,level]),終止執行的函數,拋出message做爲錯誤信息
level表示附加的錯誤位置信息
level=1,error的位置
level=2,調用error的函數
level=0,不添加錯誤位置信息
相似於trycatch語句pcall,xpcall
調用格式:
pcall(f[,arg]) --f是protect call的函數,arg是f的參數
xpcall(f,errHandleFun[,arg]) --errHandleFun是錯誤處理函數
相同點:
當程序正常執行時,都返回true和被執行函數f的返回值
不一樣點:
i. pcall: 返回錯誤信息時,已經釋放了保存錯誤發生狀況的棧信息
xpcall: 在釋放棧信息以前調用錯誤處理程序處理這些信息
ii. pcall:返回nil,錯誤信息
xpcall:返回nil,無錯誤信息
local f=function(...) --local a=1 print (a+1) return a+1 end tryCatch = function(f) local ret,errMessage=pcall(f) print("ret:" ..(ret and "true" or "false") .."\nerrMessage:"..(errMessage or "null")) end xTryCatchGetErrorInfo=function() print(debug.traceback()) end xTryCatch=function(f) local ret,errMessage=xpcall(f,xTryCatchGetErrorInfo) print("ret:"..(ret and "true" or "false").."\nerrMessage:"..(errMessage or "null")) end print("\n---------A---------\n") tryCatch(f) print("\n---------B---------\n") xTryCatch(f) print("\n---------C---------\n")
輸出
---------A--------- ret:false errMessage:testIO.lua:18: attempt to perform arithmetic on global 'a' (a nil value) ---------B--------- stack traceback: testIO.lua:28: in function <testIO.lua:27> testIO.lua:18: in function <testIO.lua:16> [C]: in function 'xpcall' testIO.lua:32: in function 'xTryCatch' testIO.lua:39: in main chunk [C]: ? ret:false errMessage:null ---------C--------- >Exit code: 0