aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-04-11 11:42:41 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-04-11 11:42:41 -0300
commit0e0e4a480e6d9b0125a96ca982a3e9571578a037 (patch)
tree21f13f032e9e337879168c74871d0d4bb2534248
parent2a501882692afaa08ecc38af3052e9b4f60f6e85 (diff)
downloadlua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.tar.gz
lua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.tar.bz2
lua-0e0e4a480e6d9b0125a96ca982a3e9571578a037.zip
first implementation for weak tables
-rw-r--r--lapi.c33
-rw-r--r--lbaselib.c26
-rw-r--r--lgc.c59
-rw-r--r--lobject.h3
-rw-r--r--ltable.c3
-rw-r--r--ltests.c15
-rw-r--r--lua.h12
7 files changed, 121 insertions, 30 deletions
diff --git a/lapi.c b/lapi.c
index 6652e7f4..f146bf8a 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.136 2001/03/07 18:09:25 roberto Exp roberto $ 2** $Id: lapi.c,v 1.137 2001/03/26 14:31:49 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*/
@@ -681,18 +681,19 @@ LUA_API int lua_next (lua_State *L, int index) {
681 681
682 682
683LUA_API int lua_getn (lua_State *L, int index) { 683LUA_API int lua_getn (lua_State *L, int index) {
684 Hash *h; 684 StkId t;
685 const TObject *value; 685 const TObject *value;
686 int n; 686 int n;
687 lua_lock(L); 687 lua_lock(L);
688 h = hvalue(luaA_index(L, index)); 688 t = luaA_index(L, index);
689 value = luaH_getstr(h, luaS_newliteral(L, l_s("n"))); /* = h.n */ 689 api_check(L, ttype(t) == LUA_TTABLE);
690 value = luaH_getstr(hvalue(t), luaS_newliteral(L, l_s("n"))); /* = t.n */
690 if (ttype(value) == LUA_TNUMBER) 691 if (ttype(value) == LUA_TNUMBER)
691 n = (int)nvalue(value); 692 n = (int)nvalue(value);
692 else { 693 else {
693 lua_Number max = 0; 694 lua_Number max = 0;
694 int i = h->size; 695 int i = hvalue(t)->size;
695 Node *nd = h->node; 696 Node *nd = hvalue(t)->node;
696 while (i--) { 697 while (i--) {
697 if (ttype_key(nd) == LUA_TNUMBER && 698 if (ttype_key(nd) == LUA_TNUMBER &&
698 ttype(val(nd)) != LUA_TNIL && 699 ttype(val(nd)) != LUA_TNIL &&
@@ -737,3 +738,23 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
737 return p; 738 return p;
738} 739}
739 740
741
742LUA_API int lua_getweakmode (lua_State *L, int index) {
743 StkId t;
744 int mode;
745 lua_lock(L);
746 t = luaA_index(L, index);
747 api_check(L, ttype(t) == LUA_TTABLE);
748 mode = hvalue(t)->weakmode;
749 lua_unlock(L);
750 return mode;
751}
752
753
754LUA_API void lua_setweakmode (lua_State *L, int mode) {
755 lua_lock(L);
756 api_check(L, ttype(L->top-1) == LUA_TTABLE);
757 hvalue(L->top-1)->weakmode = mode;
758 lua_unlock(L);
759}
760
diff --git a/lbaselib.c b/lbaselib.c
index d0dd1e9f..4a979814 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.31 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.32 2001/04/06 18:25:00 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*/
@@ -169,6 +169,29 @@ static int luaB_settag (lua_State *L) {
169 return 1; /* return table */ 169 return 1; /* return table */
170} 170}
171 171
172static int luaB_weakmode (lua_State *L) {
173 const char *mode = luaL_opt_string(L, 2, NULL);
174 luaL_checktype(L, 1, LUA_TTABLE);
175 if (mode == NULL) {
176 char buff[3];
177 char *s = buff;
178 int imode = lua_getweakmode(L, 1);
179 if (imode & LUA_WEAK_KEY) *s++ = 'k';
180 if (imode & LUA_WEAK_VALUE) *s++ = 'v';
181 *s = '\0';
182 lua_pushstring(L, buff);
183 return 1;
184 }
185 else {
186 int imode = 0;
187 lua_pushvalue(L, 1); /* push table */
188 if (strchr(mode, l_c('k'))) imode |= LUA_WEAK_KEY;
189 if (strchr(mode, l_c('v'))) imode |= LUA_WEAK_VALUE;
190 lua_setweakmode(L, imode);
191 return 1;
192 }
193}
194
172static int luaB_newtype (lua_State *L) { 195static int luaB_newtype (lua_State *L) {
173 const l_char *name = luaL_opt_string(L, 1, NULL); 196 const l_char *name = luaL_opt_string(L, 1, NULL);
174 lua_pushnumber(L, lua_newtype(L, name, LUA_TTABLE)); 197 lua_pushnumber(L, lua_newtype(L, name, LUA_TTABLE));
@@ -753,6 +776,7 @@ static const luaL_reg base_funcs[] = {
753 {l_s("tremove"), luaB_tremove}, 776 {l_s("tremove"), luaB_tremove},
754 {l_s("unwrap"), luaB_unwrap}, 777 {l_s("unwrap"), luaB_unwrap},
755 {l_s("xtype"), luaB_xtype}, 778 {l_s("xtype"), luaB_xtype},
779 {l_s("weakmode"), luaB_weakmode}
756}; 780};
757 781
758 782
diff --git a/lgc.c b/lgc.c
index 3a665660..a7f96f8c 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.94 2001/03/07 18:09:25 roberto Exp roberto $ 2** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 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*/
@@ -38,9 +38,6 @@ typedef struct GCState {
38 38
39 39
40 40
41static void markobject (GCState *st, TObject *o);
42
43
44/* mark a string; marks larger than 1 cannot be changed */ 41/* mark a string; marks larger than 1 cannot be changed */
45#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} 42#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;}
46 43
@@ -144,22 +141,30 @@ static void traverseclosure (GCState *st, Closure *f) {
144} 141}
145 142
146 143
144static void removekey (Node *n) {
145 if (ttype_key(n) != LUA_TNIL && ttype_key(n) != LUA_TNUMBER)
146 n->key_value.ts = NULL; /* dead key; remove it */
147}
148
149
147static void traversetable (GCState *st, Hash *h) { 150static void traversetable (GCState *st, Hash *h) {
148 int i; 151 int i;
152 int mode = h->weakmode;
153 if (mode == (LUA_WEAK_KEY | LUA_WEAK_VALUE))
154 return; /* avoid traversing if both keys and values are weak */
149 for (i=0; i<h->size; i++) { 155 for (i=0; i<h->size; i++) {
150 Node *n = node(h, i); 156 Node *n = node(h, i);
151 if (ttype(val(n)) == LUA_TNIL) { 157 if (ttype(val(n)) == LUA_TNIL)
152 if (ttype_key(n) != LUA_TNIL) 158 removekey(n);
153 n->key_value.ts = NULL; /* dead key; remove it */
154 }
155 else { 159 else {
156 lua_assert(ttype_key(n) != LUA_TNIL); 160 lua_assert(ttype_key(n) != LUA_TNIL);
157 if (ttype_key(n) != LUA_TNUMBER) { 161 if (ttype_key(n) != LUA_TNUMBER && !(mode & LUA_WEAK_KEY)) {
158 TObject o; 162 TObject k;
159 setkey2obj(&o, n); 163 setkey2obj(&k, n);
160 markobject(st, &o); 164 markobject(st, &k);
161 } 165 }
162 markobject(st, &n->val); 166 if (!(mode & LUA_WEAK_VALUE))
167 markobject(st, &n->val);
163 } 168 }
164 } 169 }
165} 170}
@@ -190,7 +195,6 @@ static void markall (lua_State *L) {
190 195
191 196
192static int hasmark (const TObject *o) { 197static int hasmark (const TObject *o) {
193 /* valid only for locked objects */
194 switch (ttype(o)) { 198 switch (ttype(o)) {
195 case LUA_TSTRING: case LUA_TUSERDATA: 199 case LUA_TSTRING: case LUA_TUSERDATA:
196 return tsvalue(o)->marked; 200 return tsvalue(o)->marked;
@@ -198,7 +202,7 @@ static int hasmark (const TObject *o) {
198 return ismarked(hvalue(o)); 202 return ismarked(hvalue(o));
199 case LUA_TFUNCTION: 203 case LUA_TFUNCTION:
200 return ismarked(clvalue(o)); 204 return ismarked(clvalue(o));
201 default: /* number */ 205 default: /* number, nil */
202 return 1; 206 return 1;
203 } 207 }
204} 208}
@@ -224,6 +228,30 @@ static void invalidaterefs (global_State *G) {
224} 228}
225 229
226 230
231static void invalidatetable (Hash *h) {
232 int i;
233 for (i=0; i<h->size; i++) {
234 Node *n = node(h, i);
235 TObject k;
236 if (ttype(val(n)) == LUA_TNIL) continue; /* empty node */
237 setkey2obj(&k, n);
238 if (!hasmark(val(n)) || !hasmark(&k)) {
239 setnilvalue(val(n)); /* remove value */
240 removekey(n);
241 }
242 }
243}
244
245
246static void invalidatetables (global_State *G) {
247 Hash *h;
248 for (h = G->roottable; h; h = h->next) {
249 if (ismarked(h) && h->weakmode)
250 invalidatetable(h);
251 }
252}
253
254
227 255
228static void collectproto (lua_State *L) { 256static void collectproto (lua_State *L) {
229 Proto **p = &G(L)->rootproto; 257 Proto **p = &G(L)->rootproto;
@@ -381,6 +409,7 @@ void luaC_collect (lua_State *L, int all) {
381void luaC_collectgarbage (lua_State *L) { 409void luaC_collectgarbage (lua_State *L) {
382 markall(L); 410 markall(L);
383 invalidaterefs(G(L)); /* check unlocked references */ 411 invalidaterefs(G(L)); /* check unlocked references */
412 invalidatetables(G(L));
384 luaC_collect(L, 0); 413 luaC_collect(L, 0);
385 checkMbuffer(L); 414 checkMbuffer(L);
386 G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */ 415 G(L)->GCthreshold = 2*G(L)->nblocks; /* set new threshold */
diff --git a/lobject.h b/lobject.h
index 23ca0d03..b6f7afac 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.100 2001/03/02 17:27:50 roberto Exp roberto $ 2** $Id: lobject.h,v 1.101 2001/03/07 18:09:25 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*/
@@ -179,6 +179,7 @@ typedef struct Hash {
179 Node *firstfree; /* this position is free; all positions after it are full */ 179 Node *firstfree; /* this position is free; all positions after it are full */
180 struct Hash *next; 180 struct Hash *next;
181 struct Hash *mark; /* marked tables (point to itself when not marked) */ 181 struct Hash *mark; /* marked tables (point to itself when not marked) */
182 int weakmode;
182} Hash; 183} Hash;
183 184
184 185
diff --git a/ltable.c b/ltable.c
index 284826ef..c3e4d382 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.77 2001/02/23 17:17:25 roberto Exp roberto $ 2** $Id: ltable.c,v 1.78 2001/03/26 14:31:49 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*/
@@ -118,6 +118,7 @@ Hash *luaH_new (lua_State *L, int size) {
118 G(L)->roottable = t; 118 G(L)->roottable = t;
119 t->mark = t; 119 t->mark = t;
120 t->size = 0; 120 t->size = 0;
121 t->weakmode = 0;
121 t->node = NULL; 122 t->node = NULL;
122 setnodevector(L, t, power2(L, size)); 123 setnodevector(L, t, power2(L, size));
123 return t; 124 return t;
diff --git a/ltests.c b/ltests.c
index 4b8fcd01..d012df8b 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.76 2001/03/09 18:05:05 roberto Exp roberto $ 2** $Id: ltests.c,v 1.77 2001/03/26 14:31:49 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -337,9 +337,16 @@ static int table_query (lua_State *L) {
337 return 2; 337 return 2;
338 } 338 }
339 else if (i < t->size) { 339 else if (i < t->size) {
340 TObject o; 340 if (ttype(val(node(t, i))) != LUA_TNIL ||
341 setkey2obj(&o, &t->node[i]); 341 ttype_key(node(t, i)) == LUA_TNIL ||
342 luaA_pushobject(L, &o); 342 ttype_key(node(t, i)) == LUA_TNUMBER ||
343 tsvalue_key(node(t, i)) != NULL) {
344 TObject o;
345 setkey2obj(&o, node(t, i));
346 luaA_pushobject(L, &o);
347 }
348 else
349 lua_pushstring(L, "<undef>");
343 luaA_pushobject(L, &t->node[i].val); 350 luaA_pushobject(L, &t->node[i].val);
344 if (t->node[i].next) { 351 if (t->node[i].next) {
345 lua_pushnumber(L, t->node[i].next - t->node); 352 lua_pushnumber(L, t->node[i].next - t->node);
diff --git a/lua.h b/lua.h
index a6f32e98..6030246f 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.92 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: lua.h,v 1.93 2001/04/06 21:17:37 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil 4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
5** e-mail: lua@tecgraf.puc-rio.br 5** e-mail: lua@tecgraf.puc-rio.br
@@ -46,6 +46,11 @@
46#define LUA_ERRMEM 4 46#define LUA_ERRMEM 4
47#define LUA_ERRERR 5 47#define LUA_ERRERR 5
48 48
49/* weak modes */
50#define LUA_WEAK_KEY 1
51#define LUA_WEAK_VALUE 2
52
53
49typedef struct lua_State lua_State; 54typedef struct lua_State lua_State;
50 55
51typedef int (*lua_CFunction) (lua_State *L); 56typedef int (*lua_CFunction) (lua_State *L);
@@ -208,6 +213,9 @@ LUA_API void lua_concat (lua_State *L, int n);
208 213
209LUA_API void *lua_newuserdata (lua_State *L, size_t size); 214LUA_API void *lua_newuserdata (lua_State *L, size_t size);
210 215
216LUA_API void lua_setweakmode (lua_State *L, int mode);
217LUA_API int lua_getweakmode (lua_State *L, int index);
218
211 219
212/* 220/*
213** =============================================================== 221** ===============================================================
@@ -290,7 +298,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size);
290 298
291 299
292/****************************************************************************** 300/******************************************************************************
293* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. 301* Copyright (C) 1994-2001 TeCGraf, PUC-Rio. All rights reserved.
294* 302*
295* Permission is hereby granted, without written agreement and without license 303* Permission is hereby granted, without written agreement and without license
296* or royalty fees, to use, copy, modify, and distribute this software and its 304* or royalty fees, to use, copy, modify, and distribute this software and its