[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: Feature request: more integration of Lua and C memory management
- From: "Bilyk, Alex" <ABilyk@...>
- Date: Wed, 9 Jun 2004 14:10:12 -0700
It seems to me metatables and userdata define a framework that is good enough for adding any user types. A type, in my view is, no more than a data domain and a set of operations defined for it. Lua's userdata presents a general enough abstraction for any data domain -- what is more abstract than <void*, size_t> pair? At the same time metatables present a way to associate operations with domains represented as userdata. I don't see any conceptual flows in the present model. Now, if there are any particular issues/requests on the implementation side they may be addressed but why do we need to reinvent this wheel over an over again? Am I missing something big in here?
Alex
>-----Original Message-----
>From: Mike Pall [mailto:mikelu-0406@mike.de]
>Sent: Wednesday, June 09, 2004 1:37 PM
>To: Lua list
>Subject: Re: Feature request: more integration of Lua and C memory
>management
>
>
>Hi,
>
>why not extend the Lua type system so it allows for user definable and
>user allocatable types? Surprisingly little glue logic is needed to
>integrate it into the Lua GC.
>
>Completely untested and incomplete pseudo-code follows:
>
>---- lua.h ----
>typedef void (*lua_GCTraverse)(void *ud, void *p, void *gcstate);
>typedef void (*lua_GCFree)(void *ud, void *p, void *gcstate);
>LUA_API int lua_utyperegister(lua_State *L, lua_GCTraverse t,
>lua_GCFree f, void *ud);
>
>LUA_API void lua_pushutype(lua_State *L, int tag, void *p);
>#define lua_toutype(L,idx) lua_togcref(L, idx)
>
>LUA_API void *lua_togcref(lua_State *L, int idx);
>LUA_API void lua_markgcref(void *gcstate, void *gcref);
>
>/* Types must match Utype from lobject.h */
>#define LUA_UTHEADER \
> void *_lua_n; unsigned char _lua_t; unsigned char _lua_k; \
> void *_lua_m; void *_lua_g;
>
>
>---- lobject.h ----
>
>#define LUA_TUTYPE (NUM_TAGS+3)
>
>#define ttisutype(o) (ttype(o) >= LUA_TUTYPE)
>
>#define utvalue(o) check_exp(ttisutype(o), &(o)->value.gc->ut)
>
>#define setutvalue(obj,t,x) \
> { TObject *i_o=(obj); i_o->tt=t; \
> i_o->value.gc=cast(GCObject *, (x)); \
> /* i_o->value.gc->gch.tt=t; ... done by luaC_link ... */ }
>
>typedef union Utype {
> L_Umaxalign dummy;
> struct {
> CommonHeader;
> struct Table *metatable;
> GCObject *gclist;
> } utv;
>} Utype;
>
>
>---- lstate.h ----
>
>#define gcotout(o) check_exp((o)->gch.tt >= LUA_TUTYPE, &((o)->ut))
>
>union GCObject {
> ...
> union Utype ut;
>};
>
>
>---- lapi.c ----
>
>/* Register your type once and get back a unique tag */
>LUA_API int lua_utyperegister(lua_State *L, lua_GCTraverse t,
>lua_GCFree f, void *ud)
>{
> tag = ... assign next free tag number starting after
>internal tags ...
> ... register traversal and free functions plus ud with this tag ...
> return tag;
>}
>
>/* Allocate a specific type and call this function to export
>it to Lua */
>LUA_API void lua_pushutype(lua_State *L, int tag, void *p)
>{
> lua_lock(L);
> ... check that the passed tag is valid and registered ...
> setutvalue(L->top, tag, p);
> luaC_link(L, L->top, tag);
> api_incr_top(L);
> lua_unlock(L);
>}
>
>/* Get an abstract GC object reference that can be marked upon
>traversal */
>LUA_API void *lua_togcref(lua_State *L, int idx)
>{
> StkId o = luaA_indexAcceptable(L, idx);
> if (o == NULL || !iscollectable(o)) return NULL;
> return (void *)o->value;
>}
>
>... add metatable support for types >= LUA_UTYPE ...
>
>---- lgc.c ----
>/* Mark a GC object reference during traversal */
>LUA_API void lua_markgcref(void *gcstate, void *gcref)
>{
> markvalue((GCState *)gcstate, gcref);
>}
>
>static void reallymarkobject(GCState *st, GCObject *o)
>{
> ...
> switch (o->gch.tt) {
> case LUA_TSTRING:
> break;
> default:
> gcotout(o)->gclist = st->tmark;
> st->tmark = o;
> break;
> }
>}
>
>static void propagatemarks(GCState *st)
>{
> while (st->tmark) { /* traverse marked objects */
> switch (st->tmark->gch.tt) {
> ...
> default:
> Utype *u = gcotout(st->tmark);
> lua_GCTraverse func;
> st->tmark = ut->gclist;
> markvalue(st, ut->metatable);
> ... get traversal function for this type ...
> func(ud, p, (void *)st);
> break;
> }
> }
>}
>
>static void freeobj(lua_State *L, GCObject *o)
>{
> switch (o->gch.tt) {
> ...
> default:
> lua_GCFree func;
> ... get free function for this type ...
> func(ud, (void *)o, (void *)st);
> break;
> }
>}
>
>... add logic similar to luaC_separateudata for the new types? ...
>
>----
>
>This is for the Lua 5.0 GC. I haven't taken a closer look at
>the Lua 5.1
>incremental GC yet.
>
>The type system could be extended to allow for different types
>that either
>do not need traversal (omit gclist) and/or metatables (omit metatable).
>This would reduce the per-object GC overhead.
>
>I'm not sure this whole idea works and/or solves your
>problems. But maybe
>it's a start?
>
>Bye,
> Mike
>
>