aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-01-11 18:26:52 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-01-11 18:26:52 -0200
commitd56d4cf776b2a874e35d7a92c506840f4a2051b6 (patch)
tree873e9d729b589749aa207916dd1c42843154ce63
parentb7ae43d457ca7b5a46ca768f482b334d70897a14 (diff)
downloadlua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.tar.gz
lua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.tar.bz2
lua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.zip
distinct functions to create/destroy states and threads
-rw-r--r--ldo.h3
-rw-r--r--lgc.c6
-rw-r--r--lstate.c185
-rw-r--r--lstate.h6
-rw-r--r--ltests.c14
-rw-r--r--ltests.h3
-rw-r--r--lua.h6
7 files changed, 135 insertions, 88 deletions
diff --git a/ldo.h b/ldo.h
index 769fccb9..83ed513b 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ 2** $Id: ldo.h,v 1.38 2002/01/11 20:24:39 roberto Exp $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -22,7 +22,6 @@
22#define luaD_checkstack(L,n) if (L->stack_last-(n)<=L->top) luaD_stackerror(L) 22#define luaD_checkstack(L,n) if (L->stack_last-(n)<=L->top) luaD_stackerror(L)
23 23
24 24
25void luaD_init (lua_State *L, int stacksize);
26void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); 25void luaD_lineHook (lua_State *L, int line, lua_Hook linehook);
27void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event); 26void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event);
28StkId luaD_precall (lua_State *L, StkId func); 27StkId luaD_precall (lua_State *L, StkId func);
diff --git a/lgc.c b/lgc.c
index 64eee046..696c726c 100644
--- a/lgc.c
+++ b/lgc.c
@@ -126,6 +126,12 @@ static void markstacks (GCState *st) {
126 lua_State *L1 = st->L; 126 lua_State *L1 = st->L;
127 do { /* for each thread */ 127 do { /* for each thread */
128 StkId o, lim; 128 StkId o, lim;
129 if (L1->base_ci == NULL) { /* incomplete state? */
130 lua_assert(L1 != st->L);
131 L1 = L1->next;
132 luaE_closethread(st->L, L1->previous); /* collect it */
133 continue;
134 }
129 for (o=L1->stack; o<L1->top; o++) 135 for (o=L1->stack; o<L1->top; o++)
130 markobject(st, o); 136 markobject(st, o);
131 lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK 137 lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK
diff --git a/lstate.c b/lstate.c
index bf669bec..ca606adb 100644
--- a/lstate.c
+++ b/lstate.c
@@ -26,7 +26,26 @@ struct Sopen {
26}; 26};
27 27
28 28
29static void close_state (lua_State *L, lua_State *OL); 29static void close_state (lua_State *L);
30
31
32static void stack_init (lua_State *L, lua_State *OL, int stacksize) {
33 if (stacksize == 0)
34 stacksize = DEFAULT_STACK_SIZE;
35 else
36 stacksize += LUA_MINSTACK;
37 stacksize += EXTRA_STACK;
38 L->stack = luaM_newvector(OL, stacksize, TObject);
39 L->stacksize = stacksize;
40 L->top = L->stack + RESERVED_STACK_PREFIX;
41 L->stack_last = L->stack+(L->stacksize-EXTRA_STACK)-1;
42 L->base_ci = luaM_newvector(OL, 10, CallInfo);
43 L->ci = L->base_ci;
44 L->ci->base = L->top;
45 L->ci->savedpc = NULL;
46 L->size_ci = 10;
47 L->end_ci = L->base_ci + L->size_ci;
48}
30 49
31 50
32/* 51/*
@@ -34,93 +53,102 @@ static void close_state (lua_State *L, lua_State *OL);
34*/ 53*/
35static void f_luaopen (lua_State *L, void *ud) { 54static void f_luaopen (lua_State *L, void *ud) {
36 struct Sopen *so = cast(struct Sopen *, ud); 55 struct Sopen *so = cast(struct Sopen *, ud);
37 if (so->stacksize == 0) 56 /* create a new global state */
38 so->stacksize = DEFAULT_STACK_SIZE; 57 L->_G = luaM_new(L, global_State);
39 else 58 G(L)->strt.size = 0;
40 so->stacksize += LUA_MINSTACK; 59 G(L)->strt.nuse = 0;
41 if (so->L != NULL) { /* shared global state? */ 60 G(L)->strt.hash = NULL;
42 L->_G = G(so->L); 61 G(L)->Mbuffer = NULL;
43 so->L->next->previous = L; /* insert L into linked list */ 62 G(L)->Mbuffsize = 0;
44 L->next = so->L->next; 63 G(L)->rootproto = NULL;
45 so->L->next = L; 64 G(L)->rootcl = NULL;
46 L->previous = so->L; 65 G(L)->roottable = NULL;
47 luaD_init(L, so->stacksize); /* init stack */ 66 G(L)->rootupval = NULL;
48 setobj(defaultet(L), defaultet(so->L)); /* share default event table */ 67 G(L)->rootudata = NULL;
49 setobj(gt(L), gt(so->L)); /* share table of globals */ 68 G(L)->tmudata = NULL;
50 setobj(registry(L), registry(so->L)); /* share registry */ 69 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
51 } 70 stack_init(L, L, so->stacksize); /* init stack */
52 else { /* create a new global state */ 71 /* create default event table with a dummy table, and then close the loop */
53 L->_G = luaM_new(L, global_State); 72 sethvalue(defaultet(L), NULL);
54 G(L)->strt.size = 0; 73 sethvalue(defaultet(L), luaH_new(L, 0, 4));
55 G(L)->strt.nuse = 0; 74 hvalue(defaultet(L))->eventtable = hvalue(defaultet(L));
56 G(L)->strt.hash = NULL; 75 sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */
57 G(L)->Mbuffer = NULL; 76 sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */
58 G(L)->Mbuffsize = 0; 77 luaS_resize(L, 4); /* initial size of string table */
59 G(L)->rootproto = NULL; 78 luaT_init(L);
60 G(L)->rootcl = NULL; 79 luaX_init(L);
61 G(L)->roottable = NULL; 80 G(L)->GCthreshold = 4*G(L)->nblocks;
62 G(L)->rootupval = NULL; 81}
63 G(L)->rootudata = NULL; 82
64 G(L)->tmudata = NULL; 83
65 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); 84static void preinit_state (lua_State *L) {
66 luaD_init(L, so->stacksize); /* init stack */ 85 L->stack = NULL;
67 /* create default event table with a dummy table, and then close the loop */ 86 L->stacksize = 0;
68 sethvalue(defaultet(L), NULL); 87 L->errorJmp = NULL;
69 sethvalue(defaultet(L), luaH_new(L, 0, 4)); 88 L->callhook = NULL;
70 hvalue(defaultet(L))->eventtable = hvalue(defaultet(L)); 89 L->linehook = NULL;
71 sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ 90 L->openupval = NULL;
72 sethvalue(registry(L), luaH_new(L, 0, 0)); /* registry */ 91 L->size_ci = 0;
73 luaS_resize(L, 4); /* initial size of string table */ 92 L->base_ci = NULL;
74 luaT_init(L); 93 L->allowhooks = 1;
75 luaX_init(L);
76 G(L)->GCthreshold = 4*G(L)->nblocks;
77 }
78} 94}
79 95
80 96
81LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) { 97LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
82 struct Sopen so;
83 lua_State *L; 98 lua_State *L;
84 if (OL) lua_lock(OL); 99 lua_lock(OL);
85 L = luaM_new(OL, lua_State); 100 L = luaM_new(OL, lua_State);
101 preinit_state(L);
102 L->_G = OL->_G;
103 OL->next->previous = L; /* insert L into linked list */
104 L->next = OL->next;
105 OL->next = L;
106 L->previous = OL;
107 stack_init(L, OL, stacksize); /* init stack */
108 setobj(defaultet(L), defaultet(OL)); /* share default event table */
109 setobj(gt(L), gt(OL)); /* share table of globals */
110 setobj(registry(L), registry(OL)); /* share registry */
111 lua_unlock(OL);
112 lua_userstateopen(L);
113 return L;
114}
115
116
117LUA_API lua_State *lua_open (int stacksize) {
118 struct Sopen so;
119 lua_State *L;
120 L = luaM_new(NULL, lua_State);
86 if (L) { /* allocation OK? */ 121 if (L) { /* allocation OK? */
122 preinit_state(L);
87 L->_G = NULL; 123 L->_G = NULL;
88 L->stack = NULL;
89 L->stacksize = 0;
90 L->errorJmp = NULL;
91 L->callhook = NULL;
92 L->linehook = NULL;
93 L->openupval = NULL;
94 L->size_ci = 0;
95 L->base_ci = NULL;
96 L->allowhooks = 1;
97 L->next = L->previous = L; 124 L->next = L->previous = L;
98 so.stacksize = stacksize; 125 so.stacksize = stacksize;
99 so.L = OL; 126 so.L = NULL;
100 if (luaD_runprotected(L, f_luaopen, &so) != 0) { 127 if (luaD_runprotected(L, f_luaopen, &so) != 0) {
101 /* memory allocation error: free partial state */ 128 /* memory allocation error: free partial state */
102 close_state(L, OL); 129 close_state(L);
103 L = NULL; 130 L = NULL;
104 } 131 }
105 } 132 }
106 if (OL) lua_unlock(OL);
107 lua_userstateopen(L); 133 lua_userstateopen(L);
108 return L; 134 return L;
109} 135}
110 136
111 137
112static void close_state (lua_State *L, lua_State *OL) { 138void luaE_closethread (lua_State *OL, lua_State *L) {
113 luaF_close(L, L->stack); /* close all upvalues for this thread */ 139 luaF_close(L, L->stack); /* close all upvalues for this thread */
114 lua_assert(L->openupval == NULL); 140 lua_assert(L->openupval == NULL);
115 if (OL != NULL) { /* are there other threads? */ 141 L->previous->next = L->next;
116 lua_assert(L->previous != L); 142 L->next->previous = L->previous;
117 L->previous->next = L->next; 143 luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
118 L->next->previous = L->previous; 144 luaM_freearray(OL, L->stack, L->stacksize, TObject);
119 } 145 luaM_freelem(OL, L);
120 else if (G(L)) { /* last thread; close global state */ 146}
121 if (G(L)->rootudata) /* (avoid problems with incomplete states) */ 147
122 luaC_callallgcTM(L); /* call GC tag methods for all udata */ 148
123 lua_assert(G(L)->tmudata == NULL); 149static void close_state (lua_State *L) {
150 luaF_close(L, L->stack); /* close all upvalues for this thread */
151 if (G(L)) { /* close global state */
124 luaC_collect(L, 1); /* collect all elements */ 152 luaC_collect(L, 1); /* collect all elements */
125 lua_assert(G(L)->rootproto == NULL); 153 lua_assert(G(L)->rootproto == NULL);
126 lua_assert(G(L)->rootudata == NULL); 154 lua_assert(G(L)->rootudata == NULL);
@@ -131,21 +159,24 @@ static void close_state (lua_State *L, lua_State *OL) {
131 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char); 159 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
132 luaM_freelem(NULL, L->_G); 160 luaM_freelem(NULL, L->_G);
133 } 161 }
134 luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo); 162 luaE_closethread(NULL, L);
135 luaM_freearray(OL, L->stack, L->stacksize, TObject); 163}
136 luaM_freelem(OL, L); 164
165
166LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
167 if (L == thread) lua_error(L, "cannot close only thread of a state");
168 lua_lock(L);
169 luaE_closethread(L, thread);
170 lua_unlock(L);
137} 171}
138 172
139 173
140LUA_API void lua_close (lua_State *L) { 174LUA_API void lua_close (lua_State *L) {
141 lua_State *OL;
142 lua_assert(L != lua_state || lua_gettop(L) == 0);
143 lua_lock(L); 175 lua_lock(L);
144 OL = L->next; /* any surviving thread (if there is one) */ 176 luaC_callallgcTM(L); /* call GC tag methods for all udata */
145 if (OL == L) OL = NULL; /* no surviving threads */ 177 lua_assert(G(L)->tmudata == NULL);
146 close_state(L, OL); 178 while (L->next != L) /* then, close all other threads */
147 if (OL) lua_unlock(OL); /* cannot unlock over a freed state */ 179 luaE_closethread(L, L->next);
148 lua_assert(L != lua_state || memdebug_numblocks == 0); 180 close_state(L);
149 lua_assert(L != lua_state || memdebug_total == 0);
150} 181}
151 182
diff --git a/lstate.h b/lstate.h
index b7d69af6..978ffbc1 100644
--- a/lstate.h
+++ b/lstate.h
@@ -64,6 +64,9 @@ struct lua_longjmp; /* defined in ldo.c */
64 64
65#define RESERVED_STACK_PREFIX 3 65#define RESERVED_STACK_PREFIX 3
66 66
67/* space to handle stack overflow errors */
68#define EXTRA_STACK (2*LUA_MINSTACK)
69
67 70
68 71
69typedef struct stringtable { 72typedef struct stringtable {
@@ -90,6 +93,7 @@ typedef struct CallInfo {
90 93
91#define ci_func(ci) (clvalue((ci)->base - 1)) 94#define ci_func(ci) (clvalue((ci)->base - 1))
92 95
96#define yield_results refi /* reuse this field */
93 97
94 98
95/* 99/*
@@ -138,5 +142,7 @@ struct lua_State {
138#define G(L) (L->_G) 142#define G(L) (L->_G)
139 143
140 144
145void luaE_closethread (lua_State *OL, lua_State *L);
146
141#endif 147#endif
142 148
diff --git a/ltests.c b/ltests.c
index 72a448bd..3e63d0d3 100644
--- a/ltests.c
+++ b/ltests.c
@@ -36,7 +36,7 @@
36#ifdef LUA_DEBUG 36#ifdef LUA_DEBUG
37 37
38 38
39lua_State *lua_state = NULL; 39static lua_State *lua_state = NULL;
40 40
41int islocked = 0; 41int islocked = 0;
42 42
@@ -374,10 +374,9 @@ static int udataval (lua_State *L) {
374 374
375static int doonnewstack (lua_State *L) { 375static int doonnewstack (lua_State *L) {
376 lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1)); 376 lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1));
377 if (L1 == NULL) return 0;
378 lua_dostring(L1, luaL_check_string(L, 2)); 377 lua_dostring(L1, luaL_check_string(L, 2));
379 lua_pushnumber(L, 1); 378 lua_pushnumber(L, 1);
380 lua_close(L1); 379 lua_closethread(L, L1);
381 return 1; 380 return 1;
382} 381}
383 382
@@ -652,6 +651,14 @@ static const struct luaL_reg tests_funcs[] = {
652}; 651};
653 652
654 653
654static void fim (void) {
655 if (!islocked)
656 lua_close(lua_state);
657 lua_assert(memdebug_numblocks == 0);
658 lua_assert(memdebug_total == 0);
659}
660
661
655void luaB_opentests (lua_State *L) { 662void luaB_opentests (lua_State *L) {
656 *cast(int **, L) = &islocked; /* init lock */ 663 *cast(int **, L) = &islocked; /* init lock */
657 lua_state = L; /* keep first state to be opened */ 664 lua_state = L; /* keep first state to be opened */
@@ -663,6 +670,7 @@ void luaB_opentests (lua_State *L) {
663 luaL_openl(L, tests_funcs); /* open functions inside new table */ 670 luaL_openl(L, tests_funcs); /* open functions inside new table */
664 lua_setglobals(L); /* restore old table of globals */ 671 lua_setglobals(L); /* restore old table of globals */
665 lua_setglobal(L, "T"); /* set new table as global T */ 672 lua_setglobal(L, "T"); /* set new table as global T */
673 atexit(fim);
666} 674}
667 675
668#endif 676#endif
diff --git a/ltests.h b/ltests.h
index 18b703a6..12fac8d3 100644
--- a/ltests.h
+++ b/ltests.h
@@ -48,9 +48,6 @@ extern int islocked;
48#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0) 48#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0)
49 49
50 50
51extern lua_State *lua_state;
52
53
54void luaB_opentests (lua_State *L); 51void luaB_opentests (lua_State *L);
55 52
56#define LUA_USERINIT(L) (luaB_opentests(L), openstdlibs(L)) 53#define LUA_USERINIT(L) (luaB_opentests(L), openstdlibs(L))
diff --git a/lua.h b/lua.h
index 0a2f5b10..89b5818d 100644
--- a/lua.h
+++ b/lua.h
@@ -94,8 +94,10 @@ typedef LUA_NUMBER lua_Number;
94/* 94/*
95** state manipulation 95** state manipulation
96*/ 96*/
97LUA_API lua_State *lua_newthread (lua_State *L, int stacksize); 97LUA_API lua_State *lua_open (int stacksize);
98LUA_API void lua_close (lua_State *L); 98LUA_API void lua_close (lua_State *L);
99LUA_API lua_State *lua_newthread (lua_State *L, int stacksize);
100LUA_API void lua_closethread (lua_State *L, lua_State *thread);
99 101
100 102
101/* 103/*
@@ -215,8 +217,6 @@ LUA_API void lua_newuserdatabox (lua_State *L, void *u);
215** =============================================================== 217** ===============================================================
216*/ 218*/
217 219
218#define lua_open(n) lua_newthread(NULL, (n))
219
220#define lua_pop(L,n) lua_settop(L, -(n)-1) 220#define lua_pop(L,n) lua_settop(L, -(n)-1)
221 221
222#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) 222#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n))