lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Sat, Jul 30, 2011 at 7:31 PM, Gregory Bonik <gregory@bonik.org> wrote:
Gaspard Bucher wrote:

> The garbage collection is:
>
>
> Lua ---> userdata ---> fenv ---> thread --> function
>
>
> Since the function is not stored in a global table (as you do
> with luaL_ref), gc management is easy.
>

This sounds reasonable but is still not an acceptable solution for me.
The problem is that my C++ objects are internally reference-counted and
can hold references on each other. For example, a container UI widget
holds references on its children. Consider the following code:

-- Get a container widget that is already created in C++:
local container = get_container()

-- Create a new button:
local button = Button()

-- Set the callback:
button:on_click(function() button:some_method() end)

-- Pack the button into the container.
-- Container adds a reference on the button internally.
container:add_child(button)

-- Forget about the button
button = nil

-- The callback will be collected now, but it shouldn't!
-- Button's userdata will be collected too, but its C++
-- object will still be alive.
collectgarbage("collect")


-- Gregory Bonik


I do not think this is a show stopper: there are solutions that do not require reference counting for this "collected too soon" issue:

a. You could make your container store a reference to the Lua object it stores and let Lua take care of memory issues (this could be done in the Lua interface to the container).
b. You could make your C++ objects truly deletable from Lua (button deleted => removed from container or use a smart pointer based container storage) and have users take care of keeping their widgets at hand (what is the use of a widget created from Lua but not reachable any more ?).

Before switching to Lua for message passing in Lubyk, I had implemented a complex stack of C++, reference counted variant objects in the oscit library [1]. Doing this correctly with a few mockups was easy, managing the whole system when complexity increased started to look like writing a new (badly conceived) scripting language. AFAIK there are good reasons why mark and sweep (generational) garbage collection systems are used in favor of reference counted memory management and the easiest way to use one in this case, is to keep the objects visible from Lua...

Reference counting seems ok in libraries like OpenCV where the type of objects does not permit circular references but I would never use reference counting for a graphical interface widgets...


                                                               Gaspard

[1] https://github.com/rubyk/oscit