Browse Source

distinct functions to create/destroy states and threads

Roberto Ierusalimschy 23 years ago
parent
commit
d56d4cf776
7 changed files with 135 additions and 88 deletions
  1. 1 2
      ldo.h
  2. 6 0
      lgc.c
  3. 108 77
      lstate.c
  4. 6 0
      lstate.h
  5. 11 3
      ltests.c
  6. 0 3
      ltests.h
  7. 3 3
      lua.h

+ 1 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
+** $Id: ldo.h,v 1.38 2002/01/11 20:24:39 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -22,7 +22,6 @@
 #define luaD_checkstack(L,n) if (L->stack_last-(n)<=L->top) luaD_stackerror(L)
 
 
-void luaD_init (lua_State *L, int stacksize);
 void luaD_lineHook (lua_State *L, int line, lua_Hook linehook);
 void luaD_callHook (lua_State *L, lua_Hook callhook, const char *event);
 StkId luaD_precall (lua_State *L, StkId func);

+ 6 - 0
lgc.c

@@ -126,6 +126,12 @@ static void markstacks (GCState *st) {
   lua_State *L1 = st->L;
   do {  /* for each thread */
     StkId o, lim;
+    if (L1->base_ci == NULL) {  /* incomplete state? */
+      lua_assert(L1 != st->L);
+      L1 = L1->next;
+      luaE_closethread(st->L, L1->previous);  /* collect it */
+      continue;
+    }
     for (o=L1->stack; o<L1->top; o++)
       markobject(st, o);
     lim = (L1->stack_last - L1->ci->base > MAXSTACK) ? L1->ci->base+MAXSTACK

+ 108 - 77
lstate.c

@@ -26,7 +26,26 @@ struct Sopen {
 };
 
 
-static void close_state (lua_State *L, lua_State *OL);
+static void close_state (lua_State *L);
+
+
+static void stack_init (lua_State *L, lua_State *OL, int stacksize) {
+  if (stacksize == 0)
+    stacksize = DEFAULT_STACK_SIZE;
+  else
+    stacksize += LUA_MINSTACK;
+  stacksize += EXTRA_STACK;
+  L->stack = luaM_newvector(OL, stacksize, TObject);
+  L->stacksize = stacksize;
+  L->top = L->stack + RESERVED_STACK_PREFIX;
+  L->stack_last = L->stack+(L->stacksize-EXTRA_STACK)-1;
+  L->base_ci = luaM_newvector(OL, 10, CallInfo);
+  L->ci = L->base_ci;
+  L->ci->base = L->top;
+  L->ci->savedpc = NULL;
+  L->size_ci = 10;
+  L->end_ci = L->base_ci + L->size_ci;
+}
 
 
 /*
@@ -34,93 +53,102 @@ static void close_state (lua_State *L, lua_State *OL);
 */
 static void f_luaopen (lua_State *L, void *ud) {
   struct Sopen *so = cast(struct Sopen *, ud);
-  if (so->stacksize == 0)
-    so->stacksize = DEFAULT_STACK_SIZE;
-  else
-    so->stacksize += LUA_MINSTACK;
-  if (so->L != NULL) {  /* shared global state? */
-    L->_G = G(so->L);
-    so->L->next->previous = L;  /* insert L into linked list */
-    L->next = so->L->next;
-    so->L->next = L;
-    L->previous = so->L;
-    luaD_init(L, so->stacksize);  /* init stack */
-    setobj(defaultet(L), defaultet(so->L));  /* share default event table */
-    setobj(gt(L), gt(so->L));  /* share table of globals */
-    setobj(registry(L), registry(so->L));  /* share registry */
-  }
-  else {  /* create a new global state */
-    L->_G = luaM_new(L, global_State);
-    G(L)->strt.size = 0;
-    G(L)->strt.nuse = 0;
-    G(L)->strt.hash = NULL;
-    G(L)->Mbuffer = NULL;
-    G(L)->Mbuffsize = 0;
-    G(L)->rootproto = NULL;
-    G(L)->rootcl = NULL;
-    G(L)->roottable = NULL;
-    G(L)->rootupval = NULL;
-    G(L)->rootudata = NULL;
-    G(L)->tmudata = NULL;
-    G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
-    luaD_init(L, so->stacksize);  /* init stack */
-    /* create default event table with a dummy table, and then close the loop */
-    sethvalue(defaultet(L), NULL);
-    sethvalue(defaultet(L), luaH_new(L, 0, 4));
-    hvalue(defaultet(L))->eventtable = hvalue(defaultet(L));
-    sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
-    sethvalue(registry(L), luaH_new(L, 0, 0));  /* registry */
-    luaS_resize(L, 4);  /* initial size of string table */
-    luaT_init(L);
-    luaX_init(L);
-    G(L)->GCthreshold = 4*G(L)->nblocks;
-  }
+  /* create a new global state */
+  L->_G = luaM_new(L, global_State);
+  G(L)->strt.size = 0;
+  G(L)->strt.nuse = 0;
+  G(L)->strt.hash = NULL;
+  G(L)->Mbuffer = NULL;
+  G(L)->Mbuffsize = 0;
+  G(L)->rootproto = NULL;
+  G(L)->rootcl = NULL;
+  G(L)->roottable = NULL;
+  G(L)->rootupval = NULL;
+  G(L)->rootudata = NULL;
+  G(L)->tmudata = NULL;
+  G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
+  stack_init(L, L, so->stacksize);  /* init stack */
+  /* create default event table with a dummy table, and then close the loop */
+  sethvalue(defaultet(L), NULL);
+  sethvalue(defaultet(L), luaH_new(L, 0, 4));
+  hvalue(defaultet(L))->eventtable = hvalue(defaultet(L));
+  sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
+  sethvalue(registry(L), luaH_new(L, 0, 0));  /* registry */
+  luaS_resize(L, 4);  /* initial size of string table */
+  luaT_init(L);
+  luaX_init(L);
+  G(L)->GCthreshold = 4*G(L)->nblocks;
+}
+
+
+static void preinit_state (lua_State *L) {
+  L->stack = NULL;
+  L->stacksize = 0;
+  L->errorJmp = NULL;
+  L->callhook = NULL;
+  L->linehook = NULL;
+  L->openupval = NULL;
+  L->size_ci = 0;
+  L->base_ci = NULL;
+  L->allowhooks = 1;
 }
 
 
 LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
-  struct Sopen so;
   lua_State *L;
-  if (OL) lua_lock(OL);
+  lua_lock(OL);
   L = luaM_new(OL, lua_State);
+  preinit_state(L);
+  L->_G = OL->_G;
+  OL->next->previous = L;  /* insert L into linked list */
+  L->next = OL->next;
+  OL->next = L;
+  L->previous = OL;
+  stack_init(L, OL, stacksize);  /* init stack */
+  setobj(defaultet(L), defaultet(OL));  /* share default event table */
+  setobj(gt(L), gt(OL));  /* share table of globals */
+  setobj(registry(L), registry(OL));  /* share registry */
+  lua_unlock(OL);
+  lua_userstateopen(L);
+  return L;
+}
+
+
+LUA_API lua_State *lua_open (int stacksize) {
+  struct Sopen so;
+  lua_State *L;
+  L = luaM_new(NULL, lua_State);
   if (L) {  /* allocation OK? */
+    preinit_state(L);
     L->_G = NULL;
-    L->stack = NULL;
-    L->stacksize = 0;
-    L->errorJmp = NULL;
-    L->callhook = NULL;
-    L->linehook = NULL;
-    L->openupval = NULL;
-    L->size_ci = 0;
-    L->base_ci = NULL;
-    L->allowhooks = 1;
     L->next = L->previous = L;
     so.stacksize = stacksize;
-    so.L = OL;
+    so.L = NULL;
     if (luaD_runprotected(L, f_luaopen, &so) != 0) {
       /* memory allocation error: free partial state */
-      close_state(L, OL);
+      close_state(L);
       L = NULL;
     }
   }
-  if (OL) lua_unlock(OL);
   lua_userstateopen(L);
   return L;
 }
 
 
-static void close_state (lua_State *L, lua_State *OL) {
+void luaE_closethread (lua_State *OL, lua_State *L) {
   luaF_close(L, L->stack);  /* close all upvalues for this thread */
   lua_assert(L->openupval == NULL);
-  if (OL != NULL) {  /* are there other threads? */
-    lua_assert(L->previous != L);
-    L->previous->next = L->next;
-    L->next->previous = L->previous;
-  }
-  else if (G(L)) {  /* last thread; close global state */
-    if (G(L)->rootudata)  /* (avoid problems with incomplete states) */
-      luaC_callallgcTM(L);  /* call GC tag methods for all udata */
-    lua_assert(G(L)->tmudata == NULL);
+  L->previous->next = L->next;
+  L->next->previous = L->previous;
+  luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
+  luaM_freearray(OL, L->stack, L->stacksize, TObject);
+  luaM_freelem(OL, L);
+}
+
+
+static void close_state (lua_State *L) {
+  luaF_close(L, L->stack);  /* close all upvalues for this thread */
+  if (G(L)) {  /* close global state */
     luaC_collect(L, 1);  /* collect all elements */
     lua_assert(G(L)->rootproto == NULL);
     lua_assert(G(L)->rootudata == NULL);
@@ -131,21 +159,24 @@ static void close_state (lua_State *L, lua_State *OL) {
     luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, char);
     luaM_freelem(NULL, L->_G);
   }
-  luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
-  luaM_freearray(OL, L->stack, L->stacksize, TObject);
-  luaM_freelem(OL, L);
+  luaE_closethread(NULL, L);
+}
+
+
+LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
+  if (L == thread) lua_error(L, "cannot close only thread of a state");
+  lua_lock(L);
+  luaE_closethread(L, thread);
+  lua_unlock(L);
 }
 
 
 LUA_API void lua_close (lua_State *L) {
-  lua_State *OL;
-  lua_assert(L != lua_state || lua_gettop(L) == 0);
   lua_lock(L);
-  OL = L->next;  /* any surviving thread (if there is one) */
-  if (OL == L) OL = NULL;  /* no surviving threads */
-  close_state(L, OL);
-  if (OL) lua_unlock(OL);  /* cannot unlock over a freed state */
-  lua_assert(L != lua_state || memdebug_numblocks == 0);
-  lua_assert(L != lua_state || memdebug_total == 0);
+  luaC_callallgcTM(L);  /* call GC tag methods for all udata */
+  lua_assert(G(L)->tmudata == NULL);
+  while (L->next != L)  /* then, close all other threads */
+    luaE_closethread(L, L->next);
+  close_state(L);
 }
 

+ 6 - 0
lstate.h

@@ -64,6 +64,9 @@ struct lua_longjmp;  /* defined in ldo.c */
 
 #define RESERVED_STACK_PREFIX	3
 
+/* space to handle stack overflow errors */
+#define EXTRA_STACK   (2*LUA_MINSTACK)
+
 
 
 typedef struct stringtable {
@@ -90,6 +93,7 @@ typedef struct CallInfo {
 
 #define ci_func(ci)	(clvalue((ci)->base - 1))
 
+#define yield_results	refi	/* reuse this field */
 
 
 /*
@@ -138,5 +142,7 @@ struct lua_State {
 #define G(L)	(L->_G)
 
 
+void luaE_closethread (lua_State *OL, lua_State *L);
+
 #endif
 

+ 11 - 3
ltests.c

@@ -36,7 +36,7 @@
 #ifdef LUA_DEBUG
 
 
-lua_State *lua_state = NULL;
+static lua_State *lua_state = NULL;
 
 int islocked = 0;
 
@@ -374,10 +374,9 @@ static int udataval (lua_State *L) {
 
 static int doonnewstack (lua_State *L) {
   lua_State *L1 = lua_newthread(L, luaL_check_int(L, 1));
-  if (L1 == NULL) return 0;
   lua_dostring(L1, luaL_check_string(L, 2));
   lua_pushnumber(L, 1);
-  lua_close(L1);
+  lua_closethread(L, L1);
   return 1;
 }
 
@@ -652,6 +651,14 @@ static const struct luaL_reg tests_funcs[] = {
 };
 
 
+static void fim (void) {
+  if (!islocked)
+    lua_close(lua_state);
+  lua_assert(memdebug_numblocks == 0);
+  lua_assert(memdebug_total == 0);
+}
+
+
 void luaB_opentests (lua_State *L) {
   *cast(int **, L) = &islocked;  /* init lock */
   lua_state = L;  /* keep first state to be opened */
@@ -663,6 +670,7 @@ void luaB_opentests (lua_State *L) {
   luaL_openl(L, tests_funcs);  /* open functions inside new table */
   lua_setglobals(L);  /* restore old table of globals */
   lua_setglobal(L, "T");  /* set new table as global T */
+  atexit(fim);
 }
 
 #endif

+ 0 - 3
ltests.h

@@ -48,9 +48,6 @@ extern int islocked;
 #define lua_unlock(L)   lua_assert(--(**cast(int **, L)) == 0)
 
 
-extern lua_State *lua_state;
-
-
 void luaB_opentests (lua_State *L);
 
 #define LUA_USERINIT(L) (luaB_opentests(L), openstdlibs(L))

+ 3 - 3
lua.h

@@ -94,8 +94,10 @@ typedef LUA_NUMBER lua_Number;
 /*
 ** state manipulation
 */
-LUA_API lua_State *lua_newthread (lua_State *L, int stacksize);
+LUA_API lua_State *lua_open (int stacksize);
 LUA_API void       lua_close (lua_State *L);
+LUA_API lua_State *lua_newthread (lua_State *L, int stacksize);
+LUA_API void       lua_closethread (lua_State *L, lua_State *thread);
 
 
 /*
@@ -215,8 +217,6 @@ LUA_API void  lua_newuserdatabox (lua_State *L, void *u);
 ** ===============================================================
 */
 
-#define lua_open(n)		lua_newthread(NULL, (n))
-
 #define lua_pop(L,n)		lua_settop(L, -(n)-1)
 
 #define lua_register(L,n,f)	(lua_pushcfunction(L, f), lua_setglobal(L, n))