初学者,有错误希望指正。
12————————————————协同 coroutine
#!/usr/local/bin/lua--[[
co=coroutine.create(function()
print("hi")
end
)
]]
--[[
print(co)
print(coroutine.status(co))
coroutine.resume(co)
print(coroutine.status(co))
]]
--[[
count=1
co=coroutine.create(function()
for i=1,10 do
print("co",i)
print("count",count)
count=count+1
coroutine.yield()
end
end
)
for i=1,10 do
coroutine.resume(co)
print(coroutine.status(co),"status")
--print(coroutine.resume(co),"resume")
--注释掉的这句是因为没理解清楚一开始,coroutine.resume(co)会先执行再返回true或false,结果变成了两次
print("count",count)
print("lable",i)
end
]]
--[[通过resume-yield交换数据]]
--[[
--没有yield时,resume把参数传递给协调的主程序
co=coroutine.create(function(a,b,c)
print("co",a,b,c)
end
)
coroutine.resume(co,1,2,3)
]]
--[[
--数据有yield传递给resume,true表示调用成功,之后的参数是yield的参数,resume的参数会被传递给yield
--一旦协同执行,yield接收到的resume的值就无法更改(目前--疑问)
co=coroutine.create(function(a,b)
for i=1,2 do
print("a,b",a,b)
print("lablein",i)
coroutine.yield(a+b,a-b)
end
end
)
--for i=1,10 do
-- print("lable",i)
-- print(coroutine.resume(co,i,1+10))
-- print(coroutine.status(co))
-- print("label",i)
--end
co1=co
co2=co
for i=1,2 do
if i==1 then print(coroutine.resume(co1,30,10))
--yield确实把处理后的值传递了过来,读取了30,10进行操作
else print(coroutine.resume(co1,5,10)) end
--yield不仅没有读取新的值,反而保留了原先的值
--这之上的两条注释实在,创建co1,co2之前的,但是结果相同,所以说传值是对于coroutine来说的,一旦执行协同程序,就不再传值了
--整个协同程序函数的for循环是不会被执行的
--协同程序函数返回两个值,a,b作为resume返回值
---协同程序执行完毕时,resume的返回值就不再是yield的参数了,也就是说yield会一直固话直到结束
end
--输出结果
--a,b 30 10
--lablein 1
--true 40 20
--a,b 30 10
--lablein 2
--true 40 20
]]
--[[
--代码结束时的返回值,也会传给resume
co=coroutine.create(function()
return 6,7
end
)
print(coroutine.resume(co))
]]
--[[lua的协同称为不对称协同,指的是挂起一个正在执行的协同函数,与使一个被挂起的协同再次执行的函数是不同的。有些语言提供对称协同,即使用同一个函数负责执行与挂起间的状态切换
严格意义上的协同不论在什么地方,只要不在其他的辅助代码内部的时候都可以并且只能使执行挂起,不论什么时候在其控制栈内都不会有不可决定的调用。
]]
--[[用coroutine解决消费者生产者问题]]
#!/usr/local/bin/lua
--[[
--用协同解决生产者消费者问题
--当一个协同调用yield时并不会进入一个新的函数,取而代之的是返回一个未决的resune的调用,相似的,调用resume时也不会开始一个新的函数而是返回yield的调用
--消费者驱动生产者
function receive()
print("收到请求商品的请求")
print("开始请求商品")
local status,value=coroutine.resume(producer)
print("获得商品",value)
return value
end
function send(x)
print("消费者获得商品"..x)
print("生产者休息")
coroutine.yield(x)
--yield的参数返回给resume,因为从resume读入的不是固定值所以,yield的返回值不固定
end
producer=coroutine.create(function()
while true do
print("消费者输入想要获得产品信息")
local x=io.read()
print("读入完毕,开始生产商品"..x)
print("开始发送给消费者")
send(x)
end
end
)
for i=1,10 do
print("这是第"..i.."次请求")
print("这是获得的商品"..receive())
end
]]
--[[
--recieve运行coroutine获得返回值,send使用yield返回值
--pipe,producer都是 return coroutine.create(function end)
--producer获得输入,pipe进行string.format
--使用协同实现管道
function recieve(corout)
local status,value=coroutine.resume(corout)
return value
end
function send(corout)
coroutine.yield(corout)
end
--管道实现
function pipe(corout)
local line=1
return coroutine.create(function()
local x=recieve(corout)
x=string.format("%5d %s",line,x)
line=line+1
send(x)
end
)
end
function producer()
return coroutine.create(function()
while true do
local x=io.read()
send(x)
end
end)
end
function comsumer(corout)
local x=recieve(corout)
io.write(x)
end
for i=1,10 do
p=producer()
--获得producer return的coroutine
p=pipe(p)
--获得pipe return的coroutine
comsumer(p)
--通过receive的resume返回pipe通过recieve的resume返回的producer通过io.read()读入并通过send使用yield返回的值
end
--执行顺序producer>>pipe>>comsumer
]]
--[[
--用coroutine实现迭代器
--[[
function permgen(a,n)
if n==0 then
printResult(a)
else
for i=1,n do
--printResult(a)
print(n)
a[i],a[n]=a[n],a[i]
--printResult(a)
permgen(a,n-1)
print(n)
--不仅内部递归,还内部循环
a[i],a[n]=a[n],a[i]
--printResult(a)
end
end
end
function printResult(a)
for i,v in ipairs(a) do
io.write(v," ")
end
io.write("\n")
end
permgen({"a","b","c"},3)
]]
--将printResult用coroutine.yeild替代,返回的值再用printResult输出
--循环输出 表a
function printResult(a)
for i,v in ipairs(a) do
io.write(v," ")
end
io.write("\n")
end
--迭代器
function permgen(a,n)
if n==0 then
coroutine.yield(a)
else
for i=1,n do
--printResult(a)
print(n)
a[i],a[n]=a[n],a[i]
--printResult(a)
permgen(a,n-1)
print(n)
--不仅内部递归,还内部循环
a[i],a[n]=a[n],a[i]
--printResult(a)
end
end
end
--迭代工厂 return funciton end
function perm(a)
local n=#a
local co=coroutine.create(function() permgen(a,n) end)
return function()
local code,res=coroutine.resume(co)
return res
end
end
for p in perm({"a","b","c"}) do
printResult(p)
end
]]
--[[
--非抢占式多线程
--例子:通过http从远程主机上下载文件使用Luasocket库完成
--安装使用Lua扩展库LuaSocket
--因为luaosck库较新的更新在2007年,似乎不支持最新版的,重装lua为 2006-02-20 5.1版本
[root@localhost ~]# wget http://www.lua.org/ftp/lua-5.1.tar.gz
root@localhost lua]# tar xzvf lua-5.1.tar.gz
修改配置文件config
LUAINC=-I/root/lua-5.1/src
LUALIB=-L/usr/local/lib/lua/5.1
INSTALL_TOP_SHARE=/usr/local/share/lua/5.1
INSTALL_TOP_LIB=/usr/local/lib/lua/5.1
[root@localhost luasocket-2.0]# make
[root@localhost luasocket-2.0]# make install
require "socket"
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)
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
threads = {}
function get(host, file)
-- create coroutine
local co = coroutine.create(function ()
download(host, file)
end)
-- intert it in the list
table.insert(threads, co)
end
function dispatch()
local i = 1
local connections = {}
while true do
if threads[i] == nil then
if threads[1] == nil then
break
end
i = 1 -- restart the loop
connections = {}
end
local status, res = coroutine.resume(threads[i])
if not res then
table.remove(threads, i)
else
i = i + 1
connections[#connections + 1] = res
if #connections == #threads then
socket.select(connections)
end
end
end
end
host = "www.w3.org"
get(host, "/TR/html401/html40.txt")
get(host, "/TR/2002/REC-xhtml1-20020801/xhtml1.pdf")
get(host, "/TR/REC-html32.html")
get(host, "/TR/2000/REC-DOM-Level-2-Core-20001113/DOM2-Core.txt")
dispatch() -- main loop
]]