diff options
Diffstat (limited to 'lstate.c')
-rw-r--r-- | lstate.c | 75 |
1 files changed, 30 insertions, 45 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.54 2001/01/25 16:45:36 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.55 2001/01/26 11:45:51 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -19,33 +19,27 @@ | |||
19 | #include "ltm.h" | 19 | #include "ltm.h" |
20 | 20 | ||
21 | 21 | ||
22 | #ifdef LUA_DEBUG | ||
23 | static lua_State *lua_state = NULL; | ||
24 | void luaB_opentests (lua_State *L); | ||
25 | int islocked = 0; | ||
26 | #endif | ||
27 | |||
28 | |||
29 | /* | ||
30 | ** built-in implementation for ERRORMESSAGE. In a "correct" environment | ||
31 | ** ERRORMESSAGE should have an external definition, and so this function | ||
32 | ** would not be used. | ||
33 | */ | ||
34 | static int errormessage (lua_State *L) { | ||
35 | const char *s = lua_tostring(L, 1); | ||
36 | if (s == NULL) s = "(no message)"; | ||
37 | fprintf(stderr, "error: %s\n", s); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | |||
42 | struct Sopen { | 22 | struct Sopen { |
43 | int stacksize; | 23 | int stacksize; |
44 | lua_State *L; | 24 | lua_State *L; |
45 | }; | 25 | }; |
46 | 26 | ||
47 | 27 | ||
48 | static void close_state (lua_State *L); | 28 | static void close_state (lua_State *L, lua_State *OL); |
29 | |||
30 | |||
31 | /* | ||
32 | ** initialize ref array and registry | ||
33 | */ | ||
34 | #define INIT_REFSIZE 4 | ||
35 | |||
36 | static void ref_init (lua_State *L) { | ||
37 | G(L)->refArray = luaM_newvector(L, INIT_REFSIZE, struct Ref); | ||
38 | G(L)->sizeref = INIT_REFSIZE; | ||
39 | sethvalue(&G(L)->refArray[0].o, luaH_new(L, 0)); | ||
40 | G(L)->refArray[0].st = LOCK; | ||
41 | G(L)->nref = 1; | ||
42 | } | ||
49 | 43 | ||
50 | 44 | ||
51 | /* | 45 | /* |
@@ -90,17 +84,8 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
90 | luaS_init(L); | 84 | luaS_init(L); |
91 | luaX_init(L); | 85 | luaX_init(L); |
92 | luaT_init(L); | 86 | luaT_init(L); |
87 | ref_init(L); | ||
93 | G(L)->GCthreshold = 4*G(L)->nblocks; | 88 | G(L)->GCthreshold = 4*G(L)->nblocks; |
94 | LUA_UNLOCK; /* temporary exit to use the API */ | ||
95 | lua_newtable(L); | ||
96 | lua_ref(L, 1); /* create registry */ | ||
97 | lua_register(L, LUA_ERRORMESSAGE, errormessage); | ||
98 | #ifdef LUA_DEBUG | ||
99 | luaB_opentests(L); | ||
100 | if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ | ||
101 | lua_assert(lua_gettop(L) == 0); | ||
102 | #endif | ||
103 | LUA_LOCK; /* go back inside */ | ||
104 | } | 89 | } |
105 | } | 90 | } |
106 | 91 | ||
@@ -108,7 +93,7 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
108 | LUA_API lua_State *lua_open (lua_State *OL, int stacksize) { | 93 | LUA_API lua_State *lua_open (lua_State *OL, int stacksize) { |
109 | struct Sopen so; | 94 | struct Sopen so; |
110 | lua_State *L; | 95 | lua_State *L; |
111 | LUA_LOCK; | 96 | if (OL) LUA_LOCK(OL); |
112 | L = luaM_new(OL, lua_State); | 97 | L = luaM_new(OL, lua_State); |
113 | if (L) { /* allocation OK? */ | 98 | if (L) { /* allocation OK? */ |
114 | L->G = NULL; | 99 | L->G = NULL; |
@@ -123,20 +108,17 @@ LUA_API lua_State *lua_open (lua_State *OL, int stacksize) { | |||
123 | so.L = OL; | 108 | so.L = OL; |
124 | if (luaD_runprotected(L, f_luaopen, &so) != 0) { | 109 | if (luaD_runprotected(L, f_luaopen, &so) != 0) { |
125 | /* memory allocation error: free partial state */ | 110 | /* memory allocation error: free partial state */ |
126 | close_state(L); | 111 | close_state(L, OL); |
127 | L = NULL; | 112 | L = NULL; |
128 | } | 113 | } |
129 | } | 114 | } |
130 | LUA_UNLOCK; | 115 | if (OL) LUA_UNLOCK(OL); |
131 | return L; | 116 | return L; |
132 | } | 117 | } |
133 | 118 | ||
134 | 119 | ||
135 | static void close_state (lua_State *L) { | 120 | static void close_state (lua_State *L, lua_State *OL) { |
136 | lua_State *L1; | 121 | if (OL != NULL) { /* are there other threads? */ |
137 | L1 = L->next; /* any surviving thread (if there is one) */ | ||
138 | if (L1 == L) L1 = NULL; /* no surviving threads */ | ||
139 | if (L1 != NULL) { /* are there other threads? */ | ||
140 | lua_assert(L->previous != L); | 122 | lua_assert(L->previous != L); |
141 | L->previous->next = L->next; | 123 | L->previous->next = L->next; |
142 | L->next->previous = L->previous; | 124 | L->next->previous = L->previous; |
@@ -152,15 +134,18 @@ static void close_state (lua_State *L) { | |||
152 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); | 134 | luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); |
153 | luaM_freelem(NULL, L->G, global_State); | 135 | luaM_freelem(NULL, L->G, global_State); |
154 | } | 136 | } |
155 | luaM_freearray(L1, L->stack, L->stacksize, TObject); | 137 | luaM_freearray(OL, L->stack, L->stacksize, TObject); |
156 | luaM_freelem(L1, L, lua_State); | 138 | luaM_freelem(OL, L, lua_State); |
157 | } | 139 | } |
158 | 140 | ||
159 | LUA_API void lua_close (lua_State *L) { | 141 | LUA_API void lua_close (lua_State *L) { |
142 | lua_State *OL; | ||
160 | lua_assert(L != lua_state || lua_gettop(L) == 0); | 143 | lua_assert(L != lua_state || lua_gettop(L) == 0); |
161 | LUA_LOCK; | 144 | LUA_LOCK(L); |
162 | close_state(L); | 145 | OL = L->next; /* any surviving thread (if there is one) */ |
163 | LUA_UNLOCK; | 146 | if (OL == L) OL = NULL; /* no surviving threads */ |
147 | close_state(L, OL); | ||
148 | if (OL) LUA_UNLOCK(OL); /* cannot unlock over a freed state */ | ||
164 | lua_assert(L != lua_state || memdebug_numblocks == 0); | 149 | lua_assert(L != lua_state || memdebug_numblocks == 0); |
165 | lua_assert(L != lua_state || memdebug_total == 0); | 150 | lua_assert(L != lua_state || memdebug_total == 0); |
166 | } | 151 | } |