簡易訊息迴圈

yanghui01發表於2024-08-10

---@class MsgLoop
local MsgLoop = {}
MsgLoop.__cname = "MsgLoop"
MsgLoop.__index = MsgLoop


function MsgLoop.new(maxRunSec)
    local inst = {}
    setmetatable(inst, MsgLoop)
    inst:ctor(maxRunSec)
    return inst
end

function MsgLoop:ctor(maxRunSec)
    self.m_MsgQueue = {}
    self.m_MaxRunSec = maxRunSec or 0
end

---@param callback fun(data:any)
---@param dur number
---@param data any
function MsgLoop:PostRun(callback, dur, data)
    local now = os.time()
    local msg = {
        startTime = now,
        endTime = now + dur,
        cb = callback,
        data = data,
    }
    table.insert(self.m_MsgQueue, msg)
end

---開始訊息迴圈, 執行後, 執行緒將阻塞
function MsgLoop:StartLoop()
    local startTime = os.time()
    while true do
        local now = os.time()
        if self.m_MaxRunSec > 0 and now - startTime >= self.m_MaxRunSec then
            break
        end

        local cnt = #self.m_MsgQueue
        local i = 1
        while i <= cnt do
            local loopItem = self.m_MsgQueue[i]
            local leftTime = loopItem.endTime - now
            if leftTime <= 0 then
                loopItem.cb(loopItem.data)
                table.remove(self.m_MsgQueue, i)
                cnt = cnt - 1
            else
                i = i + 1
            end
        end
        os.execute("ping -n 2 localhost > NUL") --Windows下sleep暫停
        --os.execute("sleep 0.1") -- Unix或Linux中sleep暫停
    end
    print("Msg Loop Exit!", os.time() - startTime)
end

return MsgLoop

使用程式碼

---@type MsgLoop
local MsgLoop = require("MsgLoop")
local _MsgLoop = MsgLoop.new(60)

_MsgLoop:PostRun(function(data)
    --2s後執行
end, 2, "TestData")

--其他邏輯,都要放在StartLoop前,StartLoop啟動後,當前執行緒就在那裡阻塞了

_MsgLoop:StartLoop()

相關文章