lua freertos 消息订阅和发布实现

之前有用到合宙luat中的air202模块,热衷于Luat的消息发布和订阅的模式,便准备移植到我的程序中

先看效果

 测试消息订阅发布的主函数

--main.lua
require("msg")
local x = 0
local y = 0
--订阅消息TEST_MSG
subscribe(
    "TEST_MSG",
    function(data)
        y = y + 1
        print("thsi is a test msg1", data.cnt, x, y, x + y, collectgarbage("count"))
    end
)
--订阅消息TEST_MSG
subscribe(
    "TEST_MSG",
    function(data)
        y = y + 1
        print("thsi is a test msg2", data.cnt, x, y, x + y, collectgarbage("count"))
        --在消息回调函数中发布消息
        publish("TEST_MSG_MSG", {param = 12345})
    end
)
--订阅消息TEST_MSG_MSG
subscribe(
    "TEST_MSG_MSG",
    function(data)
        print("thsi is a test msg3", data.cnt, x, y, x + y, collectgarbage("count"))
    end
)
--创建线程
task.run(
    function()
        local z = 0
        while true do
            x = x + 1
            z = z + 1
            publish("TEST_MSG", {param = 4322, cnt = z})
            os.sleep(100)
        end
    end
)

运行结果:

lua freertos 消息订阅和发布实现_第1张图片

 3个消息事件循环执行,满足预期要求。

接下来就是msg.lua文件的实现了。该部分的代码基本上都是沿用 script_LuaTask 中的sys.lua文件中的代码。合宙Luat官网下载

------------------------------------------ LUA应用消息订阅/发布接口 ------------------------------------------
-- 订阅者列表
local subscribers = {}
--内部消息队列
local messageQueue = {}

--- 订阅消息
-- @param id 消息id
-- @param callback 消息回调处理
-- @usage subscribe("NET_STATUS_IND", callback)
function subscribe(id, callback)
    if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then
        --log.warn("warning: sys.subscribe invalid parameter", id, callback)
        return
    end
    if not subscribers[id] then
        subscribers[id] = {}
    end
    subscribers[id][callback] = true
end

--- 取消订阅消息
-- @param id 消息id
-- @param callback 消息回调处理
-- @usage unsubscribe("NET_STATUS_IND", callback)
function unsubscribe(id, callback)
    if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then
        --log.warn("warning: sys.unsubscribe invalid parameter", id, callback)
        return
    end
    if subscribers[id] then
        subscribers[id][callback] = nil
    end
end

--- 发布内部消息,存储在内部消息队列中
-- @param ... 可变参数,用户自定义
-- @return 无
-- @usage publish("NET_STATUS_IND")
function publish(...)
    table.insert(messageQueue, {...})
end

-- 分发消息
local function dispatch()
    while true do
        if #messageQueue == 0 then
            break
        end
        local message = table.remove(messageQueue, 1)
        if subscribers[message[1]] then
            for callback, _ in pairs(subscribers[message[1]]) do
                if type(callback) == "function" then
                    callback(table.unpack(message, 2, #message))
                elseif type(callback) == "thread" then
                --coroutine.resume(callback, table.unpack(message))
                end
            end
        end
    end
end
--启动消息轮询执行线程
task.run(
    function()
        print("启动线程 msg task > run")
        while true do
            dispatch()
            os.sleep(10)
        end
    end
)

其中,添加了dispatch()函数的轮询机制。

注意:

  • 我的多线程不是lua中的协同程序Coroutine。而是FreeRTOS操作系统所提供的多线程。
  •  os.sleep(ms)函数延时也必须是FreeRTOS中的延时函数,能够主动释放和切换FreeRTOS线程上下文。
  • lua协同程序的主要功能是每个协程有自己的堆栈,只要自己主动切换和挂起时其他协程才会被执行。具体参考链接Lua Coroutine详解
  • unpack()函数在5.1版本后修改成了table.unpack(),传入可变参数{...}的获取arg移除了,只能主动获取 local arg={...}

 

 

你可能感兴趣的:(lua)