mirror of https://github.com/lua/lua
new API for weak mode
This commit is contained in:
parent
a2fa48a570
commit
634344d61f
27
lapi.c
27
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;
|
||||
|
|
25
lbaselib.c
25
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 */
|
||||
|
|
63
lgc.c
63
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
|
3
ltable.c
3
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
6
ltm.c
6
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;
|
||||
|
|
11
ltm.h
11
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,
|
||||
|
|
4
lua.h
4
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:info@lua.org
|
||||
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue