Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
coroutineLua 的协同程序coroutine和线程比较类似,有独立的堆栈、局部变量、独立的指针指令,同时又能共享全局变量
但coroutine又和多线程程序不同,首先一个多线程程序可以同时运行多个单线程,但协同程序只能串行,也就是说同一时刻只能有一个协同程序在运行,并且这个协同程序将一直占用处理器直到被显式的挂起。
基本的函数
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
生产者-消费者问题
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()
I/O
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)
复杂模式
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的模式有
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
- Erlang学习笔记(六)顺序程序的错误处理
- Lua 学习笔记(七) —— 协同程序(一)
- C++ Primer 学习笔记_88_用于大型程序的工具 -错误处理[续1]
- Lua学习笔记(三)——协同程序
- 调试的艺术学习笔记--程序崩溃处理(段错误)
- lua学习笔记四--协同程序
- Lua学习笔记 第九章 协同程序 —— coroutine
- C++ Primer 学习笔记_90_用于大型程序的工具 -错误处理[续3]
- Lua 学习笔记(七) —— 协同程序(二)
- C++ Primer 学习笔记_87_用于大型程序的工具 -错误处理
- Lua 学习笔记(七) —— 协同程序(三)
- C++ Primer 学习笔记_89_用于大型程序的工具 -错误处理[续2]
- Lua学习笔记-9.1章-协同程序
- Lua笔记——模块、错误处理、文件IO
- Lua 学习笔记(九)协同程序(线程thread)
- HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。
- WCF问题:“HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理”解决方法
- c++ 学习笔记-----头文件预处理
- 读入图像文件并显示【C#图像处理学习笔记】
- VS2010 学习笔记 WF4 (8) 在工作流中进行错误捕捉和处理