… | |
… | |
1990 | if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] |
1990 | if (PL_op->op_ppaddr != PL_ppaddr [OP_ENTERSUB] |
1991 | && PL_op->op_ppaddr != pp_slf) |
1991 | && PL_op->op_ppaddr != pp_slf) |
1992 | croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); |
1992 | croak ("FATAL: Coro SLF calls can only be made normally, not via goto or any other means, caught"); |
1993 | |
1993 | |
1994 | if (items > 3) |
1994 | if (items > 3) |
1995 | croak ("Coro only supports up to three arguments to SLF functions currently, caught"); |
1995 | croak ("Coro only supports up to three arguments to SLF functions currently (not %d), caught", items); |
1996 | |
1996 | |
1997 | CvFLAGS (cv) |= CVf_SLF; |
1997 | CvFLAGS (cv) |= CVf_SLF; |
1998 | CvXSUBANY (cv).any_ptr = (void *)init_cb; |
1998 | CvXSUBANY (cv).any_ptr = (void *)init_cb; |
1999 | slf_cv = cv; |
1999 | slf_cv = cv; |
2000 | |
2000 | |
… | |
… | |
2013 | PL_op->op_ppaddr = pp_slf; |
2013 | PL_op->op_ppaddr = pp_slf; |
2014 | |
2014 | |
2015 | PL_op = (OP *)&slf_restore; |
2015 | PL_op = (OP *)&slf_restore; |
2016 | } |
2016 | } |
2017 | |
2017 | |
|
|
2018 | /*****************************************************************************/ |
|
|
2019 | |
|
|
2020 | static int |
|
|
2021 | slf_check_semaphore_down (pTHX_ struct CoroSLF *frame) |
|
|
2022 | { |
|
|
2023 | AV *av = (AV *)frame->data; |
|
|
2024 | SV *count_sv = AvARRAY (av)[0]; |
|
|
2025 | |
|
|
2026 | if (SvIVX (count_sv) > 0) |
|
|
2027 | { |
|
|
2028 | SvIVX (count_sv) = SvIVX (count_sv) - 1; |
|
|
2029 | return 0; |
|
|
2030 | } |
|
|
2031 | else |
|
|
2032 | { |
|
|
2033 | int i; |
|
|
2034 | /* if we were woken up but can't down, we look through the whole */ |
|
|
2035 | /* waiters list and only add us if we aren't in there already */ |
|
|
2036 | /* this avoids some degenerate memory usage cases */ |
|
|
2037 | |
|
|
2038 | for (i = 1; i <= AvFILLp (av); ++i) |
|
|
2039 | if (AvARRAY (av)[i] == SvRV (coro_current)) |
|
|
2040 | return 1; |
|
|
2041 | |
|
|
2042 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
|
|
2043 | return 1; |
|
|
2044 | } |
|
|
2045 | } |
|
|
2046 | |
|
|
2047 | static void |
|
|
2048 | slf_init_semaphore_down (pTHX_ struct CoroSLF *frame, SV **arg, int items) |
|
|
2049 | { |
|
|
2050 | AV *av = (AV *)SvRV (arg [0]); |
|
|
2051 | |
|
|
2052 | if (SvIVX (AvARRAY (av)[0]) > 0) |
|
|
2053 | { |
|
|
2054 | frame->data = (void *)av; |
|
|
2055 | frame->prepare = prepare_nop; |
|
|
2056 | } |
|
|
2057 | else |
|
|
2058 | { |
|
|
2059 | av_push (av, SvREFCNT_inc (SvRV (coro_current))); |
|
|
2060 | |
|
|
2061 | frame->data = (void *)sv_2mortal (SvREFCNT_inc ((SV *)av)); |
|
|
2062 | frame->prepare = prepare_schedule; |
|
|
2063 | } |
|
|
2064 | |
|
|
2065 | frame->check = slf_check_semaphore_down; |
|
|
2066 | |
|
|
2067 | } |
|
|
2068 | |
2018 | MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ |
2069 | MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ |
2019 | |
2070 | |
2020 | PROTOTYPES: DISABLE |
2071 | PROTOTYPES: DISABLE |
2021 | |
2072 | |
2022 | BOOT: |
2073 | BOOT: |
… | |
… | |
2129 | CODE: |
2180 | CODE: |
2130 | _exit (code); |
2181 | _exit (code); |
2131 | |
2182 | |
2132 | int |
2183 | int |
2133 | cctx_stacksize (int new_stacksize = 0) |
2184 | cctx_stacksize (int new_stacksize = 0) |
|
|
2185 | PROTOTYPE: ;$ |
2134 | CODE: |
2186 | CODE: |
2135 | RETVAL = cctx_stacksize; |
2187 | RETVAL = cctx_stacksize; |
2136 | if (new_stacksize) |
2188 | if (new_stacksize) |
2137 | { |
2189 | { |
2138 | cctx_stacksize = new_stacksize; |
2190 | cctx_stacksize = new_stacksize; |
… | |
… | |
2141 | OUTPUT: |
2193 | OUTPUT: |
2142 | RETVAL |
2194 | RETVAL |
2143 | |
2195 | |
2144 | int |
2196 | int |
2145 | cctx_max_idle (int max_idle = 0) |
2197 | cctx_max_idle (int max_idle = 0) |
|
|
2198 | PROTOTYPE: ;$ |
2146 | CODE: |
2199 | CODE: |
2147 | RETVAL = cctx_max_idle; |
2200 | RETVAL = cctx_max_idle; |
2148 | if (max_idle > 1) |
2201 | if (max_idle > 1) |
2149 | cctx_max_idle = max_idle; |
2202 | cctx_max_idle = max_idle; |
2150 | OUTPUT: |
2203 | OUTPUT: |
2151 | RETVAL |
2204 | RETVAL |
2152 | |
2205 | |
2153 | int |
2206 | int |
2154 | cctx_count () |
2207 | cctx_count () |
|
|
2208 | PROTOTYPE: |
2155 | CODE: |
2209 | CODE: |
2156 | RETVAL = cctx_count; |
2210 | RETVAL = cctx_count; |
2157 | OUTPUT: |
2211 | OUTPUT: |
2158 | RETVAL |
2212 | RETVAL |
2159 | |
2213 | |
2160 | int |
2214 | int |
2161 | cctx_idle () |
2215 | cctx_idle () |
|
|
2216 | PROTOTYPE: |
2162 | CODE: |
2217 | CODE: |
2163 | RETVAL = cctx_idle; |
2218 | RETVAL = cctx_idle; |
2164 | OUTPUT: |
2219 | OUTPUT: |
2165 | RETVAL |
2220 | RETVAL |
2166 | |
2221 | |
2167 | void |
2222 | void |
2168 | list () |
2223 | list () |
|
|
2224 | PROTOTYPE: |
2169 | PPCODE: |
2225 | PPCODE: |
2170 | { |
2226 | { |
2171 | struct coro *coro; |
2227 | struct coro *coro; |
2172 | for (coro = coro_first; coro; coro = coro->next) |
2228 | for (coro = coro_first; coro; coro = coro->next) |
2173 | if (coro->hv) |
2229 | if (coro->hv) |
… | |
… | |
2240 | SvREFCNT_dec (self->throw); |
2296 | SvREFCNT_dec (self->throw); |
2241 | self->throw = SvOK (throw) ? newSVsv (throw) : 0; |
2297 | self->throw = SvOK (throw) ? newSVsv (throw) : 0; |
2242 | |
2298 | |
2243 | void |
2299 | void |
2244 | api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) |
2300 | api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) |
|
|
2301 | PROTOTYPE: $;$ |
2245 | C_ARGS: aTHX_ coro, flags |
2302 | C_ARGS: aTHX_ coro, flags |
2246 | |
2303 | |
2247 | SV * |
2304 | SV * |
2248 | has_cctx (Coro::State coro) |
2305 | has_cctx (Coro::State coro) |
2249 | PROTOTYPE: $ |
2306 | PROTOTYPE: $ |
… | |
… | |
2274 | OUTPUT: |
2331 | OUTPUT: |
2275 | RETVAL |
2332 | RETVAL |
2276 | |
2333 | |
2277 | void |
2334 | void |
2278 | force_cctx () |
2335 | force_cctx () |
|
|
2336 | PROTOTYPE: |
2279 | CODE: |
2337 | CODE: |
2280 | struct coro *coro = SvSTATE (coro_current); |
2338 | struct coro *coro = SvSTATE (coro_current); |
2281 | coro->cctx->idle_sp = 0; |
2339 | coro->cctx->idle_sp = 0; |
2282 | |
2340 | |
2283 | void |
2341 | void |
… | |
… | |
2369 | coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; |
2427 | coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; |
2370 | UNLOCK; |
2428 | UNLOCK; |
2371 | |
2429 | |
2372 | int |
2430 | int |
2373 | prio (Coro::State coro, int newprio = 0) |
2431 | prio (Coro::State coro, int newprio = 0) |
|
|
2432 | PROTOTYPE: $;$ |
2374 | ALIAS: |
2433 | ALIAS: |
2375 | nice = 1 |
2434 | nice = 1 |
2376 | CODE: |
2435 | CODE: |
2377 | { |
2436 | { |
2378 | RETVAL = coro->prio; |
2437 | RETVAL = coro->prio; |
… | |
… | |
2442 | { |
2501 | { |
2443 | av_fill (defav, len - 1); |
2502 | av_fill (defav, len - 1); |
2444 | for (i = 0; i < len; ++i) |
2503 | for (i = 0; i < len; ++i) |
2445 | av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1])); |
2504 | av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1])); |
2446 | } |
2505 | } |
2447 | |
|
|
2448 | SvREFCNT_dec (invoke); |
|
|
2449 | } |
2506 | } |
2450 | |
2507 | |
2451 | void |
2508 | void |
2452 | _pool_2 (SV *cb) |
2509 | _pool_2 (SV *cb) |
2453 | CODE: |
2510 | CODE: |
… | |
… | |
2531 | |
2588 | |
2532 | MODULE = Coro::State PACKAGE = Coro::AIO |
2589 | MODULE = Coro::State PACKAGE = Coro::AIO |
2533 | |
2590 | |
2534 | void |
2591 | void |
2535 | _get_state (SV *self) |
2592 | _get_state (SV *self) |
|
|
2593 | PROTOTYPE: $ |
2536 | PPCODE: |
2594 | PPCODE: |
2537 | { |
2595 | { |
2538 | AV *defav = GvAV (PL_defgv); |
2596 | AV *defav = GvAV (PL_defgv); |
2539 | AV *av = newAV (); |
2597 | AV *av = newAV (); |
2540 | int i; |
2598 | int i; |
… | |
… | |
2585 | BOOT: |
2643 | BOOT: |
2586 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2644 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2587 | |
2645 | |
2588 | SV * |
2646 | SV * |
2589 | _schedule (...) |
2647 | _schedule (...) |
2590 | PROTOTYPE: @ |
|
|
2591 | CODE: |
2648 | CODE: |
2592 | { |
2649 | { |
2593 | static int incede; |
2650 | static int incede; |
2594 | |
2651 | |
2595 | api_cede_notself (aTHX); |
2652 | api_cede_notself (aTHX); |
… | |
… | |
2614 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2671 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2615 | |
2672 | |
2616 | BOOT: |
2673 | BOOT: |
2617 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2674 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2618 | |
2675 | |
|
|
2676 | MODULE = Coro::State PACKAGE = Coro::Semaphore |
|
|
2677 | |
|
|
2678 | SV * |
|
|
2679 | new (SV *klass, SV *count_ = 0) |
|
|
2680 | CODE: |
|
|
2681 | { |
|
|
2682 | /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */ |
|
|
2683 | AV *av = newAV (); |
|
|
2684 | av_push (av, newSViv (count_ && SvOK (count_) ? SvIV (count_) : 1)); |
|
|
2685 | RETVAL = sv_bless (newRV_noinc ((SV *)av), GvSTASH (CvGV (cv))); |
|
|
2686 | } |
|
|
2687 | OUTPUT: |
|
|
2688 | RETVAL |
|
|
2689 | |
|
|
2690 | SV * |
|
|
2691 | count (SV *self) |
|
|
2692 | CODE: |
|
|
2693 | RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]); |
|
|
2694 | OUTPUT: |
|
|
2695 | RETVAL |
|
|
2696 | |
|
|
2697 | void |
|
|
2698 | up (SV *self, int adjust = 1) |
|
|
2699 | ALIAS: |
|
|
2700 | adjust = 1 |
|
|
2701 | CODE: |
|
|
2702 | { |
|
|
2703 | AV *av = (AV *)SvRV (self); |
|
|
2704 | SV *count_sv = AvARRAY (av)[0]; |
|
|
2705 | IV count = SvIVX (count_sv); |
|
|
2706 | |
|
|
2707 | count += ix ? adjust : 1; |
|
|
2708 | SvIVX (count_sv) = count; |
|
|
2709 | |
|
|
2710 | /* now wake up as many waiters as possible */ |
|
|
2711 | while (count > 0 && AvFILLp (av) >= count) |
|
|
2712 | { |
|
|
2713 | SV *cb; |
|
|
2714 | |
|
|
2715 | /* swap first two elements so we can shift a waiter */ |
|
|
2716 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
|
|
2717 | AvARRAY (av)[1] = count_sv; |
|
|
2718 | cb = av_shift (av); |
|
|
2719 | |
|
|
2720 | if (SvOBJECT (cb)) |
|
|
2721 | api_ready (cb); |
|
|
2722 | else |
|
|
2723 | croak ("callbacks not yet supported"); |
|
|
2724 | |
|
|
2725 | SvREFCNT_dec (cb); |
|
|
2726 | } |
|
|
2727 | } |
|
|
2728 | |
|
|
2729 | void |
|
|
2730 | down (SV *self) |
|
|
2731 | CODE: |
|
|
2732 | api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), items); |
|
|
2733 | |
|
|
2734 | void |
|
|
2735 | try (SV *self) |
|
|
2736 | PPCODE: |
|
|
2737 | { |
|
|
2738 | AV *av = (AV *)SvRV (self); |
|
|
2739 | SV *count_sv = AvARRAY (av)[0]; |
|
|
2740 | IV count = SvIVX (count_sv); |
|
|
2741 | |
|
|
2742 | if (count > 0) |
|
|
2743 | { |
|
|
2744 | --count; |
|
|
2745 | SvIVX (count_sv) = count; |
|
|
2746 | XSRETURN_YES; |
|
|
2747 | } |
|
|
2748 | else |
|
|
2749 | XSRETURN_NO; |
|
|
2750 | } |
|
|
2751 | |
|
|
2752 | void |
|
|
2753 | waiters (SV *self) |
|
|
2754 | CODE: |
|
|
2755 | { |
|
|
2756 | AV *av = (AV *)SvRV (self); |
|
|
2757 | |
|
|
2758 | if (GIMME_V == G_SCALAR) |
|
|
2759 | XPUSHs (sv_2mortal (newSVsv (AvARRAY (av)[0]))); |
|
|
2760 | else |
|
|
2761 | { |
|
|
2762 | int i; |
|
|
2763 | EXTEND (SP, AvFILLp (av) + 1 - 1); |
|
|
2764 | for (i = 1; i <= AvFILLp (av); ++i) |
|
|
2765 | PUSHs (newSVsv (AvARRAY (av)[i])); |
|
|
2766 | } |
|
|
2767 | } |
|
|
2768 | |