ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
(Generate patch)

Comparing Coro/Coro/State.xs (file contents):
Revision 1.284 by root, Mon Nov 17 01:05:47 2008 UTC vs.
Revision 1.285 by root, Mon Nov 17 04:17:20 2008 UTC

241/* this is a structure representing a perl-level coroutine */ 241/* this is a structure representing a perl-level coroutine */
242struct coro { 242struct coro {
243 /* the C coroutine allocated to this perl coroutine, if any */ 243 /* the C coroutine allocated to this perl coroutine, if any */
244 coro_cctx *cctx; 244 coro_cctx *cctx;
245 245
246 /* process data */ 246 /* state data */
247 struct CoroSLF slf_frame; /* saved slf frame */ 247 struct CoroSLF slf_frame; /* saved slf frame */
248 AV *mainstack; 248 AV *mainstack;
249 perl_slots *slot; /* basically the saved sp */ 249 perl_slots *slot; /* basically the saved sp */
250 250
251 AV *args; /* data associated with this coroutine (initial args) */ 251 AV *args; /* data associated with this coroutine (initial args) */
269}; 269};
270 270
271typedef struct coro *Coro__State; 271typedef struct coro *Coro__State;
272typedef struct coro *Coro__State_or_hashref; 272typedef struct coro *Coro__State_or_hashref;
273 273
274/* the following variables are effectively part of the perl context */
275/* and get copied between struct coro and these variables */
276/* the mainr easonw e don't support windows process emulation */
274static struct CoroSLF slf_frame; /* the current slf frame */ 277static struct CoroSLF slf_frame; /* the current slf frame */
278static SV *coro_throw;
275 279
276/** Coro ********************************************************************/ 280/** Coro ********************************************************************/
277 281
278#define PRIO_MAX 3 282#define PRIO_MAX 3
279#define PRIO_HIGH 1 283#define PRIO_HIGH 1
513 } 517 }
514 518
515 PUTBACK; 519 PUTBACK;
516 } 520 }
517 521
518 slf_frame = c->slf_frame; 522 slf_frame = c->slf_frame;
523 coro_throw = c->throw;
519} 524}
520 525
521static void 526static void
522save_perl (pTHX_ Coro__State c) 527save_perl (pTHX_ Coro__State c)
523{ 528{
529 c->throw = coro_throw;
524 c->slf_frame = slf_frame; 530 c->slf_frame = slf_frame;
525 531
526 { 532 {
527 dSP; 533 dSP;
528 I32 cxix = cxstack_ix; 534 I32 cxix = cxstack_ix;
821slf_check_nop (pTHX_ struct CoroSLF *frame) 827slf_check_nop (pTHX_ struct CoroSLF *frame)
822{ 828{
823 return 0; 829 return 0;
824} 830}
825 831
826static void 832static void NOINLINE /* noinline to keep it out of the transfer fast path */
827coro_setup (pTHX_ struct coro *coro) 833coro_setup (pTHX_ struct coro *coro)
828{ 834{
829 /* 835 /*
830 * emulate part of the perl startup here. 836 * emulate part of the perl startup here.
831 */ 837 */
874 /* this newly created coroutine might be run on an existing cctx which most 880 /* this newly created coroutine might be run on an existing cctx which most
875 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here. 881 * likely was suspended in pp_slf, so we have to emulate entering pp_slf here.
876 */ 882 */
877 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ 883 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */
878 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ 884 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */
885
886 coro_throw = coro->throw;
879} 887}
880 888
881static void 889static void
882coro_destruct (pTHX_ struct coro *coro) 890coro_destruct (pTHX_ struct coro *coro)
883{ 891{
907 915
908 SvREFCNT_dec (PL_diehook); 916 SvREFCNT_dec (PL_diehook);
909 SvREFCNT_dec (PL_warnhook); 917 SvREFCNT_dec (PL_warnhook);
910 918
911 SvREFCNT_dec (coro->saved_deffh); 919 SvREFCNT_dec (coro->saved_deffh);
912 SvREFCNT_dec (coro->throw); 920 SvREFCNT_dec (coro_throw);
913 921
914 coro_destruct_stacks (aTHX); 922 coro_destruct_stacks (aTHX);
915} 923}
916 924
917INLINE void 925INLINE void
1276/** coroutine switching *****************************************************/ 1284/** coroutine switching *****************************************************/
1277 1285
1278static void 1286static void
1279transfer_check (pTHX_ struct coro *prev, struct coro *next) 1287transfer_check (pTHX_ struct coro *prev, struct coro *next)
1280{ 1288{
1289 /* TODO: throwing up here is considered harmful */
1290
1281 if (expect_true (prev != next)) 1291 if (expect_true (prev != next))
1282 { 1292 {
1283 if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) 1293 if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW))))
1284 croak ("Coro::State::transfer called with non-running/new prev Coro::State, but can only transfer from running or new states,"); 1294 croak ("Coro::State::transfer called with non-running/new prev Coro::State, but can only transfer from running or new states,");
1285 1295
1295#endif 1305#endif
1296 } 1306 }
1297} 1307}
1298 1308
1299/* always use the TRANSFER macro */ 1309/* always use the TRANSFER macro */
1300static void NOINLINE 1310static void NOINLINE /* noinline so we have a fixed stackframe */
1301transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx) 1311transfer (pTHX_ struct coro *prev, struct coro *next, int force_cctx)
1302{ 1312{
1303 dSTACKLEVEL; 1313 dSTACKLEVEL;
1304 1314
1305 /* sometimes transfer is only called to set idle_sp */ 1315 /* sometimes transfer is only called to set idle_sp */
1768 1778
1769/*****************************************************************************/ 1779/*****************************************************************************/
1770 1780
1771static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */ 1781static UNOP slf_restore; /* restore stack as entersub did, for first-re-run */
1772static const CV *slf_cv; 1782static const CV *slf_cv;
1773static SV *slf_arg0; 1783static SV **slf_argv;
1774static SV *slf_arg1; 1784static int slf_argc, slf_arga; /* count, allocated */
1775static SV *slf_arg2;
1776static I32 slf_ax; /* top of stack, for restore */ 1785static I32 slf_ax; /* top of stack, for restore */
1777 1786
1778/* this restores the stack in the case we patched the entersub, to */ 1787/* this restores the stack in the case we patched the entersub, to */
1779/* recreate the stack frame as perl will on following calls */ 1788/* recreate the stack frame as perl will on following calls */
1780/* since entersub cleared the stack */ 1789/* since entersub cleared the stack */
1781static OP * 1790static OP *
1782pp_restore (pTHX) 1791pp_restore (pTHX)
1783{ 1792{
1793 int i;
1784 SV **SP = PL_stack_base + slf_ax; 1794 SV **SP = PL_stack_base + slf_ax;
1785 1795
1786 PUSHMARK (SP); 1796 PUSHMARK (SP);
1787 1797
1788 EXTEND (SP, 3); 1798 EXTEND (SP, slf_argc + 1);
1799
1800 for (i = 0; i < slf_argc; ++i)
1789 if (slf_arg0) PUSHs (sv_2mortal (slf_arg0)); 1801 PUSHs (sv_2mortal (slf_argv [i]));
1790 if (slf_arg1) PUSHs (sv_2mortal (slf_arg1)); 1802
1791 if (slf_arg2) PUSHs (sv_2mortal (slf_arg2));
1792 PUSHs ((SV *)CvGV (slf_cv)); 1803 PUSHs ((SV *)CvGV (slf_cv));
1793 1804
1794 RETURNOP (slf_restore.op_first); 1805 RETURNOP (slf_restore.op_first);
1795} 1806}
1796 1807
1814slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) 1825slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta)
1815{ 1826{
1816 SV **arg = (SV **)slf_frame.data; 1827 SV **arg = (SV **)slf_frame.data;
1817 1828
1818 prepare_transfer (aTHX_ ta, arg [0], arg [1]); 1829 prepare_transfer (aTHX_ ta, arg [0], arg [1]);
1819
1820 /* if the destination has ->throw set, then copy it */
1821 /* into the current coro's throw slot, so it will be raised */
1822 /* after the schedule */
1823 if (expect_false (ta->next->throw))
1824 {
1825 struct coro *coro = SvSTATE_current;
1826 SvREFCNT_dec (coro->throw);
1827 coro->throw = ta->next->throw;
1828 ta->next->throw = 0;
1829 }
1830} 1830}
1831 1831
1832static void 1832static void
1833slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 1833slf_init_transfer (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1834{ 1834{
1922 1922
1923 checkmark = PL_stack_sp - PL_stack_base; 1923 checkmark = PL_stack_sp - PL_stack_base;
1924 } 1924 }
1925 while (slf_frame.check (aTHX_ &slf_frame)); 1925 while (slf_frame.check (aTHX_ &slf_frame));
1926 1926
1927 slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */
1928
1929 /* return value handling - mostly like entersub */
1927 { 1930 {
1928 dSP; 1931 dSP;
1929 SV **bot = PL_stack_base + checkmark; 1932 SV **bot = PL_stack_base + checkmark;
1930 int gimme = GIMME_V; 1933 int gimme = GIMME_V;
1931
1932 slf_frame.prepare = 0; /* invalidate the frame, so it gets initialised again next time */
1933 1934
1934 /* make sure we put something on the stack in scalar context */ 1935 /* make sure we put something on the stack in scalar context */
1935 if (gimme == G_SCALAR) 1936 if (gimme == G_SCALAR)
1936 { 1937 {
1937 if (sp == bot) 1938 if (sp == bot)
1941 } 1942 }
1942 1943
1943 PUTBACK; 1944 PUTBACK;
1944 } 1945 }
1945 1946
1946 { 1947 /* exception handling */
1947 struct coro *coro = SvSTATE_current;
1948
1949 if (expect_false (coro->throw)) 1948 if (expect_false (coro_throw))
1950 { 1949 {
1951 SV *exception = sv_2mortal (coro->throw); 1950 SV *exception = sv_2mortal (coro_throw);
1952 1951
1953 coro->throw = 0; 1952 coro_throw = 0;
1954 sv_setsv (ERRSV, exception); 1953 sv_setsv (ERRSV, exception);
1955 croak (0); 1954 croak (0);
1956 } 1955 }
1957 }
1958 1956
1959 return NORMAL; 1957 return NORMAL;
1960} 1958}
1961 1959
1962static void 1960static void
1963api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, I32 ax) 1961api_execute_slf (pTHX_ CV *cv, coro_slf_cb init_cb, I32 ax)
1964{ 1962{
1963 int i;
1965 SV **arg = PL_stack_base + ax; 1964 SV **arg = PL_stack_base + ax;
1966 int items = PL_stack_sp - arg + 1; 1965 int items = PL_stack_sp - arg + 1;
1967 1966
1968 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv))); 1967 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv)));
1969 1968
1970 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] 1969 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB]
1971 && PL_op->op_ppaddr != pp_slf) 1970 && PL_op->op_ppaddr != pp_slf)
1972 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); 1971 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught");
1973
1974#if 0
1975 if (items > 3)
1976 croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items);
1977#endif
1978 1972
1979 CvFLAGS (cv) |= CVf_SLF; 1973 CvFLAGS (cv) |= CVf_SLF;
1980 CvXSUBANY (cv).any_ptr = (void *)init_cb; 1974 CvXSUBANY (cv).any_ptr = (void *)init_cb;
1981 slf_cv = cv; 1975 slf_cv = cv;
1982 1976
1987 slf_restore.op_type = OP_CUSTOM; 1981 slf_restore.op_type = OP_CUSTOM;
1988 slf_restore.op_ppaddr = pp_restore; 1982 slf_restore.op_ppaddr = pp_restore;
1989 slf_restore.op_first = PL_op; 1983 slf_restore.op_first = PL_op;
1990 1984
1991 slf_ax = ax - 1; /* undo the ax++ inside dAXMARK */ 1985 slf_ax = ax - 1; /* undo the ax++ inside dAXMARK */
1992 slf_arg0 = items > 0 ? SvREFCNT_inc (arg [0]) : 0; 1986
1993 slf_arg1 = items > 1 ? SvREFCNT_inc (arg [1]) : 0; 1987 if (items > slf_arga)
1994 slf_arg2 = items > 2 ? SvREFCNT_inc (arg [2]) : 0; 1988 {
1989 slf_arga = items;
1990 free (slf_argv);
1991 slf_argv = malloc (slf_arga * sizeof (SV *));
1992 }
1993
1994 slf_argc = items;
1995
1996 for (i = 0; i < items; ++i)
1997 slf_argv [i] = SvREFCNT_inc (arg [i]);
1995 1998
1996 PL_op->op_ppaddr = pp_slf; 1999 PL_op->op_ppaddr = pp_slf;
1997 PL_op->op_type = OP_CUSTOM; /* maybe we should leave it at entersub? */ 2000 PL_op->op_type = OP_CUSTOM; /* maybe we should leave it at entersub? */
1998 2001
1999 PL_op = (OP *)&slf_restore; 2002 PL_op = (OP *)&slf_restore;
2355 2358
2356void 2359void
2357throw (Coro::State self, SV *throw = &PL_sv_undef) 2360throw (Coro::State self, SV *throw = &PL_sv_undef)
2358 PROTOTYPE: $;$ 2361 PROTOTYPE: $;$
2359 CODE: 2362 CODE:
2363{
2364 struct coro *current = SvSTATE_current;
2365 SV **throwp = self == current ? &coro_throw : &self->throw;
2360 SvREFCNT_dec (self->throw); 2366 SvREFCNT_dec (*throwp);
2361 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2367 *throwp = SvOK (throw) ? newSVsv (throw) : 0;
2368}
2362 2369
2363void 2370void
2364api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 2371api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
2365 PROTOTYPE: $;$ 2372 PROTOTYPE: $;$
2366 C_ARGS: aTHX_ coro, flags 2373 C_ARGS: aTHX_ coro, flags
2568 2575
2569void 2576void
2570_pool_2 (SV *cb) 2577_pool_2 (SV *cb)
2571 CODE: 2578 CODE:
2572{ 2579{
2573 struct coro *coro = SvSTATE_current; 2580 HV *hv = (HV *)SvRV (coro_current);
2581 struct coro *coro = SvSTATE_hv ((SV *)hv);
2574 2582
2575 sv_setsv (cb, &PL_sv_undef); 2583 sv_setsv (cb, &PL_sv_undef);
2576 2584
2577 SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh; 2585 SvREFCNT_dec ((SV *)PL_defoutgv); PL_defoutgv = (GV *)coro->saved_deffh;
2578 coro->saved_deffh = 0; 2586 coro->saved_deffh = 0;
2585 SvREFCNT_dec (old); 2593 SvREFCNT_dec (old);
2586 croak ("\3async_pool terminate\2\n"); 2594 croak ("\3async_pool terminate\2\n");
2587 } 2595 }
2588 2596
2589 av_clear (GvAV (PL_defgv)); 2597 av_clear (GvAV (PL_defgv));
2590 hv_store ((HV *)SvRV (coro_current), "desc", sizeof ("desc") - 1, 2598 hv_store (hv, "desc", sizeof ("desc") - 1,
2591 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0); 2599 newSVpvn ("[async_pool idle]", sizeof ("[async_pool idle]") - 1), 0);
2592 2600
2593 coro->prio = 0; 2601 coro->prio = 0;
2594 2602
2595 if (coro->cctx && (coro->cctx->flags & CC_TRACE)) 2603 if (coro->cctx && (coro->cctx->flags & CC_TRACE))

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines