我正在为一些应用程序编写扩展/插件。
在其文档中,据说插件有两个线程:
-所有业务逻辑必须存在的"主线程"
-"回调线程",应用程序通过事件调用具有预定义名称的回调,这些回调不能做复杂的事情,并尽快返回
文档不是很清楚,所以可能不是从一个线程而是从多个线程调用回调。
我写过伪互斥,它的工作原理是:
Mutex = class {
_lock = function(self, owner)
assert(owner, 'owner must be set')
local ts = Timestamp.get()
local key = tostring(owner) .. ' ' .. tostring(ts)
self[key] = ts
for k, v in pairs(self) do
if k ~= key and v <= ts then
self[key] = nil
return false
end
end
return key
end,
lock = function(self, owner, wait)
local wait = wait or 0.01
local k
repeat
k = self:_lock(owner)
if k then return k else sleep(wait) end
until k
end,
unlock = function(self, key)
self[key] = nil
end
}
并使用它来制作线程安全队列,如下所示:
ThreadSafeQueue = class {
new = function(cls)
return getmetatable(cls).new(cls, {
mx_queue = Mutex:new(),
mx_push = Mutex:new(),
})
end,
pop = function(self)
local lock_queue = self.mx_queue:lock(self)
local val
if #self then
val = table.remove(self, 1)
else
val = nil
end
self.mx_queue:unlock(lock_queue)
return val
end,
push = function(self, val)
if val == nil then return end
-- don't `push()` from few threads at the same time
local lock_push = self.mx_push:lock(val)
-- don't `pop()` when `push()` and `push()` when `pop()`
local lock_queue = self.mx_queue:lock(self)
self[#self + 1] = val
self.mx_queue:unlock(lock_queue)
self.mx_push:unlock(lock_push)
end
}
这里的class
是返回具有原型查找的对象的助手,:new()
是设置元表的方法。
主要问题是我不确定pairs()
的作用
-若原始表在迭代时会被修改,这个循环会至少返回旧状态吗
-在这种情况下,某些k
、v
是否可能不迭代?
另一个问题是我为之编写的应用程序真的是黑盒,我甚至不确定它会在哪个操作系统上运行(Win、Mac、Linux)
我所知道的一切100%都有线程和socket
模块。
你能复习一下提供的代码吗
它行得通吗?
互斥还有其他可能吗
也许socket
会有所贡献?
套接字选项:
尝试创建套接字,如果成功,则互斥锁被锁定,否则-等待关闭
local Mutex = class {
identities = {},
new = function(cls, identity)
assert(not cls.identities[identity])
local inst = getmetatable(cls).new(cls, {
port = identity,
server = nil
})
cls.identities[identity] = inst
return inst
end,
lock = function(self, wait)
local wait = wait or 0.01
local server
local ts = Timestamp.get()
repeat
server = socket.bind("*", self.port)
if server then
self.server = server
return true
else
sleep(wait)
end
assert(Timestamp.get() - ts < 3, 'deadlock')
until server
end,
unlock = function(self)
self.server:close()
self.server = nil
end
}