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