lua程序设计第二版 读书笔记(9-10章)
来源:互联网 发布:nginx ssl 泛域名 编辑:程序博客网 时间:2024/05/17 07:17
书本下载地址 http://download.csdn.net/detail/myy2012/5349646
本部分下载地址 http://download.csdn.net/detail/myy2012/5353143
lua程序设计第二版 读书笔记(1-4章)
第一章 开始
第二章 类型与值
第三章 表达式
第四章 语句
http://blog.csdn.net/myy2012/article/details/8900424
lua程序设计第二版 读书笔记(5-8章)
第五章 函数
第六章 深入函数
第七章 迭代器与泛型for
第八章 编译执行与错误
http://blog.csdn.net/myy2012/article/details/8906466
lua程序设计第二版 读书笔记(9-10章)
第九章 协同程序
第十章 完整的实例
http://blog.csdn.net/myy2012/article/details/8911206
lua程序设计第二版 读书笔记(11-14章)
第十一章 数据结构
第十二章 数据文件与持久性
第十三章 元表metatable与元方法meatmethod
第十四章 环境
http://blog.csdn.net/myy2012/article/details/8914457
lua程序设计第二版 读书笔记(15-17章)
第十五章 模块与包
第十六章 面向对象编程
第十七章 弱引用 table
http://blog.csdn.net/myy2012/article/details/8921632
lua程序设计第二版 读书笔记(18-21章)
第十八章 数学库
第十九章 table库
第二十章 字符串库
第二十一章 IO库
http://blog.csdn.net/myy2012/article/details/8925895
lua程序设计第二版 读书笔记(22-23章)
第二十二章 操作系统库
第二十三章 调试库
http://blog.csdn.net/myy2012/article/details/8930181
第九章 协同程序(coroutine)
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又与其他协同程序共享全局变量和其他大部分东西。
一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并正在运行的协同程序只会在其显式地要求挂起(suspend)时,它的执行才会暂停。
9.1协同程序基础
Lua将所有有关于协同程序的函数放置在一个名为“coroutine”的table中。函数create用于创建新的协同程序,它只有一个参数(一个函数)。该函数的代码就是协同程序所需执行的内容。Create会返回一个thread类型的值,用以表示新的协同程序。例如:
co=coroutine.create(function() print("hi") end)print(co) --thread: 005EB9B8
一个协同程序可以处于4种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当创建一个协同程序时,它处于挂起状态(协同程序不会在创建它时自动执行其内容)。可以通过函数status来检查协同程序的状态:
print( coroutine.status( co )) -- suspended
coroutine.resume用于启动或者再次启动一个协同程序的执行,并将状态从挂起改为运行。
coroutine.resume(co)-- hi
正常状态:当一个协同程序A唤醒另一个协同程序B时,A就处于一个特殊状态(正常状态normal),既不是挂起状态(无法继续A的执行),也不是运行状态(B在运行)。
Lua的协同程序可以通过一对resume-yield来交换数据。
A. 在第一次调用resume时,并没有对应的yield在等待它,因此所有传递给resume的额外参数都将视为协同程序主函数的参数。例如:
co3=coroutine.create(function(a, b, c) print("co3", a, b, c) end)coroutine.resume(co3, 1, 2)--co3 1 2 nil
B. 在resume调用返回的内容中,第一个值为true 表示没有错误,而后面所有的值都是对应yield传入的参数。例如:
co4=coroutine.create(function(a, b)coroutine.yield(a+b, a-b)end)print("co4", coroutine.resume(co4, 25, 10)) --co4 true 35 15
C. yield返回的额外值就是对应resume传入的参数。例如:
co5=coroutine.create(function()print("co5", coroutine.yield())end)coroutine.resume(co5)coroutine.resume(co5, 4, 5)--co5 4 5
D. 当一个协同程序结束时,它的主函数所返回的值都将作为对应的resume的返回值。例如:
co6=coroutine.create(function()return 6, 7end)print("co6",coroutine.resume(co6))
非对称的协同程序(asymmetric coroutine):Lua提供了2个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。有人称之为“semi-coroutine”。
9.2协同程序与过滤器
一个关于协同程序的经典示例就是“生产者-消费者”的问题。
function producer() while true do local x=io.read() --产生新的值 send(x)--发送给消费者 endendfunction consumer() while true do local x=receive() --从生产者接收值 io.write(x, “\n”)--消费新的值 endend
协同程序被称为是一种匹配生产者和消费者的理想工具,一对resume-yield完全一改典型的调用者与被调用者之间的关系。当一个协同程序调用yield时,它不是进入一个新的函数,而是从一个悬而未决的resume调用中返回;同样对于resume的调用也不会启动一个新函数,而是从一次yield调用中返回。
消费者驱动(consumer-driven)模式:当消费者需要一个新值时,它唤醒生产者。
function receive() local statue, value = coroutine.resume(producer) return valueendfunction send(x) coroutine.yield(x)end
过滤器(filter):是一种位于生产者和消费者之间的处理功能,可用于对数据的一些交换。
function filter(pro) return coroutine.create(function() for line=1, math.huge do local x=receive(prod) x=string.format(“%5d %s”, line, x) send(x) end end )
9.3以协同程序实现迭代器
功能:遍历某个数组的所有排列组合的形式。
function permgen(a, n)n=n or #aif n<=1 thencoroutine.yield(a)--elsefor i=1, n doa[n], a[i]=a[i], a[n] --将第i个元素放到数组末尾permgen(a, n-1)--递归调用a[n], a[i]=a[i], a[n] --恢复第i个元素endendend
定义一个工厂函数permutations,用于将生成函数放到一个协同程序中运行,并出具迭代器函数(只是简单地唤醒协同程序)。函数permutations是将一条唤醒协同程序的调用包装在一个函数中。
function permutations(a)local co=coroutine.create(function() permgen(a) end)return function()--迭代器local code, res=coroutine.resume(co) --开启return res--返回的res就是传入到函数permgen中的参数aendend
function printResult(a)for i=1, #a doio.write(a[i], " ")endio.write("\n")endfor p in permutations({1, 3, 5}) doprintResult(p)--调用打印函数end
9.4 非抢先式的(non-preemptive)多线程
协同程序提供了一种协作式的多线程,每个协同程序都等于一个线程。一对yield-resume可以将执行权在不同线程之间切换。有一点不同的就是:协同程序运行时是无法从外部停止它的,只有当协同程序显式地要求挂起时(调用yield),它才会停止。
对于非抢占式的多线程来说,只要一个线程调用一个阻塞(blocking)操作,整个程序在该操作完成前都会停止下来。但是这种行为对于大多数应用程序来说的无法接受的。
require "socket" host="www.w3.org"file="/TR/REC-html32.html"--------------------------------------------------------------function receive(connection) connection:settimeout(0) local s, status, partial=connection:receive(2^10) if status=="timeout" then --coroutine.yield(connection) end return s or partial, statusend
函数的实现:
function download(host, file) 打开一个TCP连接,连接到该站点的80端口 local c=assert(socket.connect(host, 80)) local count=0 返回一个连接对象,可以用它来发送文件请求 c:send("GET "..file.." HTTP/1.0\r\n\r\n") while true do local s, status, partial=receive(c) count=count+#(s or partial) if status=="closed" then break end end c:close() print(file, count) end
download(host, file)
第十章 完整的示例
10.1 数据描述
将Lua作为一种数据描述语言。
要读取这些数据,程序只需简单地给出一个关于entry的合适定义,然后将数据文件作为一个程序来运行(通过dofile)。注意,必须对所有的条目遍历两次,第一次为获得标题列表,第二次为获得项目描述。
entry的定义如下:
entry={ title="Tecgraf", org="Computer Graphics ", url="http://www.tecgraf.com", contact="waldemar ...", description=[[ Tecgraf is the result of ... ]] }
函数fwrite的实现:
function fwrite(fmt, ...) return io.write(string.format(fmt, ...)) end function writeheader() io.write([[ <html> <head><title>Projects using Lua</title></head> <body bgcolor="#FFFFFF"> Here are brief descriptions of Some Projects around the world that use <a href="home.html">Lua</a>. <br> ]]) end
函数entry1的实现:
function entry1(o) count=count+1 local title=o.title or '(no title)' fwrite('<li><a href="#%d">%s</a>', count, title) end
函数entry2的实现:
function entry2(o) count=count+1 fwrite('<hr>\n<h3>\n') local href=o.url and string.format(' href="%s", o.url') or '' local title=o.title or o.org or 'org' fwrite('<a name="%d"%s></a>\n', count, href, title) if o.title and o.org then fwrite('<br>\n<small><em>%s</em></small>', o.org) end fwrite('<\n</h3>>\n') if o.description then fwrite('%s<p>\n', string.gsub(o.description), '\n\n+', '<p>\n') end end
函数writetail的实现
function writetail() fwrite('</body></html>\n') end
------------------------------------
测试代码如下:
local inputfile='db.lua' f=loadfile(inputfile) writeheader() count=0 entry=entry1 fwrite('<ul>\n') f() fwrite('</ul>\n') count=0 entry=entry2 f() writetail()
10.2 马尔可夫链(markov chain)算法
略
第一部分完
- lua程序设计第二版 读书笔记(9-10章)
- lua程序设计第二版 读书笔记(1-4章)
- lua程序设计第二版 读书笔记(5-8章)
- lua程序设计第二版 读书笔记(11-14章)
- lua程序设计第二版 读书笔记(15-17章)
- lua程序设计第二版 读书笔记(18-21章)
- lua程序设计第二版 读书笔记(22-23章)
- lua程序设计第二版 读书笔记(24-26章)
- lua程序设计第二版 读书笔记(27-28章)
- lua开发(9)--<Lua程序设计第二版>读书笔记
- 《Lua程序设计[第二版]》第9,10章笔记
- 《lua程序设计》读书笔记 第二章:类型与值
- Lua程序设计第二版(笔记)第九章协同程序
- <Lua程序设计(第二版)>书摘-9
- <Lua程序设计(第二版)>书摘-10
- JavaScript高级程序设计(第3版)第二章读书笔记
- Lua程序设计第二版(笔记) 第二章类型与值
- 《Linux程序设计第四版》读书笔记 - 第二章 Shell程序设计
- 自定义窗口的玻璃效果(边框,标题栏...)
- 海量日志,提取出现最多的IP--python实现
- Gnuplot的一个小错误,求详解
- static_cast、dynamic_cast reinterpret_cast和const_cast
- UITextView里换行实现(键盘上附加一个完成按钮)
- lua程序设计第二版 读书笔记(9-10章)
- Object_c的retain机制
- 黑马程序员_java基础day14
- R语言:求二维随机变量数学期望
- 5.10
- Solr 删除数据的几种方式
- Fujistu Lifebook S series not supported by Ubuntu 12.04
- scrollview的scrollTo(int,int)方法
- 多核编程:选择合适的结构体大小,提高多核并发性能