… | |
… | |
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 | |
815 | static void |
815 | static void |
816 | prepare_nop (aTHX_ struct coro_transfer_args *ta) |
816 | prepare_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 | |
822 | static int |
822 | static int |
823 | slf_check_nop (aTHX) |
823 | slf_check_nop (pTHX_ struct CoroSLF *frame) |
824 | { |
824 | { |
825 | return 0; |
825 | return 0; |
826 | } |
826 | } |
827 | |
827 | |
828 | static void |
828 | static 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 |
|
|
1726 | static int |
|
|
1727 | coro_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 | |
|
|
1737 | static 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 | |
1746 | typedef struct |
1728 | typedef struct |
… | |
… | |
1862 | static void |
1844 | static void |
1863 | slf_prepare_transfer (pTHX_ struct coro_transfer_args *ta) |
1845 | slf_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 | |
1870 | static void |
1852 | static void |
1871 | slf_init_transfer (pTHX_ struct CoroSLF *frame, SV **arg, int items) |
1853 | slf_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 | |
|
|
2002 | static int |
|
|
2003 | slf_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 | |
|
|
2029 | static void |
|
|
2030 | slf_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 */ |
|
|
2058 | static SV * |
|
|
2059 | gensub (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 | |
2018 | MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ |
2075 | MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ |
2019 | |
2076 | |
2020 | PROTOTYPES: DISABLE |
2077 | PROTOTYPES: DISABLE |
2021 | |
2078 | |
2022 | BOOT: |
2079 | BOOT: |
… | |
… | |
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 | |
2114 | void |
2171 | void |
2115 | transfer (...) |
2172 | transfer (...) |
|
|
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 | |
2119 | bool |
2177 | bool |
2120 | _destroy (SV *coro_sv) |
2178 | _destroy (SV *coro_sv) |
… | |
… | |
2129 | CODE: |
2187 | CODE: |
2130 | _exit (code); |
2188 | _exit (code); |
2131 | |
2189 | |
2132 | int |
2190 | int |
2133 | cctx_stacksize (int new_stacksize = 0) |
2191 | cctx_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 | |
2144 | int |
2203 | int |
2145 | cctx_max_idle (int max_idle = 0) |
2204 | cctx_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 | |
2153 | int |
2213 | int |
2154 | cctx_count () |
2214 | cctx_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 | |
2160 | int |
2221 | int |
2161 | cctx_idle () |
2222 | cctx_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 | |
2167 | void |
2229 | void |
2168 | list () |
2230 | list () |
|
|
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 | |
2243 | void |
2306 | void |
2244 | api_trace (SV *coro, int flags = CC_TRACE | CC_TRACE_SUB) |
2307 | api_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 | |
2247 | SV * |
2311 | SV * |
2248 | has_cctx (Coro::State coro) |
2312 | has_cctx (Coro::State coro) |
2249 | PROTOTYPE: $ |
2313 | PROTOTYPE: $ |
… | |
… | |
2274 | OUTPUT: |
2338 | OUTPUT: |
2275 | RETVAL |
2339 | RETVAL |
2276 | |
2340 | |
2277 | void |
2341 | void |
2278 | force_cctx () |
2342 | force_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 | |
2283 | void |
2348 | void |
… | |
… | |
2339 | } |
2404 | } |
2340 | |
2405 | |
2341 | void |
2406 | void |
2342 | schedule (...) |
2407 | schedule (...) |
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 | |
2346 | void |
2411 | void |
2347 | cede (...) |
2412 | cede (...) |
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 | |
2351 | void |
2416 | void |
2352 | cede_notself (...) |
2417 | cede_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 | |
2356 | void |
2421 | void |
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 | |
2372 | int |
2437 | int |
2373 | prio (Coro::State coro, int newprio = 0) |
2438 | prio (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 | |
2451 | void |
2515 | void |
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 | |
|
|
2485 | void |
|
|
2486 | _generator_call (...) |
|
|
2487 | PROTOTYPE: @ |
|
|
2488 | PPCODE: |
|
|
2489 | fprintf (stderr, "call %p\n", CvXSUBANY(cv).any_ptr); |
|
|
2490 | xxxx |
|
|
2491 | abort (); |
|
|
2492 | |
|
|
2493 | SV * |
|
|
2494 | gensub (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 | |
2532 | MODULE = Coro::State PACKAGE = Coro::AIO |
2548 | MODULE = Coro::State PACKAGE = Coro::AIO |
2533 | |
2549 | |
2534 | void |
2550 | void |
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; |
… | |
… | |
2583 | MODULE = Coro::State PACKAGE = Coro::AnyEvent |
2600 | MODULE = Coro::State PACKAGE = Coro::AnyEvent |
2584 | |
2601 | |
2585 | BOOT: |
2602 | BOOT: |
2586 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2603 | sv_activity = coro_get_sv (aTHX_ "Coro::AnyEvent::ACTIVITY", TRUE); |
2587 | |
2604 | |
2588 | SV * |
2605 | void |
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); |
… | |
… | |
2614 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2630 | MODULE = Coro::State PACKAGE = PerlIO::cede |
2615 | |
2631 | |
2616 | BOOT: |
2632 | BOOT: |
2617 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2633 | PerlIO_define_layer (aTHX_ &PerlIO_cede); |
2618 | |
2634 | |
|
|
2635 | MODULE = Coro::State PACKAGE = Coro::Semaphore |
|
|
2636 | |
|
|
2637 | SV * |
|
|
2638 | new (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 | |
|
|
2649 | SV * |
|
|
2650 | count (SV *self) |
|
|
2651 | CODE: |
|
|
2652 | RETVAL = newSVsv (AvARRAY ((AV *)SvRV (self))[0]); |
|
|
2653 | OUTPUT: |
|
|
2654 | RETVAL |
|
|
2655 | |
|
|
2656 | void |
|
|
2657 | up (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 | |
|
|
2688 | void |
|
|
2689 | down (SV *self) |
|
|
2690 | CODE: |
|
|
2691 | api_execute_slf (aTHX_ cv, slf_init_semaphore_down, &ST (0), 1); |
|
|
2692 | |
|
|
2693 | void |
|
|
2694 | try (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 | |
|
|
2711 | void |
|
|
2712 | waiters (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 | |