Browse Source

new API for weak mode

Roberto Ierusalimschy 23 years ago
parent
commit
634344d61f
9 changed files with 88 additions and 65 deletions
  1. 26 1
      lapi.c
  2. 19 6
      lbaselib.c
  3. 26 37
      lgc.c
  4. 5 1
      lobject.h
  5. 2 1
      ltable.c
  6. 2 6
      ltablib.c
  7. 3 3
      ltm.c
  8. 2 9
      ltm.h
  9. 3 1
      lua.h

+ 26 - 1
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.206 2002/08/05 14:43:38 roberto Exp roberto $
+** $Id: lapi.c,v 1.207 2002/08/06 15:32:22 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -464,6 +464,20 @@ LUA_API void lua_newtable (lua_State *L) {
 }
 
 
+LUA_API const char *lua_getmode (lua_State *L, int index) {
+  static const char *const modes[] = {"", "k", "v", "kv"};
+  int mode = 0;
+  TObject *t;
+  lua_lock(L);
+  t = luaA_index(L, index);
+  api_check(L, ttistable(t));
+  if (hvalue(t)->mode & WEAKKEY) mode += 1;
+  if (hvalue(t)->mode & WEAKVALUE) mode += 2;
+  lua_unlock(L);
+  return modes[mode];
+}
+
+
 LUA_API int lua_getmetatable (lua_State *L, int objindex) {
   StkId obj;
   Table *mt;
@@ -555,6 +569,17 @@ LUA_API void lua_rawseti (lua_State *L, int index, int n) {
 }
 
 
+LUA_API void lua_setmode (lua_State *L, int index, const char *mode) {
+  TObject *t;
+  lua_lock(L);
+  t = luaA_index(L, index);
+  api_check(L, ttistable(t));
+  hvalue(t)->mode &= ~(WEAKKEY | WEAKVALUE);  /* clear bits */
+  if (strchr(mode, 'k')) hvalue(t)->mode |= WEAKKEY;
+  if (strchr(mode, 'v')) hvalue(t)->mode |= WEAKVALUE;
+  lua_unlock(L);
+}
+
 LUA_API int lua_setmetatable (lua_State *L, int objindex) {
   TObject *obj, *mt;
   int res = 1;

+ 19 - 6
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.92 2002/08/05 14:46:02 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.93 2002/08/06 15:32:22 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -81,6 +81,21 @@ static int luaB_error (lua_State *L) {
 }
 
 
+static int luaB_getmode (lua_State *L) {
+  luaL_check_type(L, 1, LUA_TTABLE);
+  lua_pushstring(L, lua_getmode(L, 1));
+  return 1;
+}
+
+
+static int luaB_setmode (lua_State *L) {
+  luaL_check_type(L, 1, LUA_TTABLE);
+  lua_setmode(L, 1, luaL_check_string(L, 2));
+  lua_settop(L, 1);
+  return 1;
+}
+
+
 static int luaB_getmetatable (lua_State *L) {
   luaL_check_any(L, 1);
   if (!lua_getmetatable(L, 1)) {
@@ -460,6 +475,8 @@ static const luaL_reg base_funcs[] = {
   {"setmetatable", luaB_setmetatable},
   {"getglobals", luaB_getglobals},
   {"setglobals", luaB_setglobals},
+  {"getmode", luaB_getmode},
+  {"setmode", luaB_setmode},
   {"next", luaB_next},
   {"ipairs", luaB_ipairs},
   {"pairs", luaB_pairs},
@@ -572,11 +589,7 @@ static void base_open (lua_State *L) {
   /* `newproxy' needs a weaktable as upvalue */
   lua_pushliteral(L, "newproxy");
   lua_newtable(L);  /* new table `w' */
-  lua_pushvalue(L, -1);  /* `w' will be its own metatable */
-  lua_setmetatable(L, -2);
-  lua_pushliteral(L, "__mode");
-  lua_pushliteral(L, "k");
-  lua_rawset(L, -3);  /* metatable(w).__mode = "k" */
+  lua_setmode(L, -1, "k");
   lua_pushcclosure(L, luaB_newproxy, 1);
   lua_rawset(L, -3);  /* set global `newproxy' */
   lua_rawset(L, -1);  /* set global _G */

+ 26 - 37
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.143 2002/07/17 16:25:13 roberto Exp $
+** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -35,12 +35,6 @@ typedef struct GCState {
 #define ismarked(x)	((x)->mark != (x))
 
 
-/* `Table.flag' bits to indicate whether table is key-weak and/or value-weak */
-#define KEYWEAKBIT	(TM_MODE+1)		/* ORDER TM */
-#define VALUEWEAKBIT	(TM_MODE+2)
-#define KEYWEAK         (1<<KEYWEAKBIT)
-#define VALUEWEAK       (1<<VALUEWEAKBIT)
-
 
 /* mark tricks for userdata */
 #define isudmarked(u)	(u->uv.len & 1)
@@ -221,19 +215,15 @@ static void removekey (Node *n) {
 
 static void traversetable (GCState *st, Table *h) {
   int i;
-  const TObject *mode;
   int weakkey = 0;
   int weakvalue = 0;
   marktable(st, h->metatable);
   lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
-  mode = fasttm(st->L, h->metatable, TM_MODE);
-  if (mode && ttisstring(mode)) {  /* weak table? */
+  if (h->mode & (WEAKKEY | WEAKVALUE)) {  /* weak table? */
+    weakkey = h->mode & WEAKKEY;
+    weakvalue = h->mode & WEAKVALUE;
     h->mark = st->toclear;  /* must be cleared after GC, ... */
-    st->toclear = h;  /* ...put in the appropriate list */
-    weakkey = (strchr(svalue(mode), 'k') != NULL);
-    weakvalue = (strchr(svalue(mode), 'v') != NULL);
-    h->flags &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */
-    h->flags |= (weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT);
+    st->toclear = h;  /* ... so put in the appropriate list */
   }
   if (!weakvalue) {
     i = sizearray(h);
@@ -284,14 +274,14 @@ static int hasmark (const TObject *o) {
 static void cleartablekeys (GCState *st) {
   Table *h;
   for (h = st->toclear; h; h = h->mark) {
-    int i;
-    if (!(h->flags & KEYWEAK)) continue;
-    lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'k'));
-    i = sizenode(h);
-    while (i--) {
-      Node *n = node(h, i);
-      if (!hasmark(key(n)))
-        removekey(n);  /* ... and key */
+    lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
+    if ((h->mode & WEAKKEY)) {  /* table may have collected keys? */
+      int i = sizenode(h);
+      while (i--) {
+        Node *n = node(h, i);
+        if (!hasmark(key(n)))  /* key was collected? */
+          removekey(n);  /* remove entry from table */
+      }
     }
   }
 }
@@ -303,20 +293,19 @@ static void cleartablekeys (GCState *st) {
 static void cleartablevalues (GCState *st) {
   Table *h;
   for (h = st->toclear; h; h = h->mark) {
-    int i;
-    if (!(h->flags & VALUEWEAK)) continue;
-    lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'v'));
-    i = sizearray(h);
-    while (i--) {
-      TObject *o = &h->array[i];
-      if (!hasmark(o))
-        setnilvalue(o);  /* remove value */
-    }
-    i = sizenode(h);
-    while (i--) {
-      Node *n = node(h, i);
-      if (!hasmark(val(n)))
-        removekey(n);  /* ... and key */
+    if ((h->mode & WEAKVALUE)) {  /* table may have collected values? */
+      int i = sizearray(h);
+      while (i--) {
+        TObject *o = &h->array[i];
+        if (!hasmark(o))  /* value was collected? */
+          setnilvalue(o);  /* remove value */
+      }
+      i = sizenode(h);
+      while (i--) {
+        Node *n = node(h, i);
+        if (!hasmark(val(n)))  /* value was collected? */
+          removekey(n);  /* remove entry from table */
+      }
     }
   }
 }

+ 5 - 1
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.140 2002/07/17 16:25:13 roberto Exp $
+** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -223,8 +223,12 @@ typedef struct Table {
   int sizearray;  /* size of `array' array */
   lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ 
   lu_byte lsizenode;  /* log2 of size of `node' array */
+  lu_byte mode;
 } Table;
 
+/* bit masks for `mode' */
+#define WEAKKEY		1
+#define WEAKVALUE	2
 
 
 /*

+ 2 - 1
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.114 2002/07/17 16:25:13 roberto Exp $
+** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -309,6 +309,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
   G(L)->roottable = t;
   t->mark = t;
   t->flags = cast(lu_byte, ~0);
+  t->mode = 0;
   /* temporary values (kept only if some malloc fails) */
   t->array = NULL;
   t->sizearray = 0;

+ 2 - 6
ltablib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.9 2002/07/01 19:25:28 roberto Exp roberto $
+** $Id: ltablib.c,v 1.10 2002/07/08 16:51:20 roberto Exp roberto $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */
@@ -288,11 +288,7 @@ static const luaL_reg tab_funcs[] = {
 
 LUALIB_API int lua_tablibopen (lua_State *L) {
   lua_newtable(L);  /* create N (table to store num. elements in tables) */
-  lua_pushvalue(L, -1);
-  lua_setmetatable(L, -2);  /* make it its own metatable */
-  lua_pushliteral(L, "__mode");
-  lua_pushliteral(L, "k");
-  lua_rawset(L, -3);  /* make it a weak table */
+  lua_setmode(L, -1, "k");  /* make it a weak table */
   luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
   return 0;
 }

+ 3 - 3
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.98 2002/07/17 16:25:13 roberto Exp $
+** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -26,7 +26,7 @@ const char *const luaT_typenames[] = {
 void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
     "__index", "__newindex",
-    "__gc", "__eq", "__mode",
+    "__gc", "__eq",
     "__gettable", "__settable",
     "__add", "__sub", "__mul", "__div",
     "__pow", "__unm", "__lt", "__le",
@@ -46,7 +46,7 @@ void luaT_init (lua_State *L) {
 */
 const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
   const TObject *tm = luaH_getstr(events, ename);
-  lua_assert(event <= TM_MODE);
+  lua_assert(event <= TM_EQ);
   if (ttisnil(tm)) {  /* no tag method? */
     events->flags |= (1u<<event);  /* cache this fact */
     return NULL;

+ 2 - 9
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 1.37 2002/06/25 19:17:22 roberto Exp roberto $
+** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -11,12 +11,6 @@
 #include "lobject.h"
 
 
-/*
-** Important: garbage collection uses two extra bits of `Table.flags'
-** (after TM_MODE), so the maximum number of `fast tag methods' is six
-** (at least while `flags' is a byte).
-*/
-
 /*
 * WARNING: if you change the order of this enumeration,
 * grep "ORDER TM"
@@ -25,8 +19,7 @@ typedef enum {
   TM_INDEX,
   TM_NEWINDEX,
   TM_GC,
-  TM_EQ,
-  TM_MODE,  /* last tag method with `fast' access */
+  TM_EQ,  /* last tag method with `fast' access */
   TM_GETTABLE,
   TM_SETTABLE,
   TM_ADD,

+ 3 - 1
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.148 2002/08/05 14:51:47 roberto Exp roberto $
+** $Id: lua.h,v 1.149 2002/08/06 15:32:22 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
 ** http://www.lua.org	mailto:[email protected]
@@ -166,6 +166,7 @@ LUA_API void  lua_rawget (lua_State *L, int index);
 LUA_API void  lua_rawgeti (lua_State *L, int index, int n);
 LUA_API void  lua_newtable (lua_State *L);
 LUA_API int   lua_getmetatable (lua_State *L, int objindex);
+LUA_API const char *lua_getmode (lua_State *L, int index);
 LUA_API void  lua_getglobals (lua_State *L, int level);
 
 
@@ -175,6 +176,7 @@ LUA_API void  lua_getglobals (lua_State *L, int level);
 LUA_API void  lua_settable (lua_State *L, int index);
 LUA_API void  lua_rawset (lua_State *L, int index);
 LUA_API void  lua_rawseti (lua_State *L, int index, int n);
+LUA_API void  lua_setmode (lua_State *L, int index, const char *mode);
 LUA_API int   lua_setmetatable (lua_State *L, int objindex);
 LUA_API int   lua_setglobals (lua_State *L, int level);