test-leaks: Fix with Lua 5.1

I have no idea why this needs collectgarbage() to be called twice.

On the other hand, I can explain the change in tooltip.lua. Lua 5.2 introduced
"ephermeron tables". This means that in the following sitation, lua 5.2 can
collect the entry from the table, while 5.1 keeps the entry alive, because the
table has a strong reference to the value and that in turn has a strong
reference to the key:

  t = setmetatable({}, { __mode = "k"})
  do
    local k = {}
    t[k] = function() print(k) end
  end
  collectgarbage("collect")
  print(next(t, nil))

To handle this incompatibility, this commit just removes the whole indirection
through the module-level variable "data".

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-09-27 16:04:20 +02:00
parent 94271e8c91
commit 3e9fdea650
2 changed files with 35 additions and 45 deletions

View File

@ -59,17 +59,6 @@ local ipairs = ipairs
-- @tfield boolean visible True if tooltip is visible. -- @tfield boolean visible True if tooltip is visible.
local tooltip = { mt = {} } local tooltip = { mt = {} }
--- Tooltip private data.
-- @local
-- @table tooltip.data
-- @tfield string fg tooltip foreground color.
-- @tfield string font Tooltip font.
-- @tfield function hide The hide() function.
-- @tfield function show The show() function.
-- @tfield gears.timer timer The text update timer.
-- @tfield function timer_function The text update timer function.
local data = setmetatable({}, { __mode = 'k' })
-- Place the tooltip on the screen. -- Place the tooltip on the screen.
-- @tparam tooltip self A tooltip object. -- @tparam tooltip self A tooltip object.
local function place(self) local function place(self)
@ -98,10 +87,10 @@ end
local function show(self) local function show(self)
-- do nothing if the tooltip is already shown -- do nothing if the tooltip is already shown
if self.visible then return end if self.visible then return end
if data[self].timer then if self.timer then
if not data[self].timer.started then if not self.timer.started then
data[self].timer_function() self.timer_function()
data[self].timer:start() self.timer:start()
end end
end end
set_geometry(self) set_geometry(self)
@ -116,9 +105,9 @@ end
local function hide(self) local function hide(self)
-- do nothing if the tooltip is already hidden -- do nothing if the tooltip is already hidden
if not self.visible then return end if not self.visible then return end
if data[self].timer then if self.timer then
if data[self].timer.started then if self.timer.started then
data[self].timer:stop() self.timer:stop()
end end
end end
self.visible = false self.visible = false
@ -154,8 +143,8 @@ end
-- @tparam tooltip self A tooltip object. -- @tparam tooltip self A tooltip object.
-- @tparam number timeout The timeout value. -- @tparam number timeout The timeout value.
tooltip.set_timeout = function(self, timeout) tooltip.set_timeout = function(self, timeout)
if data[self].timer then if self.timer then
data[self].timer.timeout = timeout self.timer.timeout = timeout
end end
end end
@ -165,8 +154,8 @@ end
-- @tparam gears.object object An object with `mouse::enter` and -- @tparam gears.object object An object with `mouse::enter` and
-- `mouse::leave` signals. -- `mouse::leave` signals.
tooltip.add_to_object = function(self, object) tooltip.add_to_object = function(self, object)
object:connect_signal("mouse::enter", data[self].show) object:connect_signal("mouse::enter", self.show)
object:connect_signal("mouse::leave", data[self].hide) object:connect_signal("mouse::leave", self.hide)
end end
--- Remove tooltip from an object. --- Remove tooltip from an object.
@ -175,8 +164,8 @@ end
-- @tparam gears.object object An object with `mouse::enter` and -- @tparam gears.object object An object with `mouse::enter` and
-- `mouse::leave` signals. -- `mouse::leave` signals.
tooltip.remove_from_object = function(self, object) tooltip.remove_from_object = function(self, object)
object:disconnect_signal("mouse::enter", data[self].show) object:disconnect_signal("mouse::enter", self.show)
object:disconnect_signal("mouse::leave", data[self].hide) object:disconnect_signal("mouse::leave", self.hide)
end end
@ -213,24 +202,24 @@ tooltip.new = function(args)
delay_timeout:stop() delay_timeout:stop()
end) end)
data[self] = { function self.show()
show = function() if not delay_timeout.started then
if not delay_timeout.started then delay_timeout:start()
delay_timeout:start() end
end end
end, function self.hide()
hide = function() if delay_timeout.started then
if delay_timeout.started then delay_timeout:stop()
delay_timeout:stop() end
end hide(self)
hide(self) end
end,
}
else else
data[self] = { function self.show()
show = function() show(self) end, show(self)
hide = function() hide(self) end, end
} function self.hide()
hide(self)
end
end end
-- export functions -- export functions
@ -242,11 +231,11 @@ tooltip.new = function(args)
-- setup the timer action only if needed -- setup the timer action only if needed
if args.timer_function then if args.timer_function then
data[self].timer = timer { timeout = args.timeout and args.timeout or 1 } self.timer = timer { timeout = args.timeout and args.timeout or 1 }
data[self].timer_function = function() self.timer_function = function()
self:set_markup(args.timer_function()) self:set_markup(args.timer_function())
end end
data[self].timer:connect_signal("timeout", data[self].timer_function) self.timer:connect_signal("timeout", self.timer_function)
end end
-- Set default properties -- Set default properties
@ -274,7 +263,7 @@ tooltip.new = function(args)
-- Close the tooltip when clicking it. This gets done on release, to not -- Close the tooltip when clicking it. This gets done on release, to not
-- emit the release event on an underlying object, e.g. the titlebar icon. -- emit the release event on an underlying object, e.g. the titlebar icon.
self.wibox:buttons(abutton({}, 1, nil, function() data[self].hide() end)) self.wibox:buttons(abutton({}, 1, nil, function() self.hide() end))
-- Re-place when the geometry of the wibox changes. -- Re-place when the geometry of the wibox changes.
self.wibox:connect_signal("property::width", function() place(self) end) self.wibox:connect_signal("property::width", function() place(self) end)

View File

@ -29,6 +29,7 @@ local function collectable(a, b, c, d, e, f, g, h, last)
prepare_for_collect = nil prepare_for_collect = nil
end end
collectgarbage("collect") collectgarbage("collect")
collectgarbage("collect")
-- Check if the table is now empty -- Check if the table is now empty
for k, v in pairs(objs) do for k, v in pairs(objs) do
print("Some object was not garbage collected!") print("Some object was not garbage collected!")