Lua学习笔记4. coroutine协同程序和文件I/O、错误处理

coroutine

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)返回一个迭代器,只是此处没有输入参数

错误处理

  1. 断言assert(arg1,arg2),首先检查第一个参数,没问题ok,有问题将第二个参数作为错误信息抛出

  2. error(message[,level]),终止执行的函数,抛出message作为错误信息

    level表示附加的错误位置信息

    level=1,error的位置

    level=2,调用error的函数

    level=0,不添加错误位置信息

  1. 类似于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、错误处理的更多相关文章

  1. [转]LUA 学习笔记

    Lua 学习笔记 入门级 一.环境配置 方式一: 1.资源下载http://www.lua.org/download.html 2.用src中的源码创建了一个工程,注释调luac.c中main函数,生 ...

  2. Lua 学习笔记(一)

    Lua学习笔记 1.lua的优势 a.可扩张性     b.简单     c.高效率     d.和平台无关 2.注释 a.单行注释 --        b.多行注释 --[[  --]] 3.类型和 ...

  3. Lua学习笔记6:C++和Lua的相互调用

        曾经一直用C++写代码.话说近期刚换工作.项目组中的是cocos2dx-lua,各种被虐的非常慘啊有木有.     新建cocos2dx-lua项目.打开class能够发现,事实上就是C++项 ...

  4. (转)Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境

    Lua学习笔记1:Windows7下使用VS2015搭建Lua开发环境(一)注意:工程必须添加两个宏:“配置属性”/“C或C++”/“预处理器”/“预处理器定义”,添加两个宏:_CRT_SECURE_ ...

  5. Lua学习笔记:面向对象

    Lua学习笔记:面向对象 https://blog.csdn.net/liutianshx2012/article/details/41921077 Lua 中只存在表(Table)这么唯一一种数据结 ...

  6. 微信小程序开发:学习笔记[7]——理解小程序的宿主环境

    微信小程序开发:学习笔记[7]——理解小程序的宿主环境 渲染层与逻辑层 小程序的运行环境分成渲染层和逻辑层. 程序构造器

  7. Linux进程线程学习笔记:运行新程序

    Linux进程线程学习笔记:运行新程序                                         周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...

  8. Java NIO 学习笔记(五)----路径、文件和管道 Path/Files/Pipe

    目录: Java NIO 学习笔记(一)----概述,Channel/Buffer Java NIO 学习笔记(二)----聚集和分散,通道到通道 Java NIO 学习笔记(三)----Select ...

  9. Lua 学习笔记(九)协同程序(线程thread)

    协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...

随机推荐

  1. Failed to load c++ bson extension, using pure JS version

    Failed to load c++ bson extension, using pure JS version npm install mongodbnpm install bson npm ins ...

  2. Inno Setup入门(九)——修改安装过程中的文字显示

    前面说到过可以使用不用的语言文件实现不同的显示方式,方便与国际接轨,事实上即使没有语言文件也可以实现修改.[Messages]段用于定义安装程序和卸载程序中显示的消息.一般不需要创建 [Message ...

  3. CentOS6.6 搭建Zabbix_3.0

    公司有下发内网监控服务器的需求 使用zabbix监控 所以这篇文章是讲述的zabbix的搭建 其实网上很多地方都有 可以参考 环境安装 系统环境: # cat /etc/redhat-release ...

  4. HttpWebRequest 抓取页面异常处理办法

    抓取页面异常处理办法 public static string GetHtmlTest(string URI) { string fullhtml = null; while (true) { try ...

  5. SQL中的左连接与右连接有什么区别,点解返回值会不同?(转)

    例子,相信你一看就明白,不需要多说 A表(a1,b1,c1) B表(a2,b2) a1 b1 c1 a2 b2 01 数学 95 01 张三 02 语文 90 02 李四 03 英语 80 04 王五 ...

  6. ANT 配置和安装 1

    --"JAVA_HOME" (JDK HOME)C:\Program Files\Java\jdk1.7.0_79 -- "ANT_HOME" (ANT HOM ...

  7. EXP AND IMP

    purpors: exp pro data to uat data exp and imp will not create user expdp and impdp will create user ...

  8. iOS 常用代码块

    1.判断邮箱格式是否正确的代码: // 利用正则表达式验证 -( BOOL )isValidateEmail:( NSString  *)email {   NSString  *emailRegex ...

  9. python 压缩 解压缩 文件

    1. 用zipfile模块打包文件或是目录.解压zip文件 http://wangwei007.blog.51cto.com/68019/1045577 #!/usr/bin/env python # ...

  10. java内部类继承--构造函数传参

    /: innerclasses/InheritInner.java // Inheriting an inner class. class WithInner { class Inner {} } / ...