使用`to-be-close`特性来实现协程锁
· 阅读需 2 分钟
最近有个想法,想使用Lua5.4的特性to-be-close
来实现协程锁。 moon中版本的实现是要单独把同步的流程放到一个函数中,然后排队,这样就有一个缺点:不能有返回值。 所以想用to-be-close
配和协程挂起来实现,代码也非常简单。
queue.lua
local status = coroutine.status
local running = coroutine.running
local yield = coroutine.yield
local resume = coroutine.resume
local make_queue = make_queue
local queue_push = queue_push
local queue_pop = queue_pop
local M = {}
M.__index = M
function M.new()
local obj = {}
obj.queue = make_queue()
return setmetatable(obj,M)
end
function M.scope_lock(self)
if self.thread and status(self.thread) ~= "dead" then
queue_push(self.queue, (running()))
yield()
end
self.thread = running()
return setmetatable({}, { __close = function()
local co = queue_pop(self.queue)
if co then
resume(co)
end
end})
end
return M
使用示例
local moon = require("moon")
local queue = require("queue")
local mutex = queue.new()
moon.async(function()
local lock<close> = mutex.scope_lock(mutex)
moon.sleep(10000)
print("run step 1")
end)
moon.async(function()
local lock<close> = mutex.scope_lock(mutex)
moon.sleep(5000)
assert(false)
print("run step 2")
end)
moon.async(function()
local lock<close> = mutex.scope_lock(mutex)
moon.sleep(1000)
print("run step 3")
end)
moon.async(function()
local lock<close> = mutex.scope_lock(mutex)
moon.sleep(500)
print("run step 4")
end)
会按调用流程执行,输出
run step 1
run step 2
run step 3
run step 4