diff options
-rw-r--r-- | lapi.c | 19 | ||||
-rw-r--r-- | lbaselib.c | 40 | ||||
-rw-r--r-- | ldo.c | 32 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 4 | ||||
-rw-r--r-- | lua.h | 15 | ||||
-rw-r--r-- | lvm.c | 4 |
7 files changed, 79 insertions, 39 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.17 2004/08/17 17:45:45 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.18 2004/08/30 13:44:44 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -97,6 +97,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
97 | if (from == to) return; | 97 | if (from == to) return; |
98 | lua_lock(to); | 98 | lua_lock(to); |
99 | api_checknelems(from, n); | 99 | api_checknelems(from, n); |
100 | api_check(L, G(from) == G(to)); | ||
100 | from->top -= n; | 101 | from->top -= n; |
101 | for (i = 0; i < n; i++) { | 102 | for (i = 0; i < n; i++) { |
102 | setobj2s(to, to->top, from->top + i); | 103 | setobj2s(to, to->top, from->top + i); |
@@ -479,6 +480,15 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { | |||
479 | } | 480 | } |
480 | 481 | ||
481 | 482 | ||
483 | LUA_API int lua_pushthread (lua_State *L) { | ||
484 | lua_lock(L); | ||
485 | setthvalue(L, L->top, L); | ||
486 | api_incr_top(L); | ||
487 | lua_unlock(L); | ||
488 | return (G(L)->mainthread == L); | ||
489 | } | ||
490 | |||
491 | |||
482 | 492 | ||
483 | /* | 493 | /* |
484 | ** get functions (Lua -> stack) | 494 | ** get functions (Lua -> stack) |
@@ -650,7 +660,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
650 | case LUA_TTABLE: { | 660 | case LUA_TTABLE: { |
651 | hvalue(obj)->metatable = mt; | 661 | hvalue(obj)->metatable = mt; |
652 | if (mt) | 662 | if (mt) |
653 | luaC_objbarrier(L, hvalue(obj), mt); | 663 | luaC_objbarriert(L, hvalue(obj), mt); |
654 | break; | 664 | break; |
655 | } | 665 | } |
656 | case LUA_TUSERDATA: { | 666 | case LUA_TUSERDATA: { |
@@ -816,6 +826,11 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) { | |||
816 | } | 826 | } |
817 | 827 | ||
818 | 828 | ||
829 | LUA_API int lua_threadstatus (lua_State *L) { | ||
830 | return L->status; | ||
831 | } | ||
832 | |||
833 | |||
819 | /* | 834 | /* |
820 | ** Garbage-collection function | 835 | ** Garbage-collection function |
821 | */ | 836 | */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.156 2004/08/30 18:35:14 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.157 2004/09/03 13:16:48 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -523,9 +523,13 @@ static int auxresume (lua_State *L, lua_State *co, int narg) { | |||
523 | int status; | 523 | int status; |
524 | if (!lua_checkstack(co, narg)) | 524 | if (!lua_checkstack(co, narg)) |
525 | luaL_error(L, "too many arguments to resume"); | 525 | luaL_error(L, "too many arguments to resume"); |
526 | if (lua_threadstatus(co) == 0 && lua_gettop(co) == 0) { | ||
527 | lua_pushliteral(L, "cannot resume dead coroutine"); | ||
528 | return -1; /* error flag */ | ||
529 | } | ||
526 | lua_xmove(L, co, narg); | 530 | lua_xmove(L, co, narg); |
527 | status = lua_resume(co, narg); | 531 | status = lua_resume(co, narg); |
528 | if (status == 0) { | 532 | if (status == 0 || status == LUA_YIELD) { |
529 | int nres = lua_gettop(co); | 533 | int nres = lua_gettop(co); |
530 | if (!lua_checkstack(L, nres)) | 534 | if (!lua_checkstack(L, nres)) |
531 | luaL_error(L, "too many results to resume"); | 535 | luaL_error(L, "too many results to resume"); |
@@ -599,22 +603,44 @@ static int luaB_costatus (lua_State *L) { | |||
599 | luaL_argcheck(L, co, 1, "coroutine expected"); | 603 | luaL_argcheck(L, co, 1, "coroutine expected"); |
600 | if (L == co) lua_pushliteral(L, "running"); | 604 | if (L == co) lua_pushliteral(L, "running"); |
601 | else { | 605 | else { |
602 | lua_Debug ar; | 606 | switch (lua_threadstatus(co)) { |
603 | if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0) | 607 | case LUA_YIELD: |
604 | lua_pushliteral(L, "dead"); | 608 | lua_pushliteral(L, "suspended"); |
605 | else | 609 | break; |
606 | lua_pushliteral(L, "suspended"); | 610 | case 0: { |
611 | lua_Debug ar; | ||
612 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ | ||
613 | lua_pushliteral(L, "normal"); /* it is running */ | ||
614 | else if (lua_gettop(co) == 0) | ||
615 | lua_pushliteral(L, "dead"); | ||
616 | else | ||
617 | lua_pushliteral(L, "suspended"); /* initial state */ | ||
618 | break; | ||
619 | } | ||
620 | default: /* some error occured */ | ||
621 | lua_pushliteral(L, "dead"); | ||
622 | break; | ||
623 | } | ||
607 | } | 624 | } |
608 | return 1; | 625 | return 1; |
609 | } | 626 | } |
610 | 627 | ||
611 | 628 | ||
629 | static int luaB_cocurrent (lua_State *L) { | ||
630 | if (lua_pushthread(L)) | ||
631 | return 0; /* main thread is not a coroutine */ | ||
632 | else | ||
633 | return 1; | ||
634 | } | ||
635 | |||
636 | |||
612 | static const luaL_reg co_funcs[] = { | 637 | static const luaL_reg co_funcs[] = { |
613 | {"create", luaB_cocreate}, | 638 | {"create", luaB_cocreate}, |
614 | {"wrap", luaB_cowrap}, | 639 | {"wrap", luaB_cowrap}, |
615 | {"resume", luaB_coresume}, | 640 | {"resume", luaB_coresume}, |
616 | {"yield", luaB_yield}, | 641 | {"yield", luaB_yield}, |
617 | {"status", luaB_costatus}, | 642 | {"status", luaB_costatus}, |
643 | {"current", luaB_cocurrent}, | ||
618 | {NULL, NULL} | 644 | {NULL, NULL} |
619 | }; | 645 | }; |
620 | 646 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.8 2004/09/03 15:48:56 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.9 2004/09/08 14:23:09 roberto Exp roberto $ |
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 | */ |
@@ -358,7 +358,7 @@ static void resume (lua_State *L, void *ud) { | |||
358 | StkId firstResult; | 358 | StkId firstResult; |
359 | int nargs = *cast(int *, ud); | 359 | int nargs = *cast(int *, ud); |
360 | CallInfo *ci = L->ci; | 360 | CallInfo *ci = L->ci; |
361 | if (!L->isSuspended) { | 361 | if (L->status != LUA_YIELD) { |
362 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); | 362 | lua_assert(ci == L->base_ci && nargs < L->top - L->base); |
363 | luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */ | 363 | luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */ |
364 | } | 364 | } |
@@ -372,10 +372,11 @@ static void resume (lua_State *L, void *ud) { | |||
372 | if (nresults >= 0) L->top = L->ci->top; | 372 | if (nresults >= 0) L->top = L->ci->top; |
373 | } /* else yielded inside a hook: just continue its execution */ | 373 | } /* else yielded inside a hook: just continue its execution */ |
374 | } | 374 | } |
375 | L->isSuspended = 0; | 375 | L->status = 0; |
376 | firstResult = luaV_execute(L, L->ci - L->base_ci); | 376 | firstResult = luaV_execute(L, L->ci - L->base_ci); |
377 | if (firstResult != NULL) /* return? */ | 377 | if (firstResult != NULL) { /* return? */ |
378 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ | 378 | luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ |
379 | } | ||
379 | } | 380 | } |
380 | 381 | ||
381 | 382 | ||
@@ -393,25 +394,20 @@ LUA_API int lua_resume (lua_State *L, int nargs) { | |||
393 | lu_byte old_allowhooks; | 394 | lu_byte old_allowhooks; |
394 | lua_lock(L); | 395 | lua_lock(L); |
395 | lua_assert(L->errfunc == 0 && L->nCcalls == 0); | 396 | lua_assert(L->errfunc == 0 && L->nCcalls == 0); |
396 | if (!L->isSuspended) { | 397 | if (L->status != LUA_YIELD) { |
397 | if (L->ci == L->base_ci) { /* no activation record? */ | 398 | if (L->status != 0) |
398 | if (nargs >= L->top - L->base) | 399 | return resume_error(L, "cannot resume dead coroutine"); |
399 | return resume_error(L, "cannot resume dead coroutine"); | 400 | else if (L->ci != L->base_ci) |
400 | } | ||
401 | else | ||
402 | return resume_error(L, "cannot resume non-suspended coroutine"); | 401 | return resume_error(L, "cannot resume non-suspended coroutine"); |
403 | } | 402 | } |
404 | old_allowhooks = L->allowhook; | 403 | old_allowhooks = L->allowhook; |
405 | status = luaD_rawrunprotected(L, resume, &nargs); | 404 | status = luaD_rawrunprotected(L, resume, &nargs); |
406 | if (status != 0) { /* error? */ | 405 | if (status != 0) { /* error? */ |
407 | L->ci = L->base_ci; /* go back to initial level */ | 406 | L->status = status; /* mark thread as `dead' */ |
408 | L->base = L->ci->base; | 407 | seterrorobj(L, status, L->top); |
409 | L->nCcalls = 0; | ||
410 | luaF_close(L, L->base); /* close eventual pending closures */ | ||
411 | seterrorobj(L, status, L->base); | ||
412 | L->allowhook = old_allowhooks; | ||
413 | restore_stack_limit(L); | ||
414 | } | 408 | } |
409 | else | ||
410 | status = L->status; | ||
415 | lua_unlock(L); | 411 | lua_unlock(L); |
416 | return status; | 412 | return status; |
417 | } | 413 | } |
@@ -431,7 +427,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { | |||
431 | L->top = L->base + nresults; | 427 | L->top = L->base + nresults; |
432 | } | 428 | } |
433 | } /* else it's an yield inside a hook: nothing to do */ | 429 | } /* else it's an yield inside a hook: nothing to do */ |
434 | L->isSuspended = 1; | 430 | L->status = LUA_YIELD; |
435 | lua_unlock(L); | 431 | lua_unlock(L); |
436 | return -1; | 432 | return -1; |
437 | } | 433 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.12 2004/08/30 13:44:44 roberto Exp $ | 2 | ** $Id: lstate.c,v 2.13 2004/09/08 14:23:09 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 | */ |
@@ -114,7 +114,7 @@ static void preinit_state (lua_State *L, global_State *g) { | |||
114 | L->openupval = NULL; | 114 | L->openupval = NULL; |
115 | L->size_ci = 0; | 115 | L->size_ci = 0; |
116 | L->nCcalls = 0; | 116 | L->nCcalls = 0; |
117 | L->isSuspended = 0; | 117 | L->status = 0; |
118 | L->base_ci = L->ci = NULL; | 118 | L->base_ci = L->ci = NULL; |
119 | L->errfunc = 0; | 119 | L->errfunc = 0; |
120 | setnilvalue(gt(L)); | 120 | setnilvalue(gt(L)); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.6 2004/08/24 20:12:06 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.7 2004/08/30 13:44:44 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 | */ |
@@ -111,7 +111,7 @@ struct lua_State { | |||
111 | unsigned short nCcalls; /* number of nested C calls */ | 111 | unsigned short nCcalls; /* number of nested C calls */ |
112 | lu_byte hookmask; | 112 | lu_byte hookmask; |
113 | lu_byte allowhook; | 113 | lu_byte allowhook; |
114 | lu_byte isSuspended; | 114 | lu_byte status; |
115 | int basehookcount; | 115 | int basehookcount; |
116 | int hookcount; | 116 | int hookcount; |
117 | lua_Hook hook; | 117 | lua_Hook hook; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lua.h,v 1.191 2004/06/02 17:37:03 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.192 2004/06/04 15:30:53 roberto Exp roberto $ |
3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - An Extensible Extension Language |
4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil | 4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil |
5 | ** http://www.lua.org mailto:info@lua.org | 5 | ** http://www.lua.org mailto:info@lua.org |
@@ -37,11 +37,12 @@ | |||
37 | #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) | 37 | #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) |
38 | 38 | ||
39 | 39 | ||
40 | /* error codes for `lua_pcall' */ | 40 | /* return codes for `lua_pcall', `lua_resume', and `lua_threadstatus' */ |
41 | #define LUA_ERRRUN 1 | 41 | #define LUA_YIELD 1 |
42 | #define LUA_ERRSYNTAX 2 | 42 | #define LUA_ERRRUN 2 |
43 | #define LUA_ERRMEM 3 | 43 | #define LUA_ERRSYNTAX 3 |
44 | #define LUA_ERRERR 4 | 44 | #define LUA_ERRMEM 4 |
45 | #define LUA_ERRERR 5 | ||
45 | 46 | ||
46 | 47 | ||
47 | typedef struct lua_State lua_State; | 48 | typedef struct lua_State lua_State; |
@@ -165,6 +166,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...); | |||
165 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); | 166 | LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); |
166 | LUA_API void lua_pushboolean (lua_State *L, int b); | 167 | LUA_API void lua_pushboolean (lua_State *L, int b); |
167 | LUA_API void lua_pushlightuserdata (lua_State *L, void *p); | 168 | LUA_API void lua_pushlightuserdata (lua_State *L, void *p); |
169 | LUA_API int lua_pushthread (lua_State *L); | ||
168 | 170 | ||
169 | 171 | ||
170 | /* | 172 | /* |
@@ -208,6 +210,7 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data); | |||
208 | */ | 210 | */ |
209 | LUA_API int lua_yield (lua_State *L, int nresults); | 211 | LUA_API int lua_yield (lua_State *L, int nresults); |
210 | LUA_API int lua_resume (lua_State *L, int narg); | 212 | LUA_API int lua_resume (lua_State *L, int narg); |
213 | LUA_API int lua_threadstatus (lua_State *L); | ||
211 | 214 | ||
212 | /* | 215 | /* |
213 | ** garbage-collection function and options | 216 | ** garbage-collection function and options |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.12 2004/08/10 19:17:23 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.13 2004/08/12 14:19:51 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -398,7 +398,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
398 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && | 398 | if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && |
399 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { | 399 | (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { |
400 | traceexec(L, pc); /***/ | 400 | traceexec(L, pc); /***/ |
401 | if (L->isSuspended) { /* did hook yield? */ | 401 | if (L->status == LUA_YIELD) { /* did hook yield? */ |
402 | L->ci->savedpc = pc - 1; | 402 | L->ci->savedpc = pc - 1; |
403 | return NULL; | 403 | return NULL; |
404 | } | 404 | } |