aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-09-14 11:30:39 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-09-14 11:30:39 -0300
commit0e45ffb8e41fa8f6b156bdaff0685e1ddfdfbd2a (patch)
tree8f59cfee30e72001ccd20d8c4c901cdfe14c9f95 /ldo.c
parent071e54ae0b2fb79bc38c2ca95354886b827c7ccb (diff)
downloadlua-0e45ffb8e41fa8f6b156bdaff0685e1ddfdfbd2a.tar.gz
lua-0e45ffb8e41fa8f6b156bdaff0685e1ddfdfbd2a.tar.bz2
lua-0e45ffb8e41fa8f6b156bdaff0685e1ddfdfbd2a.zip
first implementation of 'lua_yieldk' (yield with continuation)
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/ldo.c b/ldo.c
index e93f68e3..913375b0 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.65 2009/06/01 19:09:26 roberto Exp roberto $ 2** $Id: ldo.c,v 2.66 2009/07/15 17:26:14 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*/
@@ -418,6 +418,16 @@ static void resume (lua_State *L, void *ud) {
418 if (isLua(ci)) /* yielded inside a hook? */ 418 if (isLua(ci)) /* yielded inside a hook? */
419 luaV_execute(L); 419 luaV_execute(L);
420 else { /* 'common' yield */ 420 else { /* 'common' yield */
421 if (ci->u.c.k != NULL) { /* does it have a continuation? */
422 int n;
423 ci->u.c.status = LUA_YIELD; /* 'default' status */
424 ci->callstatus |= CIST_YIELDED;
425 ci->func = restorestack(L, ci->u.c.oldtop);
426 lua_unlock(L);
427 n = (*ci->u.c.k)(L); /* call continuation */
428 lua_lock(L);
429 firstArg = L->top - n;
430 }
421 G(L)->nCcalls--; /* finish 'luaD_call' */ 431 G(L)->nCcalls--; /* finish 'luaD_call' */
422 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ 432 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
423 } 433 }
@@ -499,17 +509,25 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
499 return status; 509 return status;
500} 510}
501 511
502LUA_API int lua_yield (lua_State *L, int nresults) { 512LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
513 CallInfo *ci = L->ci;
503 luai_userstateyield(L, nresults); 514 luai_userstateyield(L, nresults);
504 lua_lock(L); 515 lua_lock(L);
505 if (L->nny > 0) 516 if (L->nny > 0)
506 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); 517 luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
507 L->status = LUA_YIELD; 518 L->status = LUA_YIELD;
508 if (!isLua(L->ci)) { /* not inside a hook? */ 519 if (isLua(ci)) { /* inside a hook? */
509 L->ci->func = L->top - nresults - 1; /* protect stack slots below ??? */ 520 api_check(L, k == NULL, "hooks cannot continue after yielding");
521 }
522 else {
523 if ((ci->u.c.k = k) != NULL) { /* is there a continuation? */
524 ci->u.c.ctx = ctx; /* save context */
525 ci->u.c.oldtop = savestack(L, ci->func); /* save current 'func' */
526 }
527 ci->func = L->top - nresults - 1; /* protect stack slots below */
510 luaD_throw(L, LUA_YIELD); 528 luaD_throw(L, LUA_YIELD);
511 } 529 }
512 lua_assert(L->ci->callstatus & CIST_HOOKED); /* must be inside a hook */ 530 lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
513 lua_unlock(L); 531 lua_unlock(L);
514 return 0; /* otherwise, return to 'luaD_callhook' */ 532 return 0; /* otherwise, return to 'luaD_callhook' */
515} 533}