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); |