diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-08-06 14:06:56 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-08-06 14:06:56 -0300 |
commit | 634344d61fb4bd7ebd033d37b814a0083e55b5a2 (patch) | |
tree | 01794c51e00c7ec1faec1e08fe2963ee75b1a139 | |
parent | a2fa48a570b01b2a2cd37f01799f08f693fc5892 (diff) | |
download | lua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.tar.gz lua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.tar.bz2 lua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.zip |
new API for weak mode
-rw-r--r-- | lapi.c | 27 | ||||
-rw-r--r-- | lbaselib.c | 25 | ||||
-rw-r--r-- | lgc.c | 63 | ||||
-rw-r--r-- | lobject.h | 6 | ||||
-rw-r--r-- | ltable.c | 3 | ||||
-rw-r--r-- | ltablib.c | 8 | ||||
-rw-r--r-- | ltm.c | 6 | ||||
-rw-r--r-- | ltm.h | 11 | ||||
-rw-r--r-- | lua.h | 4 |
9 files changed, 88 insertions, 65 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 1.206 2002/08/05 14:43:38 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.207 2002/08/06 15:32:22 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -464,6 +464,20 @@ LUA_API void lua_newtable (lua_State *L) { | |||
464 | } | 464 | } |
465 | 465 | ||
466 | 466 | ||
467 | LUA_API const char *lua_getmode (lua_State *L, int index) { | ||
468 | static const char *const modes[] = {"", "k", "v", "kv"}; | ||
469 | int mode = 0; | ||
470 | TObject *t; | ||
471 | lua_lock(L); | ||
472 | t = luaA_index(L, index); | ||
473 | api_check(L, ttistable(t)); | ||
474 | if (hvalue(t)->mode & WEAKKEY) mode += 1; | ||
475 | if (hvalue(t)->mode & WEAKVALUE) mode += 2; | ||
476 | lua_unlock(L); | ||
477 | return modes[mode]; | ||
478 | } | ||
479 | |||
480 | |||
467 | LUA_API int lua_getmetatable (lua_State *L, int objindex) { | 481 | LUA_API int lua_getmetatable (lua_State *L, int objindex) { |
468 | StkId obj; | 482 | StkId obj; |
469 | Table *mt; | 483 | Table *mt; |
@@ -555,6 +569,17 @@ LUA_API void lua_rawseti (lua_State *L, int index, int n) { | |||
555 | } | 569 | } |
556 | 570 | ||
557 | 571 | ||
572 | LUA_API void lua_setmode (lua_State *L, int index, const char *mode) { | ||
573 | TObject *t; | ||
574 | lua_lock(L); | ||
575 | t = luaA_index(L, index); | ||
576 | api_check(L, ttistable(t)); | ||
577 | hvalue(t)->mode &= ~(WEAKKEY | WEAKVALUE); /* clear bits */ | ||
578 | if (strchr(mode, 'k')) hvalue(t)->mode |= WEAKKEY; | ||
579 | if (strchr(mode, 'v')) hvalue(t)->mode |= WEAKVALUE; | ||
580 | lua_unlock(L); | ||
581 | } | ||
582 | |||
558 | LUA_API int lua_setmetatable (lua_State *L, int objindex) { | 583 | LUA_API int lua_setmetatable (lua_State *L, int objindex) { |
559 | TObject *obj, *mt; | 584 | TObject *obj, *mt; |
560 | int res = 1; | 585 | int res = 1; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.92 2002/08/05 14:46:02 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.93 2002/08/06 15:32:22 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -81,6 +81,21 @@ static int luaB_error (lua_State *L) { | |||
81 | } | 81 | } |
82 | 82 | ||
83 | 83 | ||
84 | static int luaB_getmode (lua_State *L) { | ||
85 | luaL_check_type(L, 1, LUA_TTABLE); | ||
86 | lua_pushstring(L, lua_getmode(L, 1)); | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | |||
91 | static int luaB_setmode (lua_State *L) { | ||
92 | luaL_check_type(L, 1, LUA_TTABLE); | ||
93 | lua_setmode(L, 1, luaL_check_string(L, 2)); | ||
94 | lua_settop(L, 1); | ||
95 | return 1; | ||
96 | } | ||
97 | |||
98 | |||
84 | static int luaB_getmetatable (lua_State *L) { | 99 | static int luaB_getmetatable (lua_State *L) { |
85 | luaL_check_any(L, 1); | 100 | luaL_check_any(L, 1); |
86 | if (!lua_getmetatable(L, 1)) { | 101 | if (!lua_getmetatable(L, 1)) { |
@@ -460,6 +475,8 @@ static const luaL_reg base_funcs[] = { | |||
460 | {"setmetatable", luaB_setmetatable}, | 475 | {"setmetatable", luaB_setmetatable}, |
461 | {"getglobals", luaB_getglobals}, | 476 | {"getglobals", luaB_getglobals}, |
462 | {"setglobals", luaB_setglobals}, | 477 | {"setglobals", luaB_setglobals}, |
478 | {"getmode", luaB_getmode}, | ||
479 | {"setmode", luaB_setmode}, | ||
463 | {"next", luaB_next}, | 480 | {"next", luaB_next}, |
464 | {"ipairs", luaB_ipairs}, | 481 | {"ipairs", luaB_ipairs}, |
465 | {"pairs", luaB_pairs}, | 482 | {"pairs", luaB_pairs}, |
@@ -572,11 +589,7 @@ static void base_open (lua_State *L) { | |||
572 | /* `newproxy' needs a weaktable as upvalue */ | 589 | /* `newproxy' needs a weaktable as upvalue */ |
573 | lua_pushliteral(L, "newproxy"); | 590 | lua_pushliteral(L, "newproxy"); |
574 | lua_newtable(L); /* new table `w' */ | 591 | lua_newtable(L); /* new table `w' */ |
575 | lua_pushvalue(L, -1); /* `w' will be its own metatable */ | 592 | lua_setmode(L, -1, "k"); |
576 | lua_setmetatable(L, -2); | ||
577 | lua_pushliteral(L, "__mode"); | ||
578 | lua_pushliteral(L, "k"); | ||
579 | lua_rawset(L, -3); /* metatable(w).__mode = "k" */ | ||
580 | lua_pushcclosure(L, luaB_newproxy, 1); | 593 | lua_pushcclosure(L, luaB_newproxy, 1); |
581 | lua_rawset(L, -3); /* set global `newproxy' */ | 594 | lua_rawset(L, -3); /* set global `newproxy' */ |
582 | lua_rawset(L, -1); /* set global _G */ | 595 | lua_rawset(L, -1); /* set global _G */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.143 2002/07/17 16:25:13 roberto Exp $ | 2 | ** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -35,12 +35,6 @@ typedef struct GCState { | |||
35 | #define ismarked(x) ((x)->mark != (x)) | 35 | #define ismarked(x) ((x)->mark != (x)) |
36 | 36 | ||
37 | 37 | ||
38 | /* `Table.flag' bits to indicate whether table is key-weak and/or value-weak */ | ||
39 | #define KEYWEAKBIT (TM_MODE+1) /* ORDER TM */ | ||
40 | #define VALUEWEAKBIT (TM_MODE+2) | ||
41 | #define KEYWEAK (1<<KEYWEAKBIT) | ||
42 | #define VALUEWEAK (1<<VALUEWEAKBIT) | ||
43 | |||
44 | 38 | ||
45 | /* mark tricks for userdata */ | 39 | /* mark tricks for userdata */ |
46 | #define isudmarked(u) (u->uv.len & 1) | 40 | #define isudmarked(u) (u->uv.len & 1) |
@@ -221,19 +215,15 @@ static void removekey (Node *n) { | |||
221 | 215 | ||
222 | static void traversetable (GCState *st, Table *h) { | 216 | static void traversetable (GCState *st, Table *h) { |
223 | int i; | 217 | int i; |
224 | const TObject *mode; | ||
225 | int weakkey = 0; | 218 | int weakkey = 0; |
226 | int weakvalue = 0; | 219 | int weakvalue = 0; |
227 | marktable(st, h->metatable); | 220 | marktable(st, h->metatable); |
228 | lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); | 221 | lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); |
229 | mode = fasttm(st->L, h->metatable, TM_MODE); | 222 | if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */ |
230 | if (mode && ttisstring(mode)) { /* weak table? */ | 223 | weakkey = h->mode & WEAKKEY; |
224 | weakvalue = h->mode & WEAKVALUE; | ||
231 | h->mark = st->toclear; /* must be cleared after GC, ... */ | 225 | h->mark = st->toclear; /* must be cleared after GC, ... */ |
232 | st->toclear = h; /* ...put in the appropriate list */ | 226 | st->toclear = h; /* ... so put in the appropriate list */ |
233 | weakkey = (strchr(svalue(mode), 'k') != NULL); | ||
234 | weakvalue = (strchr(svalue(mode), 'v') != NULL); | ||
235 | h->flags &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ | ||
236 | h->flags |= (weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT); | ||
237 | } | 227 | } |
238 | if (!weakvalue) { | 228 | if (!weakvalue) { |
239 | i = sizearray(h); | 229 | i = sizearray(h); |
@@ -284,14 +274,14 @@ static int hasmark (const TObject *o) { | |||
284 | static void cleartablekeys (GCState *st) { | 274 | static void cleartablekeys (GCState *st) { |
285 | Table *h; | 275 | Table *h; |
286 | for (h = st->toclear; h; h = h->mark) { | 276 | for (h = st->toclear; h; h = h->mark) { |
287 | int i; | 277 | lua_assert(h->mode & (WEAKKEY | WEAKVALUE)); |
288 | if (!(h->flags & KEYWEAK)) continue; | 278 | if ((h->mode & WEAKKEY)) { /* table may have collected keys? */ |
289 | lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'k')); | 279 | int i = sizenode(h); |
290 | i = sizenode(h); | 280 | while (i--) { |
291 | while (i--) { | 281 | Node *n = node(h, i); |
292 | Node *n = node(h, i); | 282 | if (!hasmark(key(n))) /* key was collected? */ |
293 | if (!hasmark(key(n))) | 283 | removekey(n); /* remove entry from table */ |
294 | removekey(n); /* ... and key */ | 284 | } |
295 | } | 285 | } |
296 | } | 286 | } |
297 | } | 287 | } |
@@ -303,20 +293,19 @@ static void cleartablekeys (GCState *st) { | |||
303 | static void cleartablevalues (GCState *st) { | 293 | static void cleartablevalues (GCState *st) { |
304 | Table *h; | 294 | Table *h; |
305 | for (h = st->toclear; h; h = h->mark) { | 295 | for (h = st->toclear; h; h = h->mark) { |
306 | int i; | 296 | if ((h->mode & WEAKVALUE)) { /* table may have collected values? */ |
307 | if (!(h->flags & VALUEWEAK)) continue; | 297 | int i = sizearray(h); |
308 | lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'v')); | 298 | while (i--) { |
309 | i = sizearray(h); | 299 | TObject *o = &h->array[i]; |
310 | while (i--) { | 300 | if (!hasmark(o)) /* value was collected? */ |
311 | TObject *o = &h->array[i]; | 301 | setnilvalue(o); /* remove value */ |
312 | if (!hasmark(o)) | 302 | } |
313 | setnilvalue(o); /* remove value */ | 303 | i = sizenode(h); |
314 | } | 304 | while (i--) { |
315 | i = sizenode(h); | 305 | Node *n = node(h, i); |
316 | while (i--) { | 306 | if (!hasmark(val(n))) /* value was collected? */ |
317 | Node *n = node(h, i); | 307 | removekey(n); /* remove entry from table */ |
318 | if (!hasmark(val(n))) | 308 | } |
319 | removekey(n); /* ... and key */ | ||
320 | } | 309 | } |
321 | } | 310 | } |
322 | } | 311 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.140 2002/07/17 16:25:13 roberto Exp $ | 2 | ** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -223,8 +223,12 @@ typedef struct Table { | |||
223 | int sizearray; /* size of `array' array */ | 223 | int sizearray; /* size of `array' array */ |
224 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ | 224 | lu_byte flags; /* 1<<p means tagmethod(p) is not present */ |
225 | lu_byte lsizenode; /* log2 of size of `node' array */ | 225 | lu_byte lsizenode; /* log2 of size of `node' array */ |
226 | lu_byte mode; | ||
226 | } Table; | 227 | } Table; |
227 | 228 | ||
229 | /* bit masks for `mode' */ | ||
230 | #define WEAKKEY 1 | ||
231 | #define WEAKVALUE 2 | ||
228 | 232 | ||
229 | 233 | ||
230 | /* | 234 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 1.114 2002/07/17 16:25:13 roberto Exp $ | 2 | ** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -309,6 +309,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) { | |||
309 | G(L)->roottable = t; | 309 | G(L)->roottable = t; |
310 | t->mark = t; | 310 | t->mark = t; |
311 | t->flags = cast(lu_byte, ~0); | 311 | t->flags = cast(lu_byte, ~0); |
312 | t->mode = 0; | ||
312 | /* temporary values (kept only if some malloc fails) */ | 313 | /* temporary values (kept only if some malloc fails) */ |
313 | t->array = NULL; | 314 | t->array = NULL; |
314 | t->sizearray = 0; | 315 | t->sizearray = 0; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltablib.c,v 1.9 2002/07/01 19:25:28 roberto Exp roberto $ | 2 | ** $Id: ltablib.c,v 1.10 2002/07/08 16:51:20 roberto Exp roberto $ |
3 | ** Library for Table Manipulation | 3 | ** Library for Table Manipulation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -288,11 +288,7 @@ static const luaL_reg tab_funcs[] = { | |||
288 | 288 | ||
289 | LUALIB_API int lua_tablibopen (lua_State *L) { | 289 | LUALIB_API int lua_tablibopen (lua_State *L) { |
290 | lua_newtable(L); /* create N (table to store num. elements in tables) */ | 290 | lua_newtable(L); /* create N (table to store num. elements in tables) */ |
291 | lua_pushvalue(L, -1); | 291 | lua_setmode(L, -1, "k"); /* make it a weak table */ |
292 | lua_setmetatable(L, -2); /* make it its own metatable */ | ||
293 | lua_pushliteral(L, "__mode"); | ||
294 | lua_pushliteral(L, "k"); | ||
295 | lua_rawset(L, -3); /* make it a weak table */ | ||
296 | luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1); | 292 | luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1); |
297 | return 0; | 293 | return 0; |
298 | } | 294 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 1.98 2002/07/17 16:25:13 roberto Exp $ | 2 | ** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -26,7 +26,7 @@ const char *const luaT_typenames[] = { | |||
26 | void luaT_init (lua_State *L) { | 26 | void luaT_init (lua_State *L) { |
27 | static const char *const luaT_eventname[] = { /* ORDER TM */ | 27 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
28 | "__index", "__newindex", | 28 | "__index", "__newindex", |
29 | "__gc", "__eq", "__mode", | 29 | "__gc", "__eq", |
30 | "__gettable", "__settable", | 30 | "__gettable", "__settable", |
31 | "__add", "__sub", "__mul", "__div", | 31 | "__add", "__sub", "__mul", "__div", |
32 | "__pow", "__unm", "__lt", "__le", | 32 | "__pow", "__unm", "__lt", "__le", |
@@ -46,7 +46,7 @@ void luaT_init (lua_State *L) { | |||
46 | */ | 46 | */ |
47 | const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { | 47 | const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { |
48 | const TObject *tm = luaH_getstr(events, ename); | 48 | const TObject *tm = luaH_getstr(events, ename); |
49 | lua_assert(event <= TM_MODE); | 49 | lua_assert(event <= TM_EQ); |
50 | if (ttisnil(tm)) { /* no tag method? */ | 50 | if (ttisnil(tm)) { /* no tag method? */ |
51 | events->flags |= (1u<<event); /* cache this fact */ | 51 | events->flags |= (1u<<event); /* cache this fact */ |
52 | return NULL; | 52 | return NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 1.37 2002/06/25 19:17:22 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -12,12 +12,6 @@ | |||
12 | 12 | ||
13 | 13 | ||
14 | /* | 14 | /* |
15 | ** Important: garbage collection uses two extra bits of `Table.flags' | ||
16 | ** (after TM_MODE), so the maximum number of `fast tag methods' is six | ||
17 | ** (at least while `flags' is a byte). | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * WARNING: if you change the order of this enumeration, | 15 | * WARNING: if you change the order of this enumeration, |
22 | * grep "ORDER TM" | 16 | * grep "ORDER TM" |
23 | */ | 17 | */ |
@@ -25,8 +19,7 @@ typedef enum { | |||
25 | TM_INDEX, | 19 | TM_INDEX, |
26 | TM_NEWINDEX, | 20 | TM_NEWINDEX, |
27 | TM_GC, | 21 | TM_GC, |
28 | TM_EQ, | 22 | TM_EQ, /* last tag method with `fast' access */ |
29 | TM_MODE, /* last tag method with `fast' access */ | ||
30 | TM_GETTABLE, | 23 | TM_GETTABLE, |
31 | TM_SETTABLE, | 24 | TM_SETTABLE, |
32 | TM_ADD, | 25 | TM_ADD, |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.148 2002/08/05 14:51:47 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.149 2002/08/06 15:32:22 roberto Exp roberto $ |
3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - An Extensible Extension Language |
4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil | 4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil |
5 | ** http://www.lua.org mailto:info@lua.org | 5 | ** http://www.lua.org mailto:info@lua.org |
@@ -166,6 +166,7 @@ LUA_API void lua_rawget (lua_State *L, int index); | |||
166 | LUA_API void lua_rawgeti (lua_State *L, int index, int n); | 166 | LUA_API void lua_rawgeti (lua_State *L, int index, int n); |
167 | LUA_API void lua_newtable (lua_State *L); | 167 | LUA_API void lua_newtable (lua_State *L); |
168 | LUA_API int lua_getmetatable (lua_State *L, int objindex); | 168 | LUA_API int lua_getmetatable (lua_State *L, int objindex); |
169 | LUA_API const char *lua_getmode (lua_State *L, int index); | ||
169 | LUA_API void lua_getglobals (lua_State *L, int level); | 170 | LUA_API void lua_getglobals (lua_State *L, int level); |
170 | 171 | ||
171 | 172 | ||
@@ -175,6 +176,7 @@ LUA_API void lua_getglobals (lua_State *L, int level); | |||
175 | LUA_API void lua_settable (lua_State *L, int index); | 176 | LUA_API void lua_settable (lua_State *L, int index); |
176 | LUA_API void lua_rawset (lua_State *L, int index); | 177 | LUA_API void lua_rawset (lua_State *L, int index); |
177 | LUA_API void lua_rawseti (lua_State *L, int index, int n); | 178 | LUA_API void lua_rawseti (lua_State *L, int index, int n); |
179 | LUA_API void lua_setmode (lua_State *L, int index, const char *mode); | ||
178 | LUA_API int lua_setmetatable (lua_State *L, int objindex); | 180 | LUA_API int lua_setmetatable (lua_State *L, int objindex); |
179 | LUA_API int lua_setglobals (lua_State *L, int level); | 181 | LUA_API int lua_setglobals (lua_State *L, int level); |
180 | 182 | ||