-
Notifications
You must be signed in to change notification settings - Fork 55
/
safe.lua
67 lines (60 loc) · 1.63 KB
/
safe.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
-- utility for lua 5.2
local setfenv = setfenv or
function(fn, env)
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
local function newproxygc(func)
local proxy
if newproxy then -- 5.1
proxy = newproxy(true)
getmetatable(proxy).__gc = func
else -- 5.2
proxy = {}
setmetatable(proxy, {__gc=func})
end
return proxy
end
return function(func, mutex)
local threads = require 'threads'
assert(type(func) == 'function', 'function, [mutex] expected')
assert(mutex == nil or getmetatable(threads.Mutex).__index == getmetatable(mutex).__index, 'function, [mutex] expected')
-- make sure mutex is freed if it is our own
local proxy
if not mutex then
mutex = threads.Mutex()
proxy = newproxygc(
function()
mutex:free()
end
)
end
local mutexid = mutex:id()
local safe =
function(...)
local threads = require 'threads'
local mutex = threads.Mutex(mutexid)
local unpack = unpack or table.unpack
mutex:lock()
local res = {func(...)}
mutex:unlock()
return unpack(res)
end
-- make sure mutex is freed if it is our own
if proxy then
setfenv(safe, {require=require, unpack=unpack, table=table, proxy=proxy})
end
return safe
end