luaclass: take care of inheritance garbage collection
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
92717a0849
commit
f7746a198c
|
@ -163,11 +163,31 @@ luaA_class_add_property(lua_class_t *lua_class,
|
|||
});
|
||||
}
|
||||
|
||||
/** Garbage collect a Lua object.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
*/
|
||||
static int
|
||||
luaA_class_gc(lua_State *L)
|
||||
{
|
||||
lua_object_t *item = lua_touserdata(L, 1);
|
||||
signal_array_wipe(&item->signals);
|
||||
/* Get the object class */
|
||||
lua_class_t *class = luaA_class_get(L, 1);
|
||||
/* Call the collector function of the class, and all its parent classes */
|
||||
for(; class; class = class->parent)
|
||||
if(class->collector)
|
||||
class->collector(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Setup a new Lua class.
|
||||
* \param L The Lua VM state.
|
||||
* \param name The class name.
|
||||
* \param parent The parent class (inheritance).
|
||||
* \param allocator The allocator function used when creating a new object.
|
||||
* \param Collector The collector function used when garbage collecting an
|
||||
* object.
|
||||
* \param checker The check function to call when using luaA_checkudata().
|
||||
* \param index_miss_property Function to call when an object of this class
|
||||
* receive a __index request on an unknown property.
|
||||
|
@ -181,18 +201,19 @@ luaA_class_setup(lua_State *L, lua_class_t *class,
|
|||
const char *name,
|
||||
lua_class_t *parent,
|
||||
lua_class_allocator_t allocator,
|
||||
lua_class_collector_t collector,
|
||||
lua_class_checker_t checker,
|
||||
lua_class_propfunc_t index_miss_property,
|
||||
lua_class_propfunc_t newindex_miss_property,
|
||||
const struct luaL_reg methods[],
|
||||
const struct luaL_reg meta[])
|
||||
{
|
||||
/* Create the metatable */
|
||||
/* Create the object metatable */
|
||||
lua_newtable(L);
|
||||
/* Register it with class pointer as key in the registry
|
||||
* class-pointer -> metatable */
|
||||
lua_pushlightuserdata(L, class);
|
||||
/* Duplicate the metatable */
|
||||
/* Duplicate the object metatable */
|
||||
lua_pushvalue(L, -2);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
/* Now register class pointer with metatable as key in the registry
|
||||
|
@ -201,7 +222,12 @@ luaA_class_setup(lua_State *L, lua_class_t *class,
|
|||
lua_pushlightuserdata(L, class);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_pushvalue(L, -1); /* dup metatable 2 */
|
||||
/* Duplicate objects metatable */
|
||||
lua_pushvalue(L, -1);
|
||||
/* Set garbage collector in the metatable */
|
||||
lua_pushcfunction(L, luaA_class_gc);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
|
||||
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable 1 */
|
||||
|
||||
luaL_register(L, NULL, meta); /* 1 */
|
||||
|
@ -210,6 +236,7 @@ luaA_class_setup(lua_State *L, lua_class_t *class,
|
|||
lua_setmetatable(L, -2); /* set self as metatable 2 */
|
||||
lua_pop(L, 2);
|
||||
|
||||
class->collector = collector;
|
||||
class->allocator = allocator;
|
||||
class->name = name;
|
||||
class->index_miss_property = index_miss_property;
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct
|
|||
} lua_object_t;
|
||||
|
||||
typedef lua_object_t *(*lua_class_allocator_t)(lua_State *);
|
||||
typedef void (*lua_class_collector_t)(lua_object_t *);
|
||||
|
||||
typedef int (*lua_class_propfunc_t)(lua_State *, lua_object_t *);
|
||||
|
||||
|
@ -57,6 +58,8 @@ struct lua_class_t
|
|||
lua_class_t *parent;
|
||||
/** Allocator for creating new objects of that class */
|
||||
lua_class_allocator_t allocator;
|
||||
/** Garbage collection function */
|
||||
lua_class_collector_t collector;
|
||||
/** Class properties */
|
||||
lua_class_property_array_t properties;
|
||||
/** Function to call when a indexing an unknown property */
|
||||
|
@ -76,7 +79,8 @@ void luaA_class_emit_signal(lua_State *, lua_class_t *, const char *, int);
|
|||
|
||||
void luaA_openlib(lua_State *, const char *, const struct luaL_reg[], const struct luaL_reg[]);
|
||||
void luaA_class_setup(lua_State *, lua_class_t *, const char *, lua_class_t *,
|
||||
lua_class_allocator_t, lua_class_checker_t,
|
||||
lua_class_allocator_t, lua_class_collector_t,
|
||||
lua_class_checker_t,
|
||||
lua_class_propfunc_t, lua_class_propfunc_t,
|
||||
const struct luaL_reg[], const struct luaL_reg[]);
|
||||
|
||||
|
|
|
@ -300,16 +300,4 @@ luaA_object_tostring(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** Garbage collect a Lua object.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack.
|
||||
*/
|
||||
int
|
||||
luaA_object_gc(lua_State *L)
|
||||
{
|
||||
lua_object_t *item = lua_touserdata(L, 1);
|
||||
signal_array_wipe(&item->signals);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
||||
|
|
|
@ -191,7 +191,6 @@ int luaA_object_emit_signal_simple(lua_State *);
|
|||
}
|
||||
|
||||
int luaA_object_tostring(lua_State *);
|
||||
int luaA_object_gc(lua_State *);
|
||||
|
||||
#define LUA_OBJECT_META(prefix) \
|
||||
{ "__tostring", luaA_object_tostring }, \
|
||||
|
|
|
@ -110,12 +110,11 @@ button_class_setup(lua_State *L)
|
|||
{
|
||||
LUA_OBJECT_META(button)
|
||||
LUA_CLASS_META
|
||||
{ "__gc", luaA_object_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &button_class, "button", NULL,
|
||||
(lua_class_allocator_t) button_new, NULL,
|
||||
(lua_class_allocator_t) button_new, NULL, NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
button_methods, button_meta);
|
||||
luaA_class_add_property(&button_class, A_TK_BUTTON,
|
||||
|
|
|
@ -38,10 +38,9 @@
|
|||
* \param L The Lua VM state.
|
||||
* \return The number of element pushed on stack.
|
||||
*/
|
||||
static int
|
||||
luaA_client_gc(lua_State *L)
|
||||
static void
|
||||
client_wipe(client_t *c)
|
||||
{
|
||||
client_t *c = luaA_checkudata(L, 1, &client_class);
|
||||
button_array_wipe(&c->buttons);
|
||||
key_array_wipe(&c->keys);
|
||||
xcb_get_wm_protocols_reply_wipe(&c->protocols);
|
||||
|
@ -52,7 +51,6 @@ luaA_client_gc(lua_State *L)
|
|||
p_delete(&c->alt_icon_name);
|
||||
p_delete(&c->name);
|
||||
p_delete(&c->alt_name);
|
||||
return luaA_object_gc(L);
|
||||
}
|
||||
|
||||
/** Change the clients urgency flag.
|
||||
|
@ -2031,12 +2029,12 @@ client_class_setup(lua_State *L)
|
|||
{ "raise", luaA_client_raise },
|
||||
{ "lower", luaA_client_lower },
|
||||
{ "unmanage", luaA_client_unmanage },
|
||||
{ "__gc", luaA_client_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &client_class, "client", &window_class,
|
||||
(lua_class_allocator_t) client_new,
|
||||
(lua_class_collector_t) client_wipe,
|
||||
(lua_class_checker_t) client_checker,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
client_methods, client_meta);
|
||||
|
|
|
@ -42,14 +42,12 @@ struct image
|
|||
|
||||
LUA_OBJECT_FUNCS(image_class, image_t, image)
|
||||
|
||||
static int
|
||||
luaA_image_gc(lua_State *L)
|
||||
static void
|
||||
image_wipe(image_t *image)
|
||||
{
|
||||
image_t *p = luaA_checkudata(L, 1, &image_class);
|
||||
imlib_context_set_image(p->image);
|
||||
imlib_context_set_image(image->image);
|
||||
imlib_free_image();
|
||||
p_delete(&p->data);
|
||||
return luaA_object_gc(L);
|
||||
p_delete(&image->data);
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -816,12 +814,13 @@ image_class_setup(lua_State *L)
|
|||
{ "draw_rectangle", luaA_image_draw_rectangle },
|
||||
{ "draw_rectangle_gradient", luaA_image_draw_rectangle_gradient },
|
||||
{ "draw_circle", luaA_image_draw_circle },
|
||||
{ "__gc", luaA_image_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &image_class, "image", NULL,
|
||||
(lua_class_allocator_t) image_new, NULL,
|
||||
(lua_class_allocator_t) image_new,
|
||||
(lua_class_collector_t) image_wipe,
|
||||
NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
image_methods, image_meta);
|
||||
luaA_class_add_property(&image_class, A_TK_WIDTH,
|
||||
|
|
|
@ -1122,12 +1122,11 @@ key_class_setup(lua_State *L)
|
|||
{
|
||||
LUA_OBJECT_META(key)
|
||||
LUA_CLASS_META
|
||||
{ "__gc", luaA_object_gc },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &key_class, "key", NULL,
|
||||
(lua_class_allocator_t) key_new, NULL,
|
||||
(lua_class_allocator_t) key_new, NULL, NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
key_methods, key_meta);
|
||||
luaA_class_add_property(&key_class, A_TK_KEY,
|
||||
|
|
|
@ -50,17 +50,11 @@ tag_unref_simplified(tag_t **tag)
|
|||
luaA_object_unref(globalconf.L, *tag);
|
||||
}
|
||||
|
||||
/** Garbage collect a tag.
|
||||
* \param L The Lua VM state.
|
||||
* \return 0.
|
||||
*/
|
||||
static int
|
||||
luaA_tag_gc(lua_State *L)
|
||||
static void
|
||||
tag_wipe(tag_t *tag)
|
||||
{
|
||||
tag_t *tag = luaA_checkudata(L, 1, &tag_class);
|
||||
client_array_wipe(&tag->clients);
|
||||
p_delete(&tag->name);
|
||||
return luaA_object_gc(L);
|
||||
}
|
||||
|
||||
OBJECT_EXPORT_PROPERTY(tag, tag_t, selected)
|
||||
|
@ -413,12 +407,13 @@ tag_class_setup(lua_State *L)
|
|||
LUA_OBJECT_META(tag)
|
||||
LUA_CLASS_META
|
||||
{ "clients", luaA_tag_clients },
|
||||
{ "__gc", luaA_tag_gc },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &tag_class, "tag", NULL,
|
||||
(lua_class_allocator_t) tag_new, NULL,
|
||||
(lua_class_allocator_t) tag_new,
|
||||
(lua_class_collector_t) tag_wipe,
|
||||
NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
tag_methods, tag_meta);
|
||||
luaA_class_add_property(&tag_class, A_TK_NAME,
|
||||
|
|
|
@ -118,12 +118,11 @@ timer_class_setup(lua_State *L)
|
|||
LUA_CLASS_META
|
||||
{ "start", luaA_timer_start },
|
||||
{ "stop", luaA_timer_stop },
|
||||
{ "__gc", luaA_object_gc },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &timer_class, "timer", NULL,
|
||||
(lua_class_allocator_t) timer_new, NULL,
|
||||
(lua_class_allocator_t) timer_new, NULL, NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
timer_methods, timer_meta);
|
||||
luaA_class_add_property(&timer_class, A_TK_TIMEOUT,
|
||||
|
|
|
@ -37,7 +37,7 @@ LUA_OBJECT_FUNCS(wibox_class, wibox_t, wibox)
|
|||
* \param w The wibox to wipe.
|
||||
*/
|
||||
static void
|
||||
wibox_wipe(wibox_t *w)
|
||||
wibox_wipe_resources(wibox_t *w)
|
||||
{
|
||||
if(w->window)
|
||||
{
|
||||
|
@ -61,19 +61,13 @@ wibox_wipe(wibox_t *w)
|
|||
draw_context_wipe(&w->ctx);
|
||||
}
|
||||
|
||||
/** Take care of garbage collecting a wibox.
|
||||
* \param L The Lua VM state.
|
||||
* \return The number of elements pushed on stack, 0!
|
||||
*/
|
||||
static int
|
||||
luaA_wibox_gc(lua_State *L)
|
||||
static void
|
||||
wibox_wipe(wibox_t *wibox)
|
||||
{
|
||||
wibox_t *wibox = luaA_checkudata(L, 1, &wibox_class);
|
||||
p_delete(&wibox->cursor);
|
||||
wibox_wipe(wibox);
|
||||
wibox_wipe_resources(wibox);
|
||||
button_array_wipe(&wibox->buttons);
|
||||
widget_node_array_wipe(&wibox->widgets);
|
||||
return luaA_object_gc(L);
|
||||
}
|
||||
|
||||
/** Wipe an array of widget_node. Release references to widgets.
|
||||
|
@ -702,7 +696,7 @@ wibox_detach(lua_State *L, int udx)
|
|||
|
||||
wibox_clear_mouse_over(wibox);
|
||||
|
||||
wibox_wipe(wibox);
|
||||
wibox_wipe_resources(wibox);
|
||||
|
||||
foreach(item, globalconf.wiboxes)
|
||||
if(*item == wibox)
|
||||
|
@ -1318,12 +1312,13 @@ wibox_class_setup(lua_State *L)
|
|||
LUA_CLASS_META
|
||||
{ "buttons", luaA_wibox_buttons },
|
||||
{ "geometry", luaA_wibox_geometry },
|
||||
{ "__gc", luaA_wibox_gc },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &wibox_class, "wibox", &window_class,
|
||||
(lua_class_allocator_t) wibox_new, NULL,
|
||||
(lua_class_allocator_t) wibox_new,
|
||||
(lua_class_collector_t) wibox_wipe,
|
||||
NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
wibox_methods, wibox_meta);
|
||||
luaA_class_add_property(&wibox_class, A_TK_WIDGETS,
|
||||
|
|
|
@ -35,18 +35,12 @@
|
|||
|
||||
LUA_OBJECT_FUNCS(widget_class, widget_t, widget);
|
||||
|
||||
/** Collect a widget structure.
|
||||
* \param L The Lua VM state.
|
||||
* \return 0
|
||||
*/
|
||||
static int
|
||||
luaA_widget_gc(lua_State *L)
|
||||
static void
|
||||
widget_wipe(widget_t *widget)
|
||||
{
|
||||
widget_t *widget = luaA_checkudata(L, 1, &widget_class);
|
||||
if(widget->destructor)
|
||||
widget->destructor(widget);
|
||||
button_array_wipe(&widget->buttons);
|
||||
return luaA_object_gc(L);
|
||||
}
|
||||
|
||||
/** Get a widget node from a wibox by coords.
|
||||
|
@ -574,13 +568,13 @@ widget_class_setup(lua_State *L)
|
|||
{ "extents", luaA_widget_extents },
|
||||
{ "__index", luaA_widget_index },
|
||||
{ "__newindex", luaA_widget_newindex },
|
||||
{ "__gc", luaA_widget_gc },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
luaA_class_setup(L, &widget_class, "widget", NULL,
|
||||
(lua_class_allocator_t) widget_new, NULL,
|
||||
NULL, NULL,
|
||||
(lua_class_allocator_t) widget_new,
|
||||
(lua_class_collector_t) widget_wipe,
|
||||
NULL, NULL, NULL,
|
||||
widget_methods, widget_meta);
|
||||
luaA_class_add_property(&widget_class, A_TK_VISIBLE,
|
||||
(lua_class_propfunc_t) luaA_widget_set_visible,
|
||||
|
|
|
@ -119,7 +119,7 @@ window_class_setup(lua_State *L)
|
|||
};
|
||||
|
||||
luaA_class_setup(L, &window_class, "window", NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
luaA_class_index_miss_property, luaA_class_newindex_miss_property,
|
||||
window_methods, window_meta);
|
||||
|
||||
|
|
Loading…
Reference in New Issue