gears.object: Add :weak_connect_signal()
Connecting to a signal weakly has the same effect as connecting to it strongly, but it allows the garbage collector to disconnect the signal in case nothing else references this function. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
38840c911b
commit
089ed0e8dd
|
@ -38,7 +38,10 @@ function object:add_signal(name)
|
|||
check(self)
|
||||
assert(type(name) == "string", "name must be a string, got: " .. type(name))
|
||||
if not self._signals[name] then
|
||||
self._signals[name] = {}
|
||||
self._signals[name] = {
|
||||
strong = {},
|
||||
weak = setmetatable({}, { __mode = "k" })
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -48,7 +51,19 @@ end
|
|||
function object:connect_signal(name, func)
|
||||
assert(type(func) == "function", "callback must be a function, got: " .. type(func))
|
||||
local sig = find_signal(self, name, "connect to")
|
||||
sig[func] = func
|
||||
assert(sig.weak[func] == nil, "Trying to connect a strong callback which is already connected weakly")
|
||||
sig.strong[func] = true
|
||||
end
|
||||
|
||||
--- Connect to a signal weakly. This allows the callback function to be garbage
|
||||
-- collected and automatically disconnects the signal when that happens.
|
||||
-- @param name The name of the signal
|
||||
-- @param func The callback to call when the signal is emitted
|
||||
function object:weak_connect_signal(name, func)
|
||||
assert(type(func) == "function", "callback must be a function, got: " .. type(func))
|
||||
local sig = find_signal(self, name, "connect to")
|
||||
assert(sig.strong[func] == nil, "Trying to connect a weak callback which is already connected strongly")
|
||||
sig.weak[func] = true
|
||||
end
|
||||
|
||||
--- Disonnect to a signal
|
||||
|
@ -56,7 +71,8 @@ end
|
|||
-- @param func The callback that should be disconnected
|
||||
function object:disconnect_signal(name, func)
|
||||
local sig = find_signal(self, name, "disconnect from")
|
||||
sig[func] = nil
|
||||
sig.weak[func] = nil
|
||||
sig.strong[func] = nil
|
||||
end
|
||||
|
||||
--- Emit a signal
|
||||
|
@ -67,7 +83,10 @@ end
|
|||
-- that are given to emit_signal()
|
||||
function object:emit_signal(name, ...)
|
||||
local sig = find_signal(self, name, "emit")
|
||||
for func in pairs(sig) do
|
||||
for func in pairs(sig.strong) do
|
||||
func(self, ...)
|
||||
end
|
||||
for func in pairs(sig.weak) do
|
||||
func(self, ...)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,13 +12,19 @@ describe("gears.object", function()
|
|||
obj:add_signal("signal")
|
||||
end)
|
||||
|
||||
it("connect non-existent signal", function()
|
||||
it("strong connect non-existent signal", function()
|
||||
assert.has.errors(function()
|
||||
obj:connect_signal("foo", function() end)
|
||||
end)
|
||||
end)
|
||||
|
||||
it("disconnect non-existent signal", function()
|
||||
it("weak connect non-existent signal", function()
|
||||
assert.has.errors(function()
|
||||
obj:weak_connect_signal("foo", function() end)
|
||||
end)
|
||||
end)
|
||||
|
||||
it("strong disconnect non-existent signal", function()
|
||||
assert.has.errors(function()
|
||||
obj:disconnect_signal("foo", function() end)
|
||||
end)
|
||||
|
@ -30,16 +36,27 @@ describe("gears.object", function()
|
|||
end)
|
||||
end)
|
||||
|
||||
it("connecting and emitting signal", function()
|
||||
it("strong connecting and emitting signal", function()
|
||||
local called = false
|
||||
obj:connect_signal("signal", function()
|
||||
local function cb()
|
||||
called = true
|
||||
end)
|
||||
end
|
||||
obj:connect_signal("signal", cb)
|
||||
obj:emit_signal("signal")
|
||||
assert.is_true(called)
|
||||
end)
|
||||
|
||||
it("connecting, disconnecting and emitting signal", function()
|
||||
it("weak connecting and emitting signal", function()
|
||||
local called = false
|
||||
local function cb()
|
||||
called = true
|
||||
end
|
||||
obj:weak_connect_signal("signal", cb)
|
||||
obj:emit_signal("signal")
|
||||
assert.is_true(called)
|
||||
end)
|
||||
|
||||
it("strong connecting, disconnecting and emitting signal", function()
|
||||
local called = false
|
||||
local function cb()
|
||||
called = true
|
||||
|
@ -50,13 +67,64 @@ describe("gears.object", function()
|
|||
assert.is_false(called)
|
||||
end)
|
||||
|
||||
it("weak connecting, disconnecting and emitting signal", function()
|
||||
local called = false
|
||||
local function cb()
|
||||
called = true
|
||||
end
|
||||
obj:weak_connect_signal("signal", cb)
|
||||
obj:disconnect_signal("signal", cb)
|
||||
obj:emit_signal("signal")
|
||||
assert.is_false(called)
|
||||
end)
|
||||
|
||||
it("arguments to signal", function()
|
||||
obj:connect_signal("signal", function(arg1, arg2)
|
||||
assert.is.equal(obj, arg1)
|
||||
assert.is.same(42, arg2)
|
||||
end)
|
||||
obj:weak_connect_signal("signal", function(arg1, arg2)
|
||||
assert.is.equal(obj, arg1)
|
||||
assert.is.same(42, arg2)
|
||||
end)
|
||||
obj:emit_signal("signal", 42)
|
||||
end)
|
||||
|
||||
it("strong non-auto disconnect", function()
|
||||
local called = false
|
||||
obj:connect_signal("signal", function()
|
||||
called = true
|
||||
end)
|
||||
collectgarbage("collect")
|
||||
obj:emit_signal("signal")
|
||||
assert.is_true(called)
|
||||
end)
|
||||
|
||||
it("weak auto disconnect", function()
|
||||
local called = false
|
||||
obj:weak_connect_signal("signal", function()
|
||||
called = true
|
||||
end)
|
||||
collectgarbage("collect")
|
||||
obj:emit_signal("signal")
|
||||
assert.is_false(called)
|
||||
end)
|
||||
|
||||
it("strong connect after weak connect", function()
|
||||
local function cb() end
|
||||
obj:weak_connect_signal("signal", cb)
|
||||
assert.has.errors(function()
|
||||
obj:connect_signal("signal", cb)
|
||||
end)
|
||||
end)
|
||||
|
||||
it("weak connect after strong connect", function()
|
||||
local function cb() end
|
||||
obj:connect_signal("signal", cb)
|
||||
assert.has.errors(function()
|
||||
obj:weak_connect_signal("signal", cb)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
Loading…
Reference in New Issue