我正在编写一个Lua脚本,该脚本使用库来访问带有按钮的硬件设备。我注册了一个回调函数来处理按钮按下。代码如下:
globalvar = {}
function buttonCallback(buttonId)
...accessing globalvar
end
device.RegisterButtonCallback("buttonCallback")
while true do
end
这很有效。
现在我想更新globalvar,不仅要按下按钮,还要每隔1分钟更新一次。因为无论如何我都需要访问网络资源,我打算使用socket.select调用来获得1分钟的间隔。
#require "socket"
globalvar = {}
function buttonCallback(buttonId)
...access globalvar
end
device.RegisterButtonCallback("buttonCallback")
while true do
socket.select(nil, nil, 60) -- wait 60 seconds
...access network
...access globalvar
end
现在我担心globalvar的并发访问。我怎样才能防止这里的竞争条件? Lua中关于多线程的大多数消息来源都建议在协作调度中使用continuation,但我不知道如何在我的情况下应用它。
答案 0 :(得分:2)
假设您正在使用的库是在幕后创建另一个线程,而您唯一关心的是从回调中访问globalvar
,您可以通过写入回调中的管道并阅读来避免它在你的select
循环中来自它。换句话说,使用标准POSIX样式的管道将回调传递回主线程。处理例如,这是一种相当常见的技术。 POSIX信号。
答案 1 :(得分:2)
Lua在特定lua_State
实例中不是线程安全的。您无法从一个线程修改全局变量,而另一个线程正在使用该Lua实例执行其他操作。你当然不能在同一个实例上执行两个单独的脚本。
线程安全是你在Lua之外必须做的事情。你不能让检测按钮的C / C ++线程实际上直接调用Lua代码。它必须通过一些线程安全机制将数据发送到主线程,其中 it 将为它们调用Lua脚本。
答案 2 :(得分:0)
所以我深入研究了Lua书籍和在线文档,并联系了设备驱动程序的作者。正如已经指出的答案,安全地处理按钮回调需要比预期更多。
我现在的方法是自己编写设备驱动程序,并使用套接字作为设备和Lua脚本之间的通信通道。
我最初的方法是使用continuation,因为这被称为多线程的Lua“替换”但是当我在Lua书中阅读编程时,事实证明为了防止繁忙的等待,它使用了socket.select( !)。这增加了我对基于套接字的方法很好的感觉,特别是因为我的脚本中还需要用于访问Internet的套接字。