lua程序设计第二版 读书笔记(9-10章)

 


书本下载地址                       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, 7
end)
print("co6",coroutine.resume(co6))

 

非对称的协同程序(asymmetric coroutine):Lua提供了2个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。有人称之为“semi-coroutine”。

9.2协同程序与过滤器

一个关于协同程序的经典示例就是“生产者-消费者”的问题。

function producer()
  while true do 
  local x=io.read()  --产生新的值
  send(x)			--发送给消费者
  end
end
function consumer()
  while true do 
  local x=receive()  --从生产者接收值
  io.write(x, “\n”)	--消费新的值
  end
end

 

协同程序被称为是一种匹配生产者和消费者的理想工具,一对resume-yield完全一改典型的调用者与被调用者之间的关系。当一个协同程序调用yield时,它不是进入一个新的函数,而是从一个悬而未决的resume调用中返回;同样对于resume的调用也不会启动一个新函数,而是从一次yield调用中返回。

消费者驱动(consumer-driven)模式:当消费者需要一个新值时,它唤醒生产者。

 

function receive()
  local statue, value = coroutine.resume(producer)
  return value
end
function 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 #a
	if n<=1 then
		coroutine.yield(a)		--
	else
		for i=1, n do
			a[n], a[i]=a[i], a[n] --将第i个元素放到数组末尾
			permgen(a, n-1)	--递归调用
			a[n], a[i]=a[i], a[n]  --恢复第i个元素
		end
	end
end
 

定义一个工厂函数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中的参数a
	end
end
 
function printResult(a)
	for i=1, #a do
		io.write(a[i], " ")
	end
	io.write("\n")
end
for p in permutations({1, 3, 5}) do
	printResult(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, status
end

 

函数的实现:

  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)算法

 

第一部分完

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值