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.273 by root, Fri Nov 14 23:48:10 2008 UTC vs.
Revision 1.278 by root, Sun Nov 16 07:09:28 2008 UTC

811 811
812 return orig_sigelem_set ? orig_sigelem_set (aTHX_ sv, mg) : 0; 812 return orig_sigelem_set ? orig_sigelem_set (aTHX_ sv, mg) : 0;
813} 813}
814 814
815static void 815static void
816prepare_nop (aTHX_ struct coro_transfer_args *ta) 816prepare_nop (pTHX_ struct coro_transfer_args *ta)
817{ 817{
818 /* kind of mega-hacky, but works */ 818 /* kind of mega-hacky, but works */
819 ta->next = ta->prev = (struct coro *)ta; 819 ta->next = ta->prev = (struct coro *)ta;
820} 820}
821 821
822static int 822static int
823slf_check_nop (aTHX) 823slf_check_nop (pTHX_ struct CoroSLF *frame)
824{ 824{
825 return 0; 825 return 0;
826} 826}
827 827
828static void 828static void
1320 dSTACKLEVEL; 1320 dSTACKLEVEL;
1321 1321
1322 /* sometimes transfer is only called to set idle_sp */ 1322 /* sometimes transfer is only called to set idle_sp */
1323 if (expect_false (!next)) 1323 if (expect_false (!next))
1324 { 1324 {
1325 ((coro_cctx *)prev)->idle_sp = stacklevel; 1325 ((coro_cctx *)prev)->idle_sp = (void *)stacklevel;
1326 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */ 1326 assert (((coro_cctx *)prev)->idle_te = PL_top_env); /* just for the side-effect when asserts are enabled */
1327 } 1327 }
1328 else if (expect_true (prev != next)) 1328 else if (expect_true (prev != next))
1329 { 1329 {
1330 coro_cctx *prev__cctx; 1330 coro_cctx *prev__cctx;
1357 1357
1358 prev__cctx = prev->cctx; 1358 prev__cctx = prev->cctx;
1359 1359
1360 /* possibly untie and reuse the cctx */ 1360 /* possibly untie and reuse the cctx */
1361 if (expect_true ( 1361 if (expect_true (
1362 prev__cctx->idle_sp == stacklevel 1362 prev__cctx->idle_sp == (void *)stacklevel
1363 && !(prev__cctx->flags & CC_TRACE) 1363 && !(prev__cctx->flags & CC_TRACE)
1364 && !force_cctx 1364 && !force_cctx
1365 )) 1365 ))
1366 { 1366 {
1367 /* I assume that stacklevel is a stronger indicator than PL_top_env changes */ 1367 /* I assume that stacklevel is a stronger indicator than PL_top_env changes */
1719 PL_runops = RUNOPS_DEFAULT; 1719 PL_runops = RUNOPS_DEFAULT;
1720 else 1720 else
1721 coro->slot->runops = RUNOPS_DEFAULT; 1721 coro->slot->runops = RUNOPS_DEFAULT;
1722 } 1722 }
1723} 1723}
1724
1725#if 0
1726static int
1727coro_gensub_free (pTHX_ SV *sv, MAGIC *mg)
1728{
1729 AV *padlist;
1730 AV *av = (AV *)mg->mg_obj;
1731
1732 abort ();
1733
1734 return 0;
1735}
1736
1737static MGVTBL coro_gensub_vtbl = {
1738 0, 0, 0, 0,
1739 coro_gensub_free
1740};
1741#endif
1742 1724
1743/*****************************************************************************/ 1725/*****************************************************************************/
1744/* PerlIO::cede */ 1726/* PerlIO::cede */
1745 1727
1746typedef struct 1728typedef struct
1862static void 1844static void
1863slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) 1845slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta)
1864{ 1846{
1865 SV **arg = (SV **)slf_frame.data; 1847 SV **arg = (SV **)slf_frame.data;
1866 1848
1867 prepare_transfer (ta, arg [0], arg [1]); 1849 prepare_transfer (aTHX_ ta, arg [0], arg [1]);
1868} 1850}
1869 1851
1870static void 1852static void
1871slf_init_transfer (pTHX_ struct CoroSLF *frame, SV **arg, int items) 1853slf_init_transfer (pTHX_ struct CoroSLF *frame, SV **arg, int items)
1872{ 1854{
1987{ 1969{
1988 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv))); 1970 assert (("FATAL: SLF call with illegal CV value", !CvANON (cv)));
1989 1971
1990 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] 1972 if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB]
1991 && PL_op->op_ppaddr != pp_slf) 1973 && PL_op->op_ppaddr != pp_slf)
1992 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or other means, caught"); 1974 croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught");
1993 1975
1994 if (items > 3) 1976 if (items > 3)
1995 croak ("Coro only supports up to three arguments to SLF functions currently, caught"); 1977 croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items);
1996 1978
1997 CvFLAGS (cv) |= CVf_SLF; 1979 CvFLAGS (cv) |= CVf_SLF;
1998 CvXSUBANY (cv).any_ptr = (void *)init_cb; 1980 CvXSUBANY (cv).any_ptr = (void *)init_cb;
1999 slf_cv = cv; 1981 slf_cv = cv;
2000 1982
2013 PL_op->op_ppaddr = pp_slf; 1995 PL_op->op_ppaddr = pp_slf;
2014 1996
2015 PL_op = (OP *)&slf_restore; 1997 PL_op = (OP *)&slf_restore;
2016} 1998}
2017 1999
2000/*****************************************************************************/
2001
2002static int
2003slf_check_semaphore_down (pTHX_ struct CoroSLF *frame)
2004{
2005 AV *av = (AV *)frame->data;
2006 SV *count_sv = AvARRAY (av)[0];
2007
2008 if (SvIVX (count_sv) > 0)
2009 {
2010 SvIVX (count_sv) = SvIVX (count_sv) - 1;
2011 return 0;
2012 }
2013 else
2014 {
2015 int i;
2016 /* if we were woken up but can't down, we look through the whole */
2017 /* waiters list and only add us if we aren't in there already */
2018 /* this avoids some degenerate memory usage cases */
2019
2020 for (i = 1; i <= AvFILLp (av); ++i)
2021 if (AvARRAY (av)[i] == SvRV (coro_current))
2022 return 1;
2023
2024 av_push (av, SvREFCNT_inc (SvRV (coro_current)));
2025 return 1;
2026 }
2027}
2028
2029static void
2030slf_init_semaphore_down (pTHX_ struct CoroSLF *frame, SV **arg, int items)
2031{
2032 AV *av = (AV *)SvRV (arg [0]);
2033
2034 if (SvIVX (AvARRAY (av)[0]) > 0)
2035 {
2036 frame->data = (void *)av;
2037 frame->prepare = prepare_nop;
2038 }
2039 else
2040 {
2041 av_push (av, SvREFCNT_inc (SvRV (coro_current)));
2042
2043 frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av));
2044 frame->prepare = prepare_schedule;
2045 }
2046
2047 frame->check = slf_check_semaphore_down;
2048
2049}
2050
2051/*****************************************************************************/
2052
2053#define GENSUB_ARG CvXSUBANY (cv).any_ptr
2054
2055/* create a closure from XS, returns a code reference */
2056/* the arg can be accessed via GENSUB_ARG from the callback */
2057/* the callback must use dXSARGS/XSRETURN */
2058static SV *
2059gensub (pTHX_ void (*xsub)(pTHX_ CV *), void *arg)
2060{
2061 CV *cv = (CV *)NEWSV (0, 0);
2062
2063 sv_upgrade ((SV *)cv, SVt_PVCV);
2064
2065 CvANON_on (cv);
2066 CvISXSUB_on (cv);
2067 CvXSUB (cv) = xsub;
2068 GENSUB_ARG = arg;
2069
2070 return newRV_noinc ((SV *)cv);
2071}
2072
2073/*****************************************************************************/
2074
2018MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ 2075MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
2019 2076
2020PROTOTYPES: DISABLE 2077PROTOTYPES: DISABLE
2021 2078
2022BOOT: 2079BOOT:
2111 CODE: 2168 CODE:
2112 api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items); 2169 api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items);
2113 2170
2114void 2171void
2115transfer (...) 2172transfer (...)
2173 PROTOTYPE: $$
2116 CODE: 2174 CODE:
2117 api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items); 2175 api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items);
2118 2176
2119bool 2177bool
2120_destroy (SV *coro_sv) 2178_destroy (SV *coro_sv)
2129 CODE: 2187 CODE:
2130 _exit (code); 2188 _exit (code);
2131 2189
2132int 2190int
2133cctx_stacksize (int new_stacksize = 0) 2191cctx_stacksize (int new_stacksize = 0)
2192 PROTOTYPE: ;$
2134 CODE: 2193 CODE:
2135 RETVAL = cctx_stacksize; 2194 RETVAL = cctx_stacksize;
2136 if (new_stacksize) 2195 if (new_stacksize)
2137 { 2196 {
2138 cctx_stacksize = new_stacksize; 2197 cctx_stacksize = new_stacksize;
2141 OUTPUT: 2200 OUTPUT:
2142 RETVAL 2201 RETVAL
2143 2202
2144int 2203int
2145cctx_max_idle (int max_idle = 0) 2204cctx_max_idle (int max_idle = 0)
2205 PROTOTYPE: ;$
2146 CODE: 2206 CODE:
2147 RETVAL = cctx_max_idle; 2207 RETVAL = cctx_max_idle;
2148 if (max_idle > 1) 2208 if (max_idle > 1)
2149 cctx_max_idle = max_idle; 2209 cctx_max_idle = max_idle;
2150 OUTPUT: 2210 OUTPUT:
2151 RETVAL 2211 RETVAL
2152 2212
2153int 2213int
2154cctx_count () 2214cctx_count ()
2215 PROTOTYPE:
2155 CODE: 2216 CODE:
2156 RETVAL = cctx_count; 2217 RETVAL = cctx_count;
2157 OUTPUT: 2218 OUTPUT:
2158 RETVAL 2219 RETVAL
2159 2220
2160int 2221int
2161cctx_idle () 2222cctx_idle ()
2223 PROTOTYPE:
2162 CODE: 2224 CODE:
2163 RETVAL = cctx_idle; 2225 RETVAL = cctx_idle;
2164 OUTPUT: 2226 OUTPUT:
2165 RETVAL 2227 RETVAL
2166 2228
2167void 2229void
2168list () 2230list ()
2231 PROTOTYPE:
2169 PPCODE: 2232 PPCODE:
2170{ 2233{
2171 struct coro *coro; 2234 struct coro *coro;
2172 for (coro = coro_first; coro; coro = coro->next) 2235 for (coro = coro_first; coro; coro = coro->next)
2173 if (coro->hv) 2236 if (coro->hv)
2240 SvREFCNT_dec (self->throw); 2303 SvREFCNT_dec (self->throw);
2241 self->throw = SvOK (throw) ? newSVsv (throw) : 0; 2304 self->throw = SvOK (throw) ? newSVsv (throw) : 0;
2242 2305
2243void 2306void
2244api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) 2307api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB)
2308 PROTOTYPE: $;$
2245 C_ARGS: aTHX_ coro, flags 2309 C_ARGS: aTHX_ coro, flags
2246 2310
2247SV * 2311SV *
2248has_cctx (Coro::State coro) 2312has_cctx (Coro::State coro)
2249 PROTOTYPE: $ 2313 PROTOTYPE: $
2274 OUTPUT: 2338 OUTPUT:
2275 RETVAL 2339 RETVAL
2276 2340
2277void 2341void
2278force_cctx () 2342force_cctx ()
2343 PROTOTYPE:
2279 CODE: 2344 CODE:
2280 struct coro *coro = SvSTATE (coro_current); 2345 struct coro *coro = SvSTATE (coro_current);
2281 coro->cctx->idle_sp = 0; 2346 coro->cctx->idle_sp = 0;
2282 2347
2283void 2348void
2339} 2404}
2340 2405
2341void 2406void
2342schedule (...) 2407schedule (...)
2343 CODE: 2408 CODE:
2344 api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), items); 2409 api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), 0);
2345 2410
2346void 2411void
2347cede (...) 2412cede (...)
2348 CODE: 2413 CODE:
2349 api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), items); 2414 api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), 0);
2350 2415
2351void 2416void
2352cede_notself (...) 2417cede_notself (...)
2353 CODE: 2418 CODE:
2354 api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), items); 2419 api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), 0);
2355 2420
2356void 2421void
2357_set_current (SV *current) 2422_set_current (SV *current)
2358 PROTOTYPE: $ 2423 PROTOTYPE: $
2359 CODE: 2424 CODE:
2369 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; 2434 coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0;
2370 UNLOCK; 2435 UNLOCK;
2371 2436
2372int 2437int
2373prio (Coro::State coro, int newprio = 0) 2438prio (Coro::State coro, int newprio = 0)
2439 PROTOTYPE: $;$
2374 ALIAS: 2440 ALIAS:
2375 nice = 1 2441 nice = 1
2376 CODE: 2442 CODE:
2377{ 2443{
2378 RETVAL = coro->prio; 2444 RETVAL = coro->prio;
2442 { 2508 {
2443 av_fill (defav, len - 1); 2509 av_fill (defav, len - 1);
2444 for (i = 0; i < len; ++i) 2510 for (i = 0; i < len; ++i)
2445 av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1])); 2511 av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1]));
2446 } 2512 }
2447
2448 SvREFCNT_dec (invoke);
2449} 2513}
2450 2514
2451void 2515void
2452_pool_2 (SV *cb) 2516_pool_2 (SV *cb)
2453 CODE: 2517 CODE:
2478 api_trace (aTHX_ coro_current, 0); 2542 api_trace (aTHX_ coro_current, 0);
2479 2543
2480 av_push (av_async_pool, newSVsv (coro_current)); 2544 av_push (av_async_pool, newSVsv (coro_current));
2481} 2545}
2482 2546
2483#if 0
2484
2485void
2486_generator_call (...)
2487 PROTOTYPE: @
2488 PPCODE:
2489 fprintf (stderr, "call %p\n", CvXSUBANY(cv).any_ptr);
2490 xxxx
2491 abort ();
2492
2493SV *
2494gensub (SV *sub, ...)
2495 PROTOTYPE: &;@
2496 CODE:
2497{
2498 struct coro *coro;
2499 MAGIC *mg;
2500 CV *xcv;
2501 CV *ncv = (CV *)newSV_type (SVt_PVCV);
2502 int i;
2503
2504 CvGV (ncv) = CvGV (cv);
2505 CvFILE (ncv) = CvFILE (cv);
2506
2507 Newz (0, coro, 1, struct coro);
2508 coro->args = newAV ();
2509 coro->flags = CF_NEW;
2510
2511 av_extend (coro->args, items - 1);
2512 for (i = 1; i < items; i++)
2513 av_push (coro->args, newSVsv (ST (i)));
2514
2515 CvISXSUB_on (ncv);
2516 CvXSUBANY (ncv).any_ptr = (void *)coro;
2517
2518 xcv = GvCV (gv_fetchpv ("Coro::_generator_call", 0, SVt_PVCV));
2519
2520 CvXSUB (ncv) = CvXSUB (xcv);
2521 CvANON_on (ncv);
2522
2523 mg = sv_magicext ((SV *)ncv, 0, CORO_MAGIC_type_state, &coro_gensub_vtbl, (char *)coro, 0);
2524 RETVAL = newRV_noinc ((SV *)ncv);
2525}
2526 OUTPUT:
2527 RETVAL
2528
2529#endif
2530
2531 2547
2532MODULE = Coro::State PACKAGE = Coro::AIO 2548MODULE = Coro::State PACKAGE = Coro::AIO
2533 2549
2534void 2550void
2535_get_state (SV *self) 2551_get_state (SV *self)
2552 PROTOTYPE: $
2536 PPCODE: 2553 PPCODE:
2537{ 2554{
2538 AV *defav = GvAV (PL_defgv); 2555 AV *defav = GvAV (PL_defgv);
2539 AV *av = newAV (); 2556 AV *av = newAV ();
2540 int i; 2557 int i;
2583MODULE = Coro::State PACKAGE = Coro::AnyEvent 2600MODULE = Coro::State PACKAGE = Coro::AnyEvent
2584 2601
2585BOOT: 2602BOOT:
2586 sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); 2603 sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE);
2587 2604
2588SV * 2605void
2589_schedule (...) 2606_schedule (...)
2590 PROTOTYPE: @
2591 CODE: 2607 CODE:
2592{ 2608{
2593 static int incede; 2609 static int incede;
2594 2610
2595 api_cede_notself (aTHX); 2611 api_cede_notself (aTHX);
2614MODULE = Coro::State PACKAGE = PerlIO::cede 2630MODULE = Coro::State PACKAGE = PerlIO::cede
2615 2631
2616BOOT: 2632BOOT:
2617 PerlIO_define_layer (aTHX_ &PerlIO_cede); 2633 PerlIO_define_layer (aTHX_ &PerlIO_cede);
2618 2634
2635MODULE = Coro::State PACKAGE = Coro::Semaphore
2636
2637SV *
2638new (SV *klass, SV *count_ = 0)
2639 CODE:
2640{
2641 /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */
2642 AV *av = newAV ();
2643 av_push (av, newSViv (count_ && SvOK (count_) ? SvIV (count_) : 1));
2644 RETVAL = sv_bless (newRV_noinc ((SV *)av), GvSTASH (CvGV (cv)));
2645}
2646 OUTPUT:
2647 RETVAL
2648
2649SV *
2650count (SV *self)
2651 CODE:
2652 RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]);
2653 OUTPUT:
2654 RETVAL
2655
2656void
2657up (SV *self, int adjust = 1)
2658 ALIAS:
2659 adjust = 1
2660 CODE:
2661{
2662 AV *av = (AV *)SvRV (self);
2663 SV *count_sv = AvARRAY (av)[0];
2664 IV count = SvIVX (count_sv);
2665
2666 count += ix ? adjust : 1;
2667 SvIVX (count_sv) = count;
2668
2669 /* now wake up as many waiters as possible */
2670 while (count > 0 && AvFILLp (av) >= count)
2671 {
2672 SV *cb;
2673
2674 /* swap first two elements so we can shift a waiter */
2675 AvARRAY (av)[0] = AvARRAY (av)[1];
2676 AvARRAY (av)[1] = count_sv;
2677 cb = av_shift (av);
2678
2679 if (SvOBJECT (cb))
2680 api_ready (aTHX_ cb);
2681 else
2682 croak ("callbacks not yet supported");
2683
2684 SvREFCNT_dec (cb);
2685 }
2686}
2687
2688void
2689down (SV *self)
2690 CODE:
2691 api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), 1);
2692
2693void
2694try (SV *self)
2695 PPCODE:
2696{
2697 AV *av = (AV *)SvRV (self);
2698 SV *count_sv = AvARRAY (av)[0];
2699 IV count = SvIVX (count_sv);
2700
2701 if (count > 0)
2702 {
2703 --count;
2704 SvIVX (count_sv) = count;
2705 XSRETURN_YES;
2706 }
2707 else
2708 XSRETURN_NO;
2709}
2710
2711void
2712waiters (SV *self)
2713 CODE:
2714{
2715 AV *av = (AV *)SvRV (self);
2716
2717 if (GIMME_V == G_SCALAR)
2718 XPUSHs (sv_2mortal (newSVsv (AvARRAY (av)[0])));
2719 else
2720 {
2721 int i;
2722 EXTEND (SP, AvFILLp (av) + 1 - 1);
2723 for (i = 1; i <= AvFILLp (av); ++i)
2724 PUSHs (newSVsv (AvARRAY (av)[i]));
2725 }
2726}
2727

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines