lua-users home
lua-l archive

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


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
>
>