… | |
… | |
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: |
… | |
… | |
2111 | CODE: |
2162 | CODE: |
2112 | api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items); |
2163 | api_execute_slf (aTHX_ cv, slf_init_set_stacklevel, &ST (0), items); |
2113 | |
2164 | |
2114 | void |
2165 | void |
2115 | transfer (...) |
2166 | transfer (...) |
|
|
2167 | PROTOTYPE: $$ |
2116 | CODE: |
2168 | CODE: |
2117 | api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items); |
2169 | api_execute_slf (aTHX_ cv, slf_init_transfer, &ST (0), items); |
2118 | |
2170 | |
2119 | bool |
2171 | bool |
2120 | _destroy (SV *coro_sv) |
2172 | _destroy (SV *coro_sv) |
… | |
… | |
2129 | CODE: |
2181 | CODE: |
2130 | _exit (code); |
2182 | _exit (code); |
2131 | |
2183 | |
2132 | int |
2184 | int |
2133 | cctx_stacksize (int new_stacksize = 0) |
2185 | cctx_stacksize (int new_stacksize = 0) |
|
|
2186 | PROTOTYPE: ;$ |
2134 | CODE: |
2187 | CODE: |
2135 | RETVAL = cctx_stacksize; |
2188 | RETVAL = cctx_stacksize; |
2136 | if (new_stacksize) |
2189 | if (new_stacksize) |
2137 | { |
2190 | { |
2138 | cctx_stacksize = new_stacksize; |
2191 | cctx_stacksize = new_stacksize; |
… | |
… | |
2141 | OUTPUT: |
2194 | OUTPUT: |
2142 | RETVAL |
2195 | RETVAL |
2143 | |
2196 | |
2144 | int |
2197 | int |
2145 | cctx_max_idle (int max_idle = 0) |
2198 | cctx_max_idle (int max_idle = 0) |
|
|
2199 | PROTOTYPE: ;$ |
2146 | CODE: |
2200 | CODE: |
2147 | RETVAL = cctx_max_idle; |
2201 | RETVAL = cctx_max_idle; |
2148 | if (max_idle > 1) |
2202 | if (max_idle > 1) |
2149 | cctx_max_idle = max_idle; |
2203 | cctx_max_idle = max_idle; |
2150 | OUTPUT: |
2204 | OUTPUT: |
2151 | RETVAL |
2205 | RETVAL |
2152 | |
2206 | |
2153 | int |
2207 | int |
2154 | cctx_count () |
2208 | cctx_count () |
|
|
2209 | PROTOTYPE: |
2155 | CODE: |
2210 | CODE: |
2156 | RETVAL = cctx_count; |
2211 | RETVAL = cctx_count; |
2157 | OUTPUT: |
2212 | OUTPUT: |
2158 | RETVAL |
2213 | RETVAL |
2159 | |
2214 | |
2160 | int |
2215 | int |
2161 | cctx_idle () |
2216 | cctx_idle () |
|
|
2217 | PROTOTYPE: |
2162 | CODE: |
2218 | CODE: |
2163 | RETVAL = cctx_idle; |
2219 | RETVAL = cctx_idle; |
2164 | OUTPUT: |
2220 | OUTPUT: |
2165 | RETVAL |
2221 | RETVAL |
2166 | |
2222 | |
2167 | void |
2223 | void |
2168 | list () |
2224 | list () |
|
|
2225 | PROTOTYPE: |
2169 | PPCODE: |
2226 | PPCODE: |
2170 | { |
2227 | { |
2171 | struct coro *coro; |
2228 | struct coro *coro; |
2172 | for (coro = coro_first; coro; coro = coro->next) |
2229 | for (coro = coro_first; coro; coro = coro->next) |
2173 | if (coro->hv) |
2230 | if (coro->hv) |
… | |
… | |
2240 | SvREFCNT_dec (self->throw); |
2297 | SvREFCNT_dec (self->throw); |
2241 | self->throw = SvOK (throw) ? newSVsv (throw) : 0; |
2298 | self->throw = SvOK (throw) ? newSVsv (throw) : 0; |
2242 | |
2299 | |
2243 | void |
2300 | void |
2244 | api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) |
2301 | api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) |
|
|
2302 | PROTOTYPE: $;$ |
2245 | C_ARGS: aTHX_ coro, flags |
2303 | C_ARGS: aTHX_ coro, flags |
2246 | |
2304 | |
2247 | SV * |
2305 | SV * |
2248 | has_cctx (Coro::State coro) |
2306 | has_cctx (Coro::State coro) |
2249 | PROTOTYPE: $ |
2307 | PROTOTYPE: $ |
… | |
… | |
2274 | OUTPUT: |
2332 | OUTPUT: |
2275 | RETVAL |
2333 | RETVAL |
2276 | |
2334 | |
2277 | void |
2335 | void |
2278 | force_cctx () |
2336 | force_cctx () |
|
|
2337 | PROTOTYPE: |
2279 | CODE: |
2338 | CODE: |
2280 | struct coro *coro = SvSTATE (coro_current); |
2339 | struct coro *coro = SvSTATE (coro_current); |
2281 | coro->cctx->idle_sp = 0; |
2340 | coro->cctx->idle_sp = 0; |
2282 | |
2341 | |
2283 | void |
2342 | void |
… | |
… | |
2339 | } |
2398 | } |
2340 | |
2399 | |
2341 | void |
2400 | void |
2342 | schedule (...) |
2401 | schedule (...) |
2343 | CODE: |
2402 | CODE: |
2344 | api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), items); |
2403 | api_execute_slf (aTHX_ cv, slf_init_schedule, &ST (0), 0); |
2345 | |
2404 | |
2346 | void |
2405 | void |
2347 | cede (...) |
2406 | cede (...) |
2348 | CODE: |
2407 | CODE: |
2349 | api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), items); |
2408 | api_execute_slf (aTHX_ cv, slf_init_cede, &ST (0), 0); |
2350 | |
2409 | |
2351 | void |
2410 | void |
2352 | cede_notself (...) |
2411 | cede_notself (...) |
2353 | CODE: |
2412 | CODE: |
2354 | api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), items); |
2413 | api_execute_slf (aTHX_ cv, slf_init_cede_notself, &ST (0), 0); |
2355 | |
2414 | |
2356 | void |
2415 | void |
2357 | _set_current (SV *current) |
2416 | _set_current (SV *current) |
2358 | PROTOTYPE: $ |
2417 | PROTOTYPE: $ |
2359 | CODE: |
2418 | CODE: |
… | |
… | |
2369 | coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; |
2428 | coro_readyhook = SvOK (hook) ? newSVsv (hook) : 0; |
2370 | UNLOCK; |
2429 | UNLOCK; |
2371 | |
2430 | |
2372 | int |
2431 | int |
2373 | prio (Coro::State coro, int newprio = 0) |
2432 | prio (Coro::State coro, int newprio = 0) |
|
|
2433 | PROTOTYPE: $;$ |
2374 | ALIAS: |
2434 | ALIAS: |
2375 | nice = 1 |
2435 | nice = 1 |
2376 | CODE: |
2436 | CODE: |
2377 | { |
2437 | { |
2378 | RETVAL = coro->prio; |
2438 | RETVAL = coro->prio; |
… | |
… | |
2442 | { |
2502 | { |
2443 | av_fill (defav, len - 1); |
2503 | av_fill (defav, len - 1); |
2444 | for (i = 0; i < len; ++i) |
2504 | for (i = 0; i < len; ++i) |
2445 | av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1])); |
2505 | av_store (defav, i, SvREFCNT_inc_NN (AvARRAY (invoke_av)[i + 1])); |
2446 | } |
2506 | } |
2447 | |
|
|
2448 | SvREFCNT_dec (invoke); |
|
|
2449 | } |
2507 | } |
2450 | |
2508 | |
2451 | void |
2509 | void |
2452 | _pool_2 (SV *cb) |
2510 | _pool_2 (SV *cb) |
2453 | CODE: |
2511 | CODE: |
… | |
… | |
2531 | |
2589 | |
2532 | MODULE = Coro::State PACKAGE = Coro::AIO |
2590 | MODULE = Coro::State PACKAGE = Coro::AIO |
2533 | |
2591 | |
2534 | void |
2592 | void |
2535 | _get_state (SV *self) |
2593 | _get_state (SV *self) |
|
|
2594 | PROTOTYPE: $ |
2536 | PPCODE: |
2595 | PPCODE: |
2537 | { |
2596 | { |
2538 | AV *defav = GvAV (PL_defgv); |
2597 | AV *defav = GvAV (PL_defgv); |
2539 | AV *av = newAV (); |
2598 | AV *av = newAV (); |
2540 | int i; |
2599 | int i; |
… | |
… | |
2585 | BOOT: |
2644 | BOOT: |
2586 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2645 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2587 | |
2646 | |
2588 | SV * |
2647 | SV * |
2589 | _schedule (...) |
2648 | _schedule (...) |
2590 | PROTOTYPE: @ |
|
|
2591 | CODE: |
2649 | CODE: |
2592 | { |
2650 | { |
2593 | static int incede; |
2651 | static int incede; |
2594 | |
2652 | |
2595 | api_cede_notself (aTHX); |
2653 | api_cede_notself (aTHX); |
… | |
… | |
2614 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2672 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2615 | |
2673 | |
2616 | BOOT: |
2674 | BOOT: |
2617 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2675 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2618 | |
2676 | |
|
|
2677 | MODULE = Coro::State PACKAGE = Coro::Semaphore |
|
|
2678 | |
|
|
2679 | SV * |
|
|
2680 | new (SV *klass, SV *count_ = 0) |
|
|
2681 | CODE: |
|
|
2682 | { |
|
|
2683 | /* a semaphore contains a counter IV in $sem->[0] and any waiters after that */ |
|
|
2684 | AV *av = newAV (); |
|
|
2685 | av_push (av, newSViv (count_ && SvOK (count_) ? SvIV (count_) : 1)); |
|
|
2686 | RETVAL = sv_bless (newRV_noinc ((SV *)av), GvSTASH (CvGV (cv))); |
|
|
2687 | } |
|
|
2688 | OUTPUT: |
|
|
2689 | RETVAL |
|
|
2690 | |
|
|
2691 | SV * |
|
|
2692 | count (SV *self) |
|
|
2693 | CODE: |
|
|
2694 | RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]); |
|
|
2695 | OUTPUT: |
|
|
2696 | RETVAL |
|
|
2697 | |
|
|
2698 | void |
|
|
2699 | up (SV *self, int adjust = 1) |
|
|
2700 | ALIAS: |
|
|
2701 | adjust = 1 |
|
|
2702 | CODE: |
|
|
2703 | { |
|
|
2704 | AV *av = (AV *)SvRV (self); |
|
|
2705 | SV *count_sv = AvARRAY (av)[0]; |
|
|
2706 | IV count = SvIVX (count_sv); |
|
|
2707 | |
|
|
2708 | count += ix ? adjust : 1; |
|
|
2709 | SvIVX (count_sv) = count; |
|
|
2710 | |
|
|
2711 | /* now wake up as many waiters as possible */ |
|
|
2712 | while (count > 0 && AvFILLp (av) >= count) |
|
|
2713 | { |
|
|
2714 | SV *cb; |
|
|
2715 | |
|
|
2716 | /* swap first two elements so we can shift a waiter */ |
|
|
2717 | AvARRAY (av)[0] = AvARRAY (av)[1]; |
|
|
2718 | AvARRAY (av)[1] = count_sv; |
|
|
2719 | cb = av_shift (av); |
|
|
2720 | |
|
|
2721 | if (SvOBJECT (cb)) |
|
|
2722 | api_ready (cb); |
|
|
2723 | else |
|
|
2724 | croak ("callbacks not yet supported"); |
|
|
2725 | |
|
|
2726 | SvREFCNT_dec (cb); |
|
|
2727 | } |
|
|
2728 | } |
|
|
2729 | |
|
|
2730 | void |
|
|
2731 | down (SV *self) |
|
|
2732 | CODE: |
|
|
2733 | api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), 1); |
|
|
2734 | |
|
|
2735 | void |
|
|
2736 | try (SV *self) |
|
|
2737 | PPCODE: |
|
|
2738 | { |
|
|
2739 | AV *av = (AV *)SvRV (self); |
|
|
2740 | SV *count_sv = AvARRAY (av)[0]; |
|
|
2741 | IV count = SvIVX (count_sv); |
|
|
2742 | |
|
|
2743 | if (count > 0) |
|
|
2744 | { |
|
|
2745 | --count; |
|
|
2746 | SvIVX (count_sv) = count; |
|
|
2747 | XSRETURN_YES; |
|
|
2748 | } |
|
|
2749 | else |
|
|
2750 | XSRETURN_NO; |
|
|
2751 | } |
|
|
2752 | |
|
|
2753 | void |
|
|
2754 | waiters (SV *self) |
|
|
2755 | CODE: |
|
|
2756 | { |
|
|
2757 | AV *av = (AV *)SvRV (self); |
|
|
2758 | |
|
|
2759 | if (GIMME_V == G_SCALAR) |
|
|
2760 | XPUSHs (sv_2mortal (newSVsv (AvARRAY (av)[0]))); |
|
|
2761 | else |
|
|
2762 | { |
|
|
2763 | int i; |
|
|
2764 | EXTEND (SP, AvFILLp (av) + 1 - 1); |
|
|
2765 | for (i = 1; i <= AvFILLp (av); ++i) |
|
|
2766 | PUSHs (newSVsv (AvARRAY (av)[i])); |
|
|
2767 | } |
|
|
2768 | } |
|
|
2769 | |