Skip to content

Instantly share code, notes, and snippets.

@psychon
Created July 25, 2015 14:45
Show Gist options
  • Save psychon/5e09f11d5d4a76c6ff39 to your computer and use it in GitHub Desktop.
Save psychon/5e09f11d5d4a76c6ff39 to your computer and use it in GitHub Desktop.
diff --git a/lib/gears/object.lua b/lib/gears/object.lua
index 7e3d62b..5ccab05 100644
--- a/lib/gears/object.lua
+++ b/lib/gears/object.lua
@@ -12,6 +12,22 @@ local error = error
local object = { mt = {} }
+--- Call the given callback when the returned object is GC'd
+local create_gc_callback
+do
+ if _VERSION <= "Lua 5.1" then
+ create_gc_callback = function(cb)
+ local obj = newproxy(true)
+ getmetatable(obj).__gc = cb
+ return obj
+ end
+ else
+ create_gc_callback = function(cb)
+ return setmetatable({}, { __gc = cb })
+ end
+ end
+end
+
--- Verify that obj is indeed a valid object as returned by new()
local function check(obj)
if type(obj) ~= "table" or type(obj._signals) ~= "table" then
@@ -59,11 +75,12 @@ end
-- 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)
+-- @param[opt] gc_func The callback to call when the signal is disconnected
+function object:weak_connect_signal(name, func, gc_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
+ sig.weak[func] = gc_func and create_gc_callback(gc_func) or true
end
--- Disonnect to a signal
diff --git a/spec/gears/object_spec.lua b/spec/gears/object_spec.lua
index 692e9fd..b992e5a 100644
--- a/spec/gears/object_spec.lua
+++ b/spec/gears/object_spec.lua
@@ -110,6 +110,22 @@ describe("gears.object", function()
assert.is_false(called)
end)
+ it("weak auto disconnect callback", function()
+ local gc_called = 0
+ obj:weak_connect_signal("signal", function()
+ end, function()
+ gc_called = gc_called + 1
+ end)
+
+ assert.is.equal(0, gc_called)
+
+ -- First collection disconnects, seconds calls callback
+ collectgarbage("collect")
+ collectgarbage("collect")
+
+ assert.is.equal(1, gc_called)
+ end)
+
it("strong connect after weak connect", function()
local function cb() end
obj:weak_connect_signal("signal", cb)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment