chuck-lua支持actor模式的線程模型.可以通過cthread.new創建線程,然后通過cthread.sendmail向線程發送消息.
與skynet這種框架不同,chuck-lua并不提供多線程的任務/消息調度功能,每個線程維護了一個簡單的線程郵箱,用于緩存其它線程發過來的消息.
下面看一個簡單的多線程服務器示例:
mtserver.lua
local chuck = require("chuck")
local engine = require("distri.engine")
local socket_helper = chuck.socket_helper
local Distri = require("distri.distri")
local cthread = chuck.cthread
local worker
function on_new_client(fd)
cthread.sendmail(worker,{fd})
end
local fd = socket_helper.socket(socket_helper.AF_INET,
socket_helper.SOCK_STREAM,
socket_helper.IPPROTO_TCP)
socket_helper.addr_reuse(fd,1)
local ip = "127.0.0.1"
local port = 8010
if 0 == socket_helper.listen(fd,ip,port) then
print("server start",ip,port)
local server = chuck.acceptor(fd)
server:Add2Engine(engine,on_new_client)
Distri.Signal(chuck.signal.SIGINT,Distri.Stop)
worker = cthread.new("distri/test/worker.lua")
Distri.Run()
end
worker.lua
local chuck = require("chuck")
local socket = require("distri.socket")
local engine = require("distri.engine")
local clone = chuck.packet.clone
local cthread = chuck.cthread
local Distri = require("distri.distri")
--設置郵件處理函數
cthread.process_mail(engine,function (sender,mail)
local fd = table.unpack(mail)
local s = socket.stream.New(fd)
if s:Ok(4096,socket.stream.decoder.rawpacket(),function (_,msg,errno)
if msg then
s:Send(clone(msg))
else
s:Close(errno)
s = nil
end
end) then
s:SetRecvTimeout(5000)
else
s:Close()
end
end)
Distri.Run()
這個示例很簡單,主線程啟動監聽,創建一個線程,當接收到連接時就將fd發送給worker線程.
在這里需要簡單介紹一下chuck-lua線程相關的一些細節.
因為各線程跑在獨立的虛擬機上,因此無法直接通過消息的方式將一個虛擬機中的對象發送到另一個線程中.目前sendmail將作為消息傳遞給它的lua table序列化為一種適合傳輸的對象,目標線程接收這個對象之后再重新轉化成本線程虛擬機中的lua table.目前消息支持lua中的所有基本類型,但為了安全考慮,不支持直接傳遞userdata類型.
用cthread.sendmail向目標線程發送消息時,如果到達目標郵箱的緩沖上線將會阻塞.所有期望處理郵件消息的線程都必須調用cthread.process_mail設定消息回調函數.如果不設定,將可能導致消息發送線程永久阻塞.
線程使用join模式創建,創建者可以通過cthread.join等待線程的結束.
以上所述就是本文的全部內容了,希望大家能夠喜歡。