Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua学习笔记4. coroutine协同程序和文件I/O、错误处理
Lua 的协同程序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
Lua学习笔记4. coroutine协同程序和文件I/O、错误处理的更多相关文章
- [转]LUA 学习笔记
Lua 学习笔记 入门级 一.环境配置 方式一: 1.资源下载http://www.lua.org/download.html 2.用src中的源码创建了一个工程,注释调luac.c中main函数,生 ...
- Lua 学习笔记(一)
Lua学习笔记 1.lua的优势 a.可扩张性 b.简单 c.高效率 d.和平台无关 2.注释 a.单行注释 -- b.多行注释 --[[ --]] 3.类型和 ...
- Lua学习笔记6:C++和Lua的相互调用
曾经一直用C++写代码.话说近期刚换工作.项目组中的是cocos2dx-lua,各种被虐的非常慘啊有木有. 新建cocos2dx-lua项目.打开class能够发现,事实上就是C++项 ...
- (转)Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境
Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境(一)注意:工程必须添加两个宏:“配置属性”/“C或C++”/“预处理器”/“预处理器定义”,添加两个宏:_CRT_SECURE_ ...
- Lua学习笔记:面向对象
Lua学习笔记:面向对象 https://blog.csdn.net/liutianshx2012/article/details/41921077 Lua 中只存在表(Table)这么唯一一种数据结 ...
- 微信小程序开发:学习笔记[7]——理解小程序的宿主环境
微信小程序开发:学习笔记[7]——理解小程序的宿主环境 渲染层与逻辑层 小程序的运行环境分成渲染层和逻辑层. 程序构造器
- Linux进程线程学习笔记:运行新程序
Linux进程线程学习笔记:运行新程序 周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...
- Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe
目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...
- Lua 学习笔记(九)协同程序(线程thread)
协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...
随机推荐
- linkButton
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...
- ASP.NET获取客户端信息,获取客户端IP等等
山上明月 ASP.NET能知道的东西 获取服务器电脑名: Page.Server.ManchineName 获取用户信息: Page.User 获取客户端电脑名:Page.Request.UserHo ...
- 安装MSYS2过程遇到的问题及解决记录
1.在安装结束后按照官方教程开始更新系统是遇到了如下的错误 could not open file /var/lib/pacman/sync/msys32.db: Unrecognized archi ...
- The Rings Akhaten
在其他的平行宇宙中存在着一个古老的星系--Akhaten,星系中有七个世界,上面生活着Panbabylonian.Lucanian等物种,不过外界也常常把他们统称为Akhet,因为这七个世界环绕着同一 ...
- scrollView的bounds
如果scrollView的contentoffset为(100,0) 那么scrollView的bounds就是(100,y,w,h)
- %3f URL --> '?'拼接引发的问题
转载自:https://www.reddit.com/r/swift/comments/2w19kp/how_do_you_send_a_through_nsmutableurlrequest/ ho ...
- Disassembly3:variable
Initializer C++ Primer上说:如果未初始化的Built-in type是定义在function外部的,那么它将自动被初始化为“0”:如果uninitialized的built-in ...
- 通过onActivityResult()先跳转到联系人界面,然后把传回来的手机号显示到应用的EditText上
<pre name="code" class="plain"><pre name="code" class="p ...
- SVM阅读资料
1,Andrew Ng机器学习公开课笔记 -- 支持向量机 2,http://blog.pluskid.org/?page_id=683 3,支持向量机SVM(一) 4,机器学习中的算法(2)-支持向 ...
- listview去掉条目间的分割线
未去掉前: 去掉后: java代码可以这么写: 1 listView.setDivider(null);//去掉条目间的分割线 PS:ListView的几个常用操作 listView ...