diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-11 18:26:52 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-11 18:26:52 -0200 |
| commit | d56d4cf776b2a874e35d7a92c506840f4a2051b6 (patch) | |
| tree | 873e9d729b589749aa207916dd1c42843154ce63 | |
| parent | b7ae43d457ca7b5a46ca768f482b334d70897a14 (diff) | |
| download | lua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.tar.gz lua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.tar.bz2 lua-d56d4cf776b2a874e35d7a92c506840f4a2051b6.zip | |
distinct functions to create/destroy states and threads
| -rw-r--r-- | ldo.h | 3 | ||||
| -rw-r--r-- | lgc.c | 6 | ||||
| -rw-r--r-- | lstate.c | 185 | ||||
| -rw-r--r-- | lstate.h | 6 | ||||
| -rw-r--r-- | ltests.c | 14 | ||||
| -rw-r--r-- | ltests.h | 3 | ||||
| -rw-r--r-- | lua.h | 6 |
7 files changed, 135 insertions, 88 deletions
| @@ -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 | ||
| 25 | void luaD_init (lua_State *L, int stacksize); | ||
| 26 | void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); | 25 | void luaD_lineHook (lua_State *L, int line, lua_Hook linehook); |
| 27 | void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event); | 26 | void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event); |
| 28 | StkId luaD_precall (lua_State *L, StkId func); | 27 | StkId luaD_precall (lua_State *L, StkId func); |
| @@ -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 |
| @@ -26,7 +26,26 @@ struct Sopen { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | static void close_state (lua_State *L, lua_State *OL); | 29 | static void close_state (lua_State *L); |
| 30 | |||
| 31 | |||
| 32 | static 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 | */ |
| 35 | static void f_luaopen (lua_State *L, void *ud) { | 54 | static 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); | 84 | static 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 | ||
| 81 | LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) { | 97 | LUA_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 | |||
| 117 | LUA_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 | ||
| 112 | static void close_state (lua_State *L, lua_State *OL) { | 138 | void 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); | 149 | static 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 | |||
| 166 | LUA_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 | ||
| 140 | LUA_API void lua_close (lua_State *L) { | 174 | LUA_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 | ||
| @@ -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 | ||
| 69 | typedef struct stringtable { | 72 | typedef 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 | ||
| 145 | void luaE_closethread (lua_State *OL, lua_State *L); | ||
| 146 | |||
| 141 | #endif | 147 | #endif |
| 142 | 148 | ||
| @@ -36,7 +36,7 @@ | |||
| 36 | #ifdef LUA_DEBUG | 36 | #ifdef LUA_DEBUG |
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | lua_State *lua_state = NULL; | 39 | static lua_State *lua_state = NULL; |
| 40 | 40 | ||
| 41 | int islocked = 0; | 41 | int islocked = 0; |
| 42 | 42 | ||
| @@ -374,10 +374,9 @@ static int udataval (lua_State *L) { | |||
| 374 | 374 | ||
| 375 | static int doonnewstack (lua_State *L) { | 375 | static 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 | ||
| 654 | static 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 | |||
| 655 | void luaB_opentests (lua_State *L) { | 662 | void 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 |
| @@ -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 | ||
| 51 | extern lua_State *lua_state; | ||
| 52 | |||
| 53 | |||
| 54 | void luaB_opentests (lua_State *L); | 51 | void 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)) |
| @@ -94,8 +94,10 @@ typedef LUA_NUMBER lua_Number; | |||
| 94 | /* | 94 | /* |
| 95 | ** state manipulation | 95 | ** state manipulation |
| 96 | */ | 96 | */ |
| 97 | LUA_API lua_State *lua_newthread (lua_State *L, int stacksize); | 97 | LUA_API lua_State *lua_open (int stacksize); |
| 98 | LUA_API void lua_close (lua_State *L); | 98 | LUA_API void lua_close (lua_State *L); |
| 99 | LUA_API lua_State *lua_newthread (lua_State *L, int stacksize); | ||
| 100 | LUA_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)) |
