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.344 by root, Mon Dec 15 19:39:40 2008 UTC vs.
Revision 1.358 by root, Mon Jun 29 04:30:25 2009 UTC

137 137
138#define IN_DESTRUCT PL_dirty 138#define IN_DESTRUCT PL_dirty
139 139
140#if __GNUC__ >= 3 140#if __GNUC__ >= 3
141# define attribute(x) __attribute__(x) 141# define attribute(x) __attribute__(x)
142# define expect(expr,value) __builtin_expect ((expr),(value)) 142# define expect(expr,value) __builtin_expect ((expr), (value))
143# define INLINE static inline 143# define INLINE static inline
144#else 144#else
145# define attribute(x) 145# define attribute(x)
146# define expect(expr,value) (expr) 146# define expect(expr,value) (expr)
147# define INLINE static 147# define INLINE static
156#define GCoroAPI (&coroapi) /* very sneaky */ 156#define GCoroAPI (&coroapi) /* very sneaky */
157 157
158#ifdef USE_ITHREADS 158#ifdef USE_ITHREADS
159# if CORO_PTHREAD 159# if CORO_PTHREAD
160static void *coro_thx; 160static void *coro_thx;
161# endif
162#endif
163
164#ifdef __linux
165# include <time.h> /* for timespec */
166# include <syscall.h> /* for SYS_* */
167# ifdef SYS_clock_gettime
168# define coro_clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
169# define CORO_CLOCK_MONOTONIC 1
170# define CORO_CLOCK_THREAD_CPUTIME_ID 3
161# endif 171# endif
162#endif 172#endif
163 173
164static double (*nvtime)(); /* so why doesn't it take void? */ 174static double (*nvtime)(); /* so why doesn't it take void? */
165 175
261/* this is a structure representing a perl-level coroutine */ 271/* this is a structure representing a perl-level coroutine */
262struct coro { 272struct coro {
263 /* the C coroutine allocated to this perl coroutine, if any */ 273 /* the C coroutine allocated to this perl coroutine, if any */
264 coro_cctx *cctx; 274 coro_cctx *cctx;
265 275
276 /* ready queue */
277 struct coro *next_ready;
278
266 /* state data */ 279 /* state data */
267 struct CoroSLF slf_frame; /* saved slf frame */ 280 struct CoroSLF slf_frame; /* saved slf frame */
268 AV *mainstack; 281 AV *mainstack;
269 perl_slots *slot; /* basically the saved sp */ 282 perl_slots *slot; /* basically the saved sp */
270 283
304/* the mainr easonw e don't support windows process emulation */ 317/* the mainr easonw e don't support windows process emulation */
305static struct CoroSLF slf_frame; /* the current slf frame */ 318static struct CoroSLF slf_frame; /* the current slf frame */
306 319
307/** Coro ********************************************************************/ 320/** Coro ********************************************************************/
308 321
309#define PRIO_MAX 3 322#define CORO_PRIO_MAX 3
310#define PRIO_HIGH 1 323#define CORO_PRIO_HIGH 1
311#define PRIO_NORMAL 0 324#define CORO_PRIO_NORMAL 0
312#define PRIO_LOW -1 325#define CORO_PRIO_LOW -1
313#define PRIO_IDLE -3 326#define CORO_PRIO_IDLE -3
314#define PRIO_MIN -4 327#define CORO_PRIO_MIN -4
315 328
316/* for Coro.pm */ 329/* for Coro.pm */
317static SV *coro_current; 330static SV *coro_current;
318static SV *coro_readyhook; 331static SV *coro_readyhook;
319static AV *coro_ready [PRIO_MAX - PRIO_MIN + 1]; 332static struct coro *coro_ready [CORO_PRIO_MAX - CORO_PRIO_MIN + 1][2]; /* head|tail */
320static CV *cv_coro_run, *cv_coro_terminate; 333static CV *cv_coro_run, *cv_coro_terminate;
321static struct coro *coro_first; 334static struct coro *coro_first;
322#define coro_nready coroapi.nready 335#define coro_nready coroapi.nready
323 336
324/** lowlevel stuff **********************************************************/ 337/** lowlevel stuff **********************************************************/
472static int 485static int
473coro_cv_free (pTHX_ SV *sv, MAGIC *mg) 486coro_cv_free (pTHX_ SV *sv, MAGIC *mg)
474{ 487{
475 AV *padlist; 488 AV *padlist;
476 AV *av = (AV *)mg->mg_obj; 489 AV *av = (AV *)mg->mg_obj;
490
491 /* perl manages to free our internal AV and _then_ call us */
492 if (IN_DESTRUCT)
493 return;
477 494
478 /* casting is fun. */ 495 /* casting is fun. */
479 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av))) 496 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
480 free_padlist (aTHX_ padlist); 497 free_padlist (aTHX_ padlist);
481 498
612 { 629 {
613 while (expect_true (cxix >= 0)) 630 while (expect_true (cxix >= 0))
614 { 631 {
615 PERL_CONTEXT *cx = &ccstk[cxix--]; 632 PERL_CONTEXT *cx = &ccstk[cxix--];
616 633
617 if (expect_true (CxTYPE (cx) == CXt_SUB || CxTYPE (cx) == CXt_FORMAT)) 634 if (expect_true (CxTYPE (cx) == CXt_SUB) || expect_false (CxTYPE (cx) == CXt_FORMAT))
618 { 635 {
619 CV *cv = cx->blk_sub.cv; 636 CV *cv = cx->blk_sub.cv;
620 637
621 if (expect_true (CvDEPTH (cv))) 638 if (expect_true (CvDEPTH (cv)))
622 { 639 {
987} 1004}
988 1005
989static void 1006static void
990coro_destruct_perl (pTHX_ struct coro *coro) 1007coro_destruct_perl (pTHX_ struct coro *coro)
991{ 1008{
1009 SV *svf [9];
1010
1011 {
1012 struct coro *current = SvSTATE_current;
1013
1014 assert (("FATAL: tried to destroy currently running coroutine", coro->mainstack != PL_mainstack));
1015
1016 save_perl (aTHX_ current);
1017 load_perl (aTHX_ coro);
1018
992 coro_unwind_stacks (aTHX); 1019 coro_unwind_stacks (aTHX);
1020 coro_destruct_stacks (aTHX);
993 1021
994 SvREFCNT_dec (GvSV (PL_defgv)); 1022 // now save some sv's to be free'd later
995 SvREFCNT_dec (GvAV (PL_defgv)); 1023 svf [0] = GvSV (PL_defgv);
996 SvREFCNT_dec (GvSV (PL_errgv)); 1024 svf [1] = (SV *)GvAV (PL_defgv);
997 SvREFCNT_dec (PL_defoutgv); 1025 svf [2] = GvSV (PL_errgv);
998 SvREFCNT_dec (PL_rs); 1026 svf [3] = (SV *)PL_defoutgv;
999 SvREFCNT_dec (GvSV (irsgv)); 1027 svf [4] = PL_rs;
1000 SvREFCNT_dec (GvHV (PL_hintgv)); 1028 svf [5] = GvSV (irsgv);
1029 svf [6] = (SV *)GvHV (PL_hintgv);
1030 svf [7] = PL_diehook;
1031 svf [8] = PL_warnhook;
1032 assert (9 == sizeof (svf) / sizeof (*svf));
1001 1033
1002 SvREFCNT_dec (PL_diehook); 1034 load_perl (aTHX_ current);
1003 SvREFCNT_dec (PL_warnhook);
1004 1035 }
1036
1037 {
1038 int i;
1039
1040 for (i = 0; i < sizeof (svf) / sizeof (*svf); ++i)
1041 SvREFCNT_dec (svf [i]);
1042
1005 SvREFCNT_dec (coro->saved_deffh); 1043 SvREFCNT_dec (coro->saved_deffh);
1006 SvREFCNT_dec (coro->rouse_cb); 1044 SvREFCNT_dec (coro->rouse_cb);
1007 SvREFCNT_dec (coro->invoke_cb); 1045 SvREFCNT_dec (coro->invoke_cb);
1008 SvREFCNT_dec (coro->invoke_av); 1046 SvREFCNT_dec (coro->invoke_av);
1009 1047 }
1010 coro_destruct_stacks (aTHX);
1011} 1048}
1012 1049
1013INLINE void 1050INLINE void
1014free_coro_mortal (pTHX) 1051free_coro_mortal (pTHX)
1015{ 1052{
1502 1539
1503 if (coro->mainstack 1540 if (coro->mainstack
1504 && coro->mainstack != main_mainstack 1541 && coro->mainstack != main_mainstack
1505 && coro->slot 1542 && coro->slot
1506 && !PL_dirty) 1543 && !PL_dirty)
1507 {
1508 struct coro *current = SvSTATE_current;
1509
1510 assert (("FATAL: tried to destroy currently running coroutine", coro->mainstack != PL_mainstack));
1511
1512 save_perl (aTHX_ current);
1513 load_perl (aTHX_ coro);
1514
1515 coro_destruct_perl (aTHX_ coro); 1544 coro_destruct_perl (aTHX_ coro);
1516
1517 load_perl (aTHX_ current);
1518
1519 coro->slot = 0;
1520 }
1521 1545
1522 cctx_destroy (coro->cctx); 1546 cctx_destroy (coro->cctx);
1523 SvREFCNT_dec (coro->startcv); 1547 SvREFCNT_dec (coro->startcv);
1524 SvREFCNT_dec (coro->args); 1548 SvREFCNT_dec (coro->args);
1525 SvREFCNT_dec (CORO_THROW); 1549 SvREFCNT_dec (CORO_THROW);
1612/** Coro ********************************************************************/ 1636/** Coro ********************************************************************/
1613 1637
1614INLINE void 1638INLINE void
1615coro_enq (pTHX_ struct coro *coro) 1639coro_enq (pTHX_ struct coro *coro)
1616{ 1640{
1617 av_push (coro_ready [coro->prio - PRIO_MIN], SvREFCNT_inc_NN (coro->hv)); 1641 struct coro **ready = coro_ready [coro->prio - CORO_PRIO_MIN];
1618}
1619 1642
1620INLINE SV * 1643 SvREFCNT_inc_NN (coro->hv);
1644
1645 coro->next_ready = 0;
1646 *(ready [0] ? &ready [1]->next_ready : &ready [0]) = coro;
1647 ready [1] = coro;
1648}
1649
1650INLINE struct coro *
1621coro_deq (pTHX) 1651coro_deq (pTHX)
1622{ 1652{
1623 int prio; 1653 int prio;
1624 1654
1625 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= 0; ) 1655 for (prio = CORO_PRIO_MAX - CORO_PRIO_MIN + 1; --prio >= 0; )
1626 if (AvFILLp (coro_ready [prio]) >= 0) 1656 {
1627 return av_shift (coro_ready [prio]); 1657 struct coro **ready = coro_ready [prio];
1658
1659 if (ready [0])
1660 {
1661 struct coro *coro = ready [0];
1662 ready [0] = coro->next_ready;
1663 return coro;
1664 }
1665 }
1628 1666
1629 return 0; 1667 return 0;
1630} 1668}
1631 1669
1632static int 1670static int
1696static void 1734static void
1697prepare_schedule (pTHX_ struct coro_transfer_args *ta) 1735prepare_schedule (pTHX_ struct coro_transfer_args *ta)
1698{ 1736{
1699 for (;;) 1737 for (;;)
1700 { 1738 {
1701 SV *next_sv = coro_deq (aTHX); 1739 struct coro *next = coro_deq (aTHX);
1702 1740
1703 if (expect_true (next_sv)) 1741 if (expect_true (next))
1704 { 1742 {
1705 struct coro *next = SvSTATE_hv (next_sv);
1706
1707 /* cannot transfer to destroyed coros, skip and look for next */ 1743 /* cannot transfer to destroyed coros, skip and look for next */
1708 if (expect_false (next->flags & (CF_DESTROYED | CF_SUSPENDED))) 1744 if (expect_false (next->flags & (CF_DESTROYED | CF_SUSPENDED)))
1709 SvREFCNT_dec (next_sv); /* coro_nready has already been taken care of by destroy */ 1745 SvREFCNT_dec (next->hv); /* coro_nready has already been taken care of by destroy */
1710 else 1746 else
1711 { 1747 {
1712 next->flags &= ~CF_READY; 1748 next->flags &= ~CF_READY;
1713 --coro_nready; 1749 --coro_nready;
1714 1750
1988 SV *data = (SV *)GENSUB_ARG; 2024 SV *data = (SV *)GENSUB_ARG;
1989 2025
1990 if (SvTYPE (SvRV (data)) != SVt_PVAV) 2026 if (SvTYPE (SvRV (data)) != SVt_PVAV)
1991 { 2027 {
1992 /* first call, set args */ 2028 /* first call, set args */
2029 SV *coro = SvRV (data);
1993 AV *av = newAV (); 2030 AV *av = newAV ();
1994 SV *coro = SvRV (data);
1995 2031
1996 SvRV_set (data, (SV *)av); 2032 SvRV_set (data, (SV *)av);
1997 api_ready (aTHX_ coro);
1998 SvREFCNT_dec (coro);
1999 2033
2000 /* better take a full copy of the arguments */ 2034 /* better take a full copy of the arguments */
2001 while (items--) 2035 while (items--)
2002 av_store (av, items, newSVsv (ST (items))); 2036 av_store (av, items, newSVsv (ST (items)));
2037
2038 api_ready (aTHX_ coro);
2039 SvREFCNT_dec (coro);
2003 } 2040 }
2004 2041
2005 XSRETURN_EMPTY; 2042 XSRETURN_EMPTY;
2006} 2043}
2007 2044
2024 2061
2025 EXTEND (SP, AvFILLp (av) + 1); 2062 EXTEND (SP, AvFILLp (av) + 1);
2026 for (i = 0; i <= AvFILLp (av); ++i) 2063 for (i = 0; i <= AvFILLp (av); ++i)
2027 PUSHs (sv_2mortal (AvARRAY (av)[i])); 2064 PUSHs (sv_2mortal (AvARRAY (av)[i]));
2028 2065
2029 /* we have stolen the elements, so ste length to zero and free */ 2066 /* we have stolen the elements, so set length to zero and free */
2030 AvFILLp (av) = -1; 2067 AvFILLp (av) = -1;
2031 av_undef (av); 2068 av_undef (av);
2032 2069
2033 PUTBACK; 2070 PUTBACK;
2034 } 2071 }
2454/* Coro::Semaphore & Coro::Signal */ 2491/* Coro::Semaphore & Coro::Signal */
2455 2492
2456static SV * 2493static SV *
2457coro_waitarray_new (pTHX_ int count) 2494coro_waitarray_new (pTHX_ int count)
2458{ 2495{
2459 /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */ 2496 /* a waitarray=semaphore contains a counter IV in $sem->[0] and any waiters after that */
2460 AV *av = newAV (); 2497 AV *av = newAV ();
2461 SV **ary; 2498 SV **ary;
2462 2499
2463 /* unfortunately, building manually saves memory */ 2500 /* unfortunately, building manually saves memory */
2464 Newx (ary, 2, SV *); 2501 Newx (ary, 2, SV *);
2608 { 2645 {
2609 /* callback form */ 2646 /* callback form */
2610 AV *av = (AV *)SvRV (arg [0]); 2647 AV *av = (AV *)SvRV (arg [0]);
2611 CV *cb_cv = coro_sv_2cv (aTHX_ arg [1]); 2648 CV *cb_cv = coro_sv_2cv (aTHX_ arg [1]);
2612 2649
2613 av_push (av, (SV *)SvREFCNT_inc_NN (cb_cv)); 2650 av_push (av, SvREFCNT_inc_NN (cb_cv));
2614 2651
2615 if (SvIVX (AvARRAY (av)[0]) > 0) 2652 if (SvIVX (AvARRAY (av)[0]) > 0)
2616 coro_semaphore_adjust (aTHX_ av, 0); 2653 coro_semaphore_adjust (aTHX_ av, 0);
2617 2654
2618 frame->prepare = prepare_nop; 2655 frame->prepare = prepare_nop;
2642 AvARRAY (av)[0] = AvARRAY (av)[1]; 2679 AvARRAY (av)[0] = AvARRAY (av)[1];
2643 AvARRAY (av)[1] = cb; 2680 AvARRAY (av)[1] = cb;
2644 2681
2645 cb = av_shift (av); 2682 cb = av_shift (av);
2646 2683
2684 if (SvTYPE (cb) == SVt_PVCV)
2685 {
2686 dSP;
2687 PUSHMARK (SP);
2688 XPUSHs (sv_2mortal (newRV_inc ((SV *)av)));
2689 PUTBACK;
2690 call_sv (cb, G_VOID | G_DISCARD | G_EVAL | G_KEEPERR);
2691 }
2692 else
2693 {
2647 api_ready (aTHX_ cb); 2694 api_ready (aTHX_ cb);
2648 sv_setiv (cb, 0); /* signal waiter */ 2695 sv_setiv (cb, 0); /* signal waiter */
2696 }
2697
2649 SvREFCNT_dec (cb); 2698 SvREFCNT_dec (cb);
2650 2699
2651 --count; 2700 --count;
2652 } 2701 }
2653} 2702}
2662static void 2711static void
2663slf_init_signal_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2712slf_init_signal_wait (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2664{ 2713{
2665 AV *av = (AV *)SvRV (arg [0]); 2714 AV *av = (AV *)SvRV (arg [0]);
2666 2715
2716 if (items >= 2)
2717 {
2718 CV *cb_cv = coro_sv_2cv (aTHX_ arg [1]);
2719 av_push (av, SvREFCNT_inc_NN (cb_cv));
2720
2667 if (SvIVX (AvARRAY (av)[0])) 2721 if (SvIVX (AvARRAY (av)[0]))
2722 coro_signal_wake (aTHX_ av, 1); /* ust be the only waiter */
2723
2724 frame->prepare = prepare_nop;
2725 frame->check = slf_check_nop;
2726 }
2727 else if (SvIVX (AvARRAY (av)[0]))
2668 { 2728 {
2669 SvIVX (AvARRAY (av)[0]) = 0; 2729 SvIVX (AvARRAY (av)[0]) = 0;
2670 frame->prepare = prepare_nop; 2730 frame->prepare = prepare_nop;
2671 frame->check = slf_check_nop; 2731 frame->check = slf_check_nop;
2672 } 2732 }
2673 else 2733 else
2674 { 2734 {
2675 SV *waiter = newRV_inc (SvRV (coro_current)); /* owned by signal av */ 2735 SV *waiter = newSVsv (coro_current); /* owned by signal av */
2676 2736
2677 av_push (av, waiter); 2737 av_push (av, waiter);
2678 2738
2679 frame->data = (void *)sv_2mortal (SvREFCNT_inc_NN (waiter)); /* owned by process */ 2739 frame->data = (void *)sv_2mortal (SvREFCNT_inc_NN (waiter)); /* owned by process */
2680 frame->prepare = prepare_schedule; 2740 frame->prepare = prepare_schedule;
2921 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer"); 2981 if (!SvIOK (*svp)) croak ("Time::NVtime isn't a function pointer");
2922 2982
2923 nvtime = INT2PTR (double (*)(), SvIV (*svp)); 2983 nvtime = INT2PTR (double (*)(), SvIV (*svp));
2924 } 2984 }
2925 2985
2926 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL)); 2986 assert (("PRIO_NORMAL must be 0", !CORO_PRIO_NORMAL));
2927} 2987}
2928 2988
2929SV * 2989SV *
2930new (char *klass, ...) 2990new (char *klass, ...)
2931 ALIAS: 2991 ALIAS:
3133 CODE: 3193 CODE:
3134{ 3194{
3135 struct coro *current = SvSTATE_current; 3195 struct coro *current = SvSTATE_current;
3136 SV **throwp = self == current ? &CORO_THROW : &self->except; 3196 SV **throwp = self == current ? &CORO_THROW : &self->except;
3137 SvREFCNT_dec (*throwp); 3197 SvREFCNT_dec (*throwp);
3198 SvGETMAGIC (throw);
3138 *throwp = SvOK (throw) ? newSVsv (throw) : 0; 3199 *throwp = SvOK (throw) ? newSVsv (throw) : 0;
3139} 3200}
3140 3201
3141void 3202void
3142api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 3203api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
3205 3266
3206MODULE = Coro::State PACKAGE = Coro 3267MODULE = Coro::State PACKAGE = Coro
3207 3268
3208BOOT: 3269BOOT:
3209{ 3270{
3210 int i;
3211
3212 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); 3271 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);
3213 sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE); 3272 sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE);
3214 cv_coro_run = get_cv ( "Coro::_coro_run" , GV_ADD); 3273 cv_coro_run = get_cv ( "Coro::_coro_run" , GV_ADD);
3215 cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD); 3274 cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD);
3216 coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); 3275 coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current);
3224 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler); 3283 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler);
3225 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new); 3284 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new);
3226 3285
3227 coro_stash = gv_stashpv ("Coro", TRUE); 3286 coro_stash = gv_stashpv ("Coro", TRUE);
3228 3287
3229 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (PRIO_MAX)); 3288 newCONSTSUB (coro_stash, "PRIO_MAX", newSViv (CORO_PRIO_MAX));
3230 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (PRIO_HIGH)); 3289 newCONSTSUB (coro_stash, "PRIO_HIGH", newSViv (CORO_PRIO_HIGH));
3231 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (PRIO_NORMAL)); 3290 newCONSTSUB (coro_stash, "PRIO_NORMAL", newSViv (CORO_PRIO_NORMAL));
3232 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (PRIO_LOW)); 3291 newCONSTSUB (coro_stash, "PRIO_LOW", newSViv (CORO_PRIO_LOW));
3233 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (PRIO_IDLE)); 3292 newCONSTSUB (coro_stash, "PRIO_IDLE", newSViv (CORO_PRIO_IDLE));
3234 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (PRIO_MIN)); 3293 newCONSTSUB (coro_stash, "PRIO_MIN", newSViv (CORO_PRIO_MIN));
3235
3236 for (i = PRIO_MAX - PRIO_MIN + 1; i--; )
3237 coro_ready[i] = newAV ();
3238 3294
3239 { 3295 {
3240 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE); 3296 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE);
3241 3297
3242 coroapi.schedule = api_schedule; 3298 coroapi.schedule = api_schedule;
3294void 3350void
3295_set_readyhook (SV *hook) 3351_set_readyhook (SV *hook)
3296 PROTOTYPE: $ 3352 PROTOTYPE: $
3297 CODE: 3353 CODE:
3298 SvREFCNT_dec (coro_readyhook); 3354 SvREFCNT_dec (coro_readyhook);
3355 SvGETMAGIC (hook);
3299 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; 3356 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0;
3300 3357
3301int 3358int
3302prio (Coro::State coro, int newprio = 0) 3359prio (Coro::State coro, int newprio = 0)
3303 PROTOTYPE: $;$ 3360 PROTOTYPE: $;$
3334 PROTOTYPE: 3391 PROTOTYPE:
3335 CODE: 3392 CODE:
3336 RETVAL = coro_nready; 3393 RETVAL = coro_nready;
3337 OUTPUT: 3394 OUTPUT:
3338 RETVAL 3395 RETVAL
3396
3397void
3398suspend (Coro::State self)
3399 PROTOTYPE: $
3400 CODE:
3401 self->flags |= CF_SUSPENDED;
3402
3403void
3404resume (Coro::State self)
3405 PROTOTYPE: $
3406 CODE:
3407 self->flags &= ~CF_SUSPENDED;
3339 3408
3340void 3409void
3341_pool_handler (...) 3410_pool_handler (...)
3342 CODE: 3411 CODE:
3343 CORO_EXECUTE_SLF_XS (slf_init_pool_handler); 3412 CORO_EXECUTE_SLF_XS (slf_init_pool_handler);
3418 av_push (*avp, SvREFCNT_inc (block)); 3487 av_push (*avp, SvREFCNT_inc (block));
3419 3488
3420 if (!ix) 3489 if (!ix)
3421 on_enterleave_call (aTHX_ block); 3490 on_enterleave_call (aTHX_ block);
3422 3491
3423 LEAVE; /* pp_entersub unfortunately forces an ENTER/LEAVE around xs calls */ 3492 LEAVE; /* pp_entersub unfortunately forces an ENTER/LEAVE around XS calls */
3424 SAVEDESTRUCTOR_X (ix ? coro_pop_on_leave : coro_pop_on_enter, (void *)coro); 3493 SAVEDESTRUCTOR_X (ix ? coro_pop_on_leave : coro_pop_on_enter, (void *)coro);
3425 ENTER; /* pp_entersub unfortunately forces an ENTER/LEAVE around xs calls */ 3494 ENTER; /* pp_entersub unfortunately forces an ENTER/LEAVE around XS calls */
3426} 3495}
3427 3496
3428 3497
3429MODULE = Coro::State PACKAGE = PerlIO::cede 3498MODULE = Coro::State PACKAGE = PerlIO::cede
3430 3499
3435MODULE = Coro::State PACKAGE = Coro::Semaphore 3504MODULE = Coro::State PACKAGE = Coro::Semaphore
3436 3505
3437SV * 3506SV *
3438new (SV *klass, SV *count = 0) 3507new (SV *klass, SV *count = 0)
3439 CODE: 3508 CODE:
3509{
3510 int semcnt = 1;
3511
3512 if (count)
3513 {
3514 SvGETMAGIC (count);
3515
3516 if (SvOK (count))
3517 semcnt = SvIV (count);
3518 }
3519
3440 RETVAL = sv_bless ( 3520 RETVAL = sv_bless (
3441 coro_waitarray_new (aTHX_ count && SvOK (count) ? SvIV (count) : 1), 3521 coro_waitarray_new (aTHX_ semcnt),
3442 GvSTASH (CvGV (cv)) 3522 GvSTASH (CvGV (cv))
3443 ); 3523 );
3524}
3444 OUTPUT: 3525 OUTPUT:
3445 RETVAL 3526 RETVAL
3446 3527
3447# helper for Coro::Channel and others 3528# helper for Coro::Channel and others
3448SV * 3529SV *

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines