diff options
Diffstat (limited to 'lbaselib.c')
-rw-r--r-- | lbaselib.c | 76 |
1 files changed, 42 insertions, 34 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.99 2002/09/16 19:49:45 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.100 2002/10/22 19:41:08 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 | */ |
@@ -362,6 +362,9 @@ static int luaB_tostring (lua_State *L) { | |||
362 | case LUA_TLIGHTUSERDATA: | 362 | case LUA_TLIGHTUSERDATA: |
363 | sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); | 363 | sprintf(buff, "userdata: %p", lua_touserdata(L, 1)); |
364 | break; | 364 | break; |
365 | case LUA_TTHREAD: | ||
366 | sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1)); | ||
367 | break; | ||
365 | case LUA_TNIL: | 368 | case LUA_TNIL: |
366 | lua_pushliteral(L, "nil"); | 369 | lua_pushliteral(L, "nil"); |
367 | return 1; | 370 | return 1; |
@@ -535,26 +538,40 @@ static const luaL_reg base_funcs[] = { | |||
535 | */ | 538 | */ |
536 | 539 | ||
537 | 540 | ||
538 | static int luaB_resume (lua_State *L) { | 541 | static int luaB_auxresume (lua_State *L, lua_State *co) { |
539 | lua_State *co = (lua_State *)lua_unboxpointer(L, lua_upvalueindex(1)); | ||
540 | int status; | 542 | int status; |
541 | lua_settop(L, 0); | 543 | int oldtop = lua_gettop(L); |
542 | status = lua_resume(L, co); | 544 | status = lua_resume(L, co); |
543 | if (status != 0) | 545 | return (status != 0) ? -1 : lua_gettop(L) - oldtop; |
544 | return lua_error(L); | ||
545 | return lua_gettop(L); | ||
546 | } | 546 | } |
547 | 547 | ||
548 | 548 | ||
549 | static int luaB_coresume (lua_State *L) { | ||
550 | lua_State *co = lua_tothread(L, 1); | ||
551 | int r; | ||
552 | luaL_arg_check(L, co, 1, "coroutine/thread expected"); | ||
553 | r = luaB_auxresume(L, co); | ||
554 | if (r < 0) { | ||
555 | lua_pushboolean(L, 0); | ||
556 | lua_insert(L, -2); | ||
557 | return 2; /* return false + error message */ | ||
558 | } | ||
559 | else { | ||
560 | lua_pushboolean(L, 1); | ||
561 | lua_insert(L, -(r + 1)); | ||
562 | return r + 1; /* return true + `resume' returns */ | ||
563 | } | ||
564 | } | ||
565 | |||
549 | 566 | ||
550 | static int gc_coroutine (lua_State *L) { | 567 | static int luaB_auxwrap (lua_State *L) { |
551 | lua_State *co = (lua_State *)lua_unboxpointer(L, 1); | 568 | int r = luaB_auxresume(L, lua_tothread(L, lua_upvalueindex(1))); |
552 | lua_closethread(L, co); | 569 | if (r < 0) lua_error(L); |
553 | return 0; | 570 | return r; |
554 | } | 571 | } |
555 | 572 | ||
556 | 573 | ||
557 | static int luaB_coroutine (lua_State *L) { | 574 | static int luaB_cocreate (lua_State *L) { |
558 | lua_State *NL; | 575 | lua_State *NL; |
559 | int ref; | 576 | int ref; |
560 | int i; | 577 | int i; |
@@ -562,20 +579,21 @@ static int luaB_coroutine (lua_State *L) { | |||
562 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, | 579 | luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, |
563 | "Lua function expected"); | 580 | "Lua function expected"); |
564 | NL = lua_newthread(L); | 581 | NL = lua_newthread(L); |
565 | if (NL == NULL) return luaL_error(L, "unable to create new thread"); | ||
566 | /* move function and arguments from L to NL */ | 582 | /* move function and arguments from L to NL */ |
567 | for (i=0; i<n; i++) { | 583 | for (i = 1; i <= n; i++) { |
584 | lua_pushvalue(L, i); | ||
568 | ref = lua_ref(L, 1); | 585 | ref = lua_ref(L, 1); |
569 | lua_getref(NL, ref); | 586 | lua_getref(NL, ref); |
570 | lua_insert(NL, 1); | ||
571 | lua_unref(L, ref); | 587 | lua_unref(L, ref); |
572 | } | 588 | } |
573 | lua_cobegin(NL, n-1); | 589 | lua_cobegin(NL, n-1); |
574 | lua_boxpointer(L, NL); | 590 | return 1; |
575 | lua_pushliteral(L, "Coroutine"); | 591 | } |
576 | lua_rawget(L, LUA_REGISTRYINDEX); | 592 | |
577 | lua_setmetatable(L, -2); | 593 | |
578 | lua_pushcclosure(L, luaB_resume, 1); | 594 | static int luaB_cowrap (lua_State *L) { |
595 | luaB_cocreate(L); | ||
596 | lua_pushcclosure(L, luaB_auxwrap, 1); | ||
579 | return 1; | 597 | return 1; |
580 | } | 598 | } |
581 | 599 | ||
@@ -585,23 +603,13 @@ static int luaB_yield (lua_State *L) { | |||
585 | } | 603 | } |
586 | 604 | ||
587 | static const luaL_reg co_funcs[] = { | 605 | static const luaL_reg co_funcs[] = { |
588 | {"create", luaB_coroutine}, | 606 | {"create", luaB_cocreate}, |
607 | {"wrap", luaB_cowrap}, | ||
608 | {"resume", luaB_coresume}, | ||
589 | {"yield", luaB_yield}, | 609 | {"yield", luaB_yield}, |
590 | {NULL, NULL} | 610 | {NULL, NULL} |
591 | }; | 611 | }; |
592 | 612 | ||
593 | |||
594 | static void co_open (lua_State *L) { | ||
595 | luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0); | ||
596 | /* create metatable for coroutines */ | ||
597 | lua_pushliteral(L, "Coroutine"); | ||
598 | lua_newtable(L); | ||
599 | lua_pushliteral(L, "__gc"); | ||
600 | lua_pushcfunction(L, gc_coroutine); | ||
601 | lua_rawset(L, -3); | ||
602 | lua_rawset(L, LUA_REGISTRYINDEX); | ||
603 | } | ||
604 | |||
605 | /* }====================================================== */ | 613 | /* }====================================================== */ |
606 | 614 | ||
607 | 615 | ||
@@ -625,7 +633,7 @@ static void base_open (lua_State *L) { | |||
625 | 633 | ||
626 | LUALIB_API int lua_baselibopen (lua_State *L) { | 634 | LUALIB_API int lua_baselibopen (lua_State *L) { |
627 | base_open(L); | 635 | base_open(L); |
628 | co_open(L); | 636 | luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0); |
629 | lua_newtable(L); | 637 | lua_newtable(L); |
630 | lua_setglobal(L, REQTAB); | 638 | lua_setglobal(L, REQTAB); |
631 | return 0; | 639 | return 0; |