diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-11-10 13:37:50 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-11-10 13:37:50 -0200 |
| commit | 53fb65d39451f9245d8ed555f941829520ee6f24 (patch) | |
| tree | 1bf6d58df6213d647270377b1bd231ef4cbfdd8c | |
| parent | a7fa7bafc808103cbb8e27a3c80168617bac8a4f (diff) | |
| download | lua-53fb65d39451f9245d8ed555f941829520ee6f24.tar.gz lua-53fb65d39451f9245d8ed555f941829520ee6f24.tar.bz2 lua-53fb65d39451f9245d8ed555f941829520ee6f24.zip | |
better implementation of `lua_ref' (much better...)
| -rw-r--r-- | lref.c | 47 | ||||
| -rw-r--r-- | lref.h | 15 |
2 files changed, 46 insertions, 16 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: $ | 2 | ** $Id: lref.c,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $ |
| 3 | ** REF mechanism | 3 | ** REF mechanism |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -16,31 +16,36 @@ int luaR_ref (const TObject *o, int lock) { | |||
| 16 | if (ttype(o) == LUA_T_NIL) | 16 | if (ttype(o) == LUA_T_NIL) |
| 17 | ref = LUA_REFNIL; | 17 | ref = LUA_REFNIL; |
| 18 | else { | 18 | else { |
| 19 | for (ref=0; ref<L->refSize; ref++) | 19 | if (L->refFree != NONEXT) { /* is there a free place? */ |
| 20 | if (L->refArray[ref].status == FREE) | 20 | ref = L->refFree; |
| 21 | break; | 21 | L->refFree = L->refArray[ref].st; |
| 22 | if (ref == L->refSize) { /* no more empty spaces? */ | 22 | } |
| 23 | else { /* no more free places */ | ||
| 23 | luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); | 24 | luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); |
| 24 | L->refSize++; | 25 | ref = L->refSize++; |
| 25 | } | 26 | } |
| 26 | L->refArray[ref].o = *o; | 27 | L->refArray[ref].o = *o; |
| 27 | L->refArray[ref].status = lock ? LOCK : HOLD; | 28 | L->refArray[ref].st = lock ? LOCK : HOLD; |
| 28 | } | 29 | } |
| 29 | return ref; | 30 | return ref; |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | 33 | ||
| 33 | void lua_unref (int ref) { | 34 | void lua_unref (int ref) { |
| 34 | if (ref >= 0 && ref < L->refSize) | 35 | if (ref >= 0) { |
| 35 | L->refArray[ref].status = FREE; | 36 | if (ref >= L->refSize || L->refArray[ref].st >= 0) |
| 37 | lua_error("API error - invalid parameter for function `lua_unref'"); | ||
| 38 | L->refArray[ref].st = L->refFree; | ||
| 39 | L->refFree = ref; | ||
| 40 | } | ||
| 36 | } | 41 | } |
| 37 | 42 | ||
| 38 | 43 | ||
| 39 | const TObject *luaR_getref (int ref) { | 44 | const TObject *luaR_getref (int ref) { |
| 40 | if (ref == LUA_REFNIL) | 45 | if (ref == LUA_REFNIL) |
| 41 | return &luaO_nilobject; | 46 | return &luaO_nilobject; |
| 42 | if (ref >= 0 && ref < L->refSize && | 47 | else if (0 <= ref && ref < L->refSize && |
| 43 | (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD)) | 48 | (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) |
| 44 | return &L->refArray[ref].o; | 49 | return &L->refArray[ref].o; |
| 45 | else | 50 | else |
| 46 | return NULL; | 51 | return NULL; |
| @@ -63,16 +68,28 @@ static int ismarked (const TObject *o) { | |||
| 63 | case LUA_T_CMARK: case LUA_T_PMARK: | 68 | case LUA_T_CMARK: case LUA_T_PMARK: |
| 64 | LUA_INTERNALERROR("invalid type"); | 69 | LUA_INTERNALERROR("invalid type"); |
| 65 | #endif | 70 | #endif |
| 66 | default: /* nil, number or cproto */ | 71 | default: /* number or cproto */ |
| 67 | return 1; | 72 | return 1; |
| 68 | } | 73 | } |
| 69 | } | 74 | } |
| 70 | 75 | ||
| 71 | 76 | ||
| 77 | /* for internal debugging only; check if a link of free refs is valid */ | ||
| 78 | #define VALIDLINK(st,n) (NONEXT <= (st) && (st) < (n)) | ||
| 79 | |||
| 72 | void luaR_invalidaterefs (void) { | 80 | void luaR_invalidaterefs (void) { |
| 81 | int n = L->refSize; | ||
| 73 | int i; | 82 | int i; |
| 74 | for (i=0; i<L->refSize; i++) | 83 | for (i=0; i<n; i++) { |
| 75 | if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) | 84 | struct ref *r = &L->refArray[i]; |
| 76 | L->refArray[i].status = COLLECTED; | 85 | if (r->st == HOLD && !ismarked(&r->o)) |
| 86 | r->st = COLLECTED; | ||
| 87 | LUA_ASSERT((r->st == LOCK && ismarked(&r->o)) || | ||
| 88 | r->st == COLLECTED || | ||
| 89 | r->st == NONEXT || | ||
| 90 | (r->st < n && VALIDLINK(L->refArray[r->st].st, n)), | ||
| 91 | "inconsistent ref table"); | ||
| 92 | } | ||
| 93 | LUA_ASSERT(VALIDLINK(L->refFree, n), "inconsistent ref table"); | ||
| 77 | } | 94 | } |
| 78 | 95 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: $ | 2 | ** $Id: lref.h,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $ |
| 3 | ** REF mechanism | 3 | ** REF mechanism |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -9,6 +9,19 @@ | |||
| 9 | 9 | ||
| 10 | #include "lobject.h" | 10 | #include "lobject.h" |
| 11 | 11 | ||
| 12 | |||
| 13 | #define NONEXT -1 /* to end the free list */ | ||
| 14 | #define HOLD -2 | ||
| 15 | #define COLLECTED -3 | ||
| 16 | #define LOCK -4 | ||
| 17 | |||
| 18 | |||
| 19 | struct ref { | ||
| 20 | TObject o; | ||
| 21 | int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */ | ||
| 22 | }; | ||
| 23 | |||
| 24 | |||
| 12 | int luaR_ref (const TObject *o, int lock); | 25 | int luaR_ref (const TObject *o, int lock); |
| 13 | const TObject *luaR_getref (int ref); | 26 | const TObject *luaR_getref (int ref); |
| 14 | void luaR_invalidaterefs (void); | 27 | void luaR_invalidaterefs (void); |
