luaobject: change global refering method

We now store elements in registry:
registry.pointer = userdata

And count references.

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2009-07-28 10:40:51 +02:00
parent fb3c5d90c7
commit a1b113901c
3 changed files with 77 additions and 26 deletions

View File

@ -21,6 +21,25 @@
#include "common/luaobject.h" #include "common/luaobject.h"
/** Setup the object system at startup.
* \param L The Lua VM state.
*/
void
luaA_object_setup(lua_State *L)
{
/* Push identification string */
lua_pushliteral(L, LUAA_OBJECT_REGISTRY_KEY);
/* Create an empty table */
lua_newtable(L);
/* Create an empty metatable */
lua_newtable(L);
/* Set this empty table as the registry metatable.
* It's used to store the number of reference on stored objects. */
lua_setmetatable(L, -2);
/* Register table inside registry */
lua_rawset(L, LUA_REGISTRYINDEX);
}
/** Increment a object reference in its store table. /** Increment a object reference in its store table.
* \param L The Lua VM state. * \param L The Lua VM state.
* \param tud The table index on the stack. * \param tud The table index on the stack.

View File

@ -33,6 +33,9 @@ luaA_settype(lua_State *L, const char *type)
return 1; return 1;
} }
#define LUAA_OBJECT_REGISTRY_KEY "awesome.object.registry"
void luaA_object_setup(lua_State *);
void * luaA_object_incref(lua_State *, int, int); void * luaA_object_incref(lua_State *, int, int);
void luaA_object_decref(lua_State *, int, void *); void luaA_object_decref(lua_State *, int, void *);
@ -89,10 +92,57 @@ luaA_object_push_item(lua_State *L, int ud, void *pointer)
return 1; return 1;
} }
DO_ARRAY(int, int, DO_NOTHING) static inline void
luaA_object_registry_push(lua_State *L)
{
lua_pushliteral(L, LUAA_OBJECT_REGISTRY_KEY);
lua_rawget(L, LUA_REGISTRYINDEX);
}
#define LUA_OBJECT_HEADER \ /** Reference an object and return a pointer to it.
int_array_t refs; * That only works with userdata, table, thread or function.
* \param L The Lua VM state.
* \param oud The object index on the stack.
* \return The object reference, or NULL if not referencable.
*/
static inline void *
luaA_object_ref(lua_State *L, int oud)
{
luaA_object_registry_push(L);
void *p = luaA_object_incref(L, -1, oud < 0 ? oud - 1 : oud);
lua_pop(L, 1);
return p;
}
/** Unreference an object and return a pointer to it.
* That only works with userdata, table, thread or function.
* \param L The Lua VM state.
* \param oud The object index on the stack.
*/
static inline void
luaA_object_unref(lua_State *L, void *pointer)
{
luaA_object_registry_push(L);
luaA_object_decref(L, -1, pointer);
lua_pop(L, 1);
}
/** Push a referenced object onto the stack.
* \param L The Lua VM state.
* \param pointer The object to push.
* \return The number of element pushed on stack.
*/
static inline int
luaA_object_push(lua_State *L, void *pointer)
{
luaA_object_registry_push(L);
lua_pushlightuserdata(L, pointer);
lua_rawget(L, -2);
lua_remove(L, -2);
return 1;
}
#define LUA_OBJECT_HEADER
/** Generic type for all objects. /** Generic type for all objects.
* All Lua objects can be casted to this type. * All Lua objects can be casted to this type.
@ -119,37 +169,19 @@ typedef struct
static inline int \ static inline int \
prefix##_push(lua_State *L, type *item) \ prefix##_push(lua_State *L, type *item) \
{ \ { \
if(item) \ return luaA_object_push(L, item); \
{ \
assert(item->refs.len); \
lua_rawgeti(L, LUA_REGISTRYINDEX, item->refs.tab[0]); \
} \
else \
lua_pushnil(L); \
return 1; \
} \ } \
\ \
static inline type * \ static inline type * \
prefix##_ref(lua_State *L, int ud) \ prefix##_ref(lua_State *L, int ud) \
{ \ { \
if(lua_isnil(L, ud)) \ return luaA_object_ref(L, ud); \
return NULL; \
type *item = luaL_checkudata(L, ud, lua_type); \
lua_pushvalue(L, ud); \
int_array_append(&item->refs, luaL_ref(L, LUA_REGISTRYINDEX)); \
lua_remove(L, ud); \
return item; \
} \ } \
\ \
static inline void \ static inline void \
prefix##_unref(lua_State *L, type *item) \ prefix##_unref(lua_State *L, type *item) \
{ \ { \
if(item) \ luaA_object_unref(L, item); \
{ \
assert(item->refs.len); \
luaL_unref(L, LUA_REGISTRYINDEX, item->refs.tab[0]); \
int_array_take(&item->refs, 0); \
} \
} \ } \
\ \
static inline int \ static inline int \
@ -169,8 +201,6 @@ typedef struct
static inline int static inline int
luaA_object_gc(lua_State *L) luaA_object_gc(lua_State *L)
{ {
lua_object_t *item = lua_touserdata(L, 1);
int_array_wipe(&item->refs);
return 0; return 0;
} }

2
luaa.c
View File

@ -677,6 +677,8 @@ luaA_init(xdgHandle* xdg)
luaA_fixups(L); luaA_fixups(L);
luaA_object_setup(L);
/* Export awesome lib */ /* Export awesome lib */
luaA_openlib(L, "awesome", awesome_lib, awesome_lib); luaA_openlib(L, "awesome", awesome_lib, awesome_lib);