123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /*
- ** $Id: lref.c,v 1.10 2000/03/27 20:10:21 roberto Exp roberto $
- ** reference mechanism
- ** See Copyright Notice in lua.h
- */
- #define LUA_REENTRANT
- #include "lapi.h"
- #include "lmem.h"
- #include "lref.h"
- #include "lstate.h"
- #include "lua.h"
- int lua_ref (lua_State *L, int lock) {
- int ref;
- luaA_checkCargs(L, 1);
- if (ttype(L->top-1) == TAG_NIL)
- ref = LUA_REFNIL;
- else {
- if (L->refFree != NONEXT) { /* is there a free place? */
- ref = L->refFree;
- L->refFree = L->refArray[ref].st;
- }
- else { /* no more free places */
- luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref, refEM, MAX_INT);
- ref = L->refSize++;
- }
- L->refArray[ref].o = *(L->top-1);
- L->refArray[ref].st = lock ? LOCK : HOLD;
- }
- L->top--;
- return ref;
- }
- void lua_unref (lua_State *L, int ref) {
- if (ref >= 0) {
- if (ref >= L->refSize || L->refArray[ref].st >= 0)
- lua_error(L, "Lua API error - "
- "invalid argument for function `lua_unref'");
- L->refArray[ref].st = L->refFree;
- L->refFree = ref;
- }
- }
- lua_Object lua_getref (lua_State *L, int ref) {
- if (ref == LUA_REFNIL)
- return luaA_putluaObject(L, &luaO_nilobject);
- else if (0 <= ref && ref < L->refSize &&
- (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
- return luaA_putluaObject(L, &L->refArray[ref].o);
- else
- return LUA_NOOBJECT;
- }
- void lua_beginblock (lua_State *L) {
- luaM_growvector(L, L->Cblocks, L->numCblocks, 1, struct C_Lua_Stack,
- "too many nested blocks", L->stacksize);
- L->Cblocks[L->numCblocks] = L->Cstack;
- L->numCblocks++;
- }
- void lua_endblock (lua_State *L) {
- if (L->numCblocks <= 0)
- lua_error(L, "Lua API error - no block to end");
- --L->numCblocks;
- L->Cstack = L->Cblocks[L->numCblocks];
- L->top = L->Cstack.base;
- }
- static int ismarked (const TObject *o) {
- /* valid only for locked objects */
- switch (o->ttype) {
- case TAG_STRING: case TAG_USERDATA:
- return o->value.ts->marked;
- case TAG_TABLE:
- return o->value.a->marked;
- case TAG_LCLOSURE: case TAG_CCLOSURE:
- return o->value.cl->marked;
- default: /* number */
- return 1;
- }
- }
- /* for internal debugging only; check if a link of free refs is valid */
- #define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
- void luaR_invalidaterefs (lua_State *L) {
- int n = L->refSize;
- int i;
- for (i=0; i<n; i++) {
- struct Ref *r = &L->refArray[i];
- if (r->st == HOLD && !ismarked(&r->o))
- r->st = COLLECTED;
- LUA_ASSERT(L, (r->st == LOCK && ismarked(&r->o)) ||
- r->st == COLLECTED ||
- r->st == NONEXT ||
- (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)),
- "inconsistent ref table");
- }
- LUA_ASSERT(L, VALIDLINK(L, L->refFree, n), "inconsistent ref table");
- }
|