协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,协同有三个状态:挂起态、运行态、停止态。
- co=coroutine.create( --coroutine协同,create创建协同程序。
- function() --匿名函数
- --print("hi")
- for i=1,10 do
- print("co",i)
- coroutine.yield() --挂起
- end
- end)
- print(co)
- print(coroutine.status(co)) --打印协同的状态
- coroutine.resume(co) --运行挂起的协同程序
- coroutine.resume(co)
- print(coroutine.status(co))
管道和过滤器:
- function receive (prod)
- local status, value = coroutine.resume(prod)
- return value
- end
- function send (x)
- coroutine.yield(x)
- end
- function producer ()
- return coroutine.create(function ()
- while true do
- local x = io.read() -- produce new value
- send(x) --send to consumer
- end
- end)
- end
- function filter (prod)
- return coroutine.create(function ()
- local line = 1
- while true do
- local x = receive(prod) -- get new value
- x = string.format("%5d %s", line, x)
- send(x) -- send it to consumer
- line = line + 1
- end
- end)
- end
- function consumer (prod)
- while true do
- local x = receive(prod) -- get new value
- io.write(x, "\n") -- consume new value
- end
- end
- p = producer()
- f = filter(p)
- consumer(f)
用作迭代器的协同:
- function permgen(a,n)
- if n==0 then
- coroutine.yield(a)
- else
- for i=1,n do
- a[n],a[i]=a[i],a[n]
- permgen(a,n-1)
- a[n],a[i]=a[i],a[n]
- end
- end
- end
- function printResult(a)
- for i,v in ipairs(a) do
- io.write(v," ")
- end
- io.write("\n")
- end
- function perm(a)
- local n=table.getn(a)
- local co=coroutine.create(function() permgen(a,n) end)
- --local co=coroutine.wrap(function() permgen(a,n) end) --wrap返回一个函数,可以抛出错误
- return function()
- local code,res=coroutine.resume(co)
- return res
- end
- end
- for p in perm{"a","b","c"} do
- printResult(p)
- end
非抢占式多线程:
- require "luasocket"
- 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=receive
- count=count+string.len(s)
- if status=="closed" then break end
- end
- c:close()
- print(file,count)
- end
- function receive(connection)
- --return connection:receive(2^10)
- connection:timeout(0) --timeout(0)对链接的任何操作都不会阻塞
- local s,status=connection:receive(2^10)
- if status=="timeout" then
- coroutine.yield(connection)
- end
- return s,status
- end
- threads={}
- function get(host,file)
- local co=coroutine.create(
- function()
- download(host,file)
- end
- )
- table.insert(threads,co)
- end
- function dispatcher()
- while true do
- local n=table.getn(threads)
- if n==0 then break end
- for i=1,n do
- local status, res=coroutine.resume(threads[i])
- if not res then
- table.remove(threads,i)
- break
- end
- end
- end
- end
- host="www.w3c.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")
- dispatcher()