… | |
… | |
145 | #define expect_true(expr) expect ((expr) != 0, 1) |
145 | #define expect_true(expr) expect ((expr) != 0, 1) |
146 | |
146 | |
147 | #define NOINLINE attribute ((noinline)) |
147 | #define NOINLINE attribute ((noinline)) |
148 | |
148 | |
149 | #include "CoroAPI.h" |
149 | #include "CoroAPI.h" |
|
|
150 | #define GCoroAPI (&coroapi) /* very sneaky */ |
150 | |
151 | |
151 | #ifdef USE_ITHREADS |
152 | #ifdef USE_ITHREADS |
152 | # if CORO_PTHREAD |
153 | # if CORO_PTHREAD |
153 | static void *coro_thx; |
154 | static void *coro_thx; |
154 | # endif |
155 | # endif |
… | |
… | |
256 | /* statistics */ |
257 | /* statistics */ |
257 | int usecount; /* number of transfers to this coro */ |
258 | int usecount; /* number of transfers to this coro */ |
258 | |
259 | |
259 | /* coro process data */ |
260 | /* coro process data */ |
260 | int prio; |
261 | int prio; |
261 | SV *throw; /* exception to be thrown */ |
262 | SV *except; /* exception to be thrown */ |
262 | |
263 | |
263 | /* async_pool */ |
264 | /* async_pool */ |
264 | SV *saved_deffh; |
265 | SV *saved_deffh; |
265 | |
266 | |
266 | /* linked list */ |
267 | /* linked list */ |
… | |
… | |
272 | |
273 | |
273 | /* the following variables are effectively part of the perl context */ |
274 | /* the following variables are effectively part of the perl context */ |
274 | /* and get copied between struct coro and these variables */ |
275 | /* and get copied between struct coro and these variables */ |
275 | /* the mainr easonw e don't support windows process emulation */ |
276 | /* the mainr easonw e don't support windows process emulation */ |
276 | static struct CoroSLF slf_frame; /* the current slf frame */ |
277 | static struct CoroSLF slf_frame; /* the current slf frame */ |
277 | static SV *coro_throw; |
|
|
278 | |
278 | |
279 | /** Coro ********************************************************************/ |
279 | /** Coro ********************************************************************/ |
280 | |
280 | |
281 | #define PRIO_MAX 3 |
281 | #define PRIO_MAX 3 |
282 | #define PRIO_HIGH 1 |
282 | #define PRIO_HIGH 1 |
… | |
… | |
511 | |
511 | |
512 | PUTBACK; |
512 | PUTBACK; |
513 | } |
513 | } |
514 | |
514 | |
515 | slf_frame = c->slf_frame; |
515 | slf_frame = c->slf_frame; |
516 | coro_throw = c->throw; |
516 | CORO_THROW = c->except; |
517 | } |
517 | } |
518 | |
518 | |
519 | static void |
519 | static void |
520 | save_perl (pTHX_ Coro__State c) |
520 | save_perl (pTHX_ Coro__State c) |
521 | { |
521 | { |
522 | c->throw = coro_throw; |
522 | c->except = CORO_THROW; |
523 | c->slf_frame = slf_frame; |
523 | c->slf_frame = slf_frame; |
524 | |
524 | |
525 | { |
525 | { |
526 | dSP; |
526 | dSP; |
527 | I32 cxix = cxstack_ix; |
527 | I32 cxix = cxstack_ix; |
… | |
… | |
885 | /* no flags required, as an init function won't be called */ |
885 | /* no flags required, as an init function won't be called */ |
886 | |
886 | |
887 | PL_op = (OP *)&coro_setup_op; |
887 | PL_op = (OP *)&coro_setup_op; |
888 | |
888 | |
889 | /* copy throw, in case it was set before coro_setup */ |
889 | /* copy throw, in case it was set before coro_setup */ |
890 | coro_throw = coro->throw; |
890 | CORO_THROW = coro->except; |
891 | } |
891 | } |
892 | |
892 | |
893 | static void |
893 | static void |
894 | coro_destruct (pTHX_ struct coro *coro) |
894 | coro_destruct (pTHX_ struct coro *coro) |
895 | { |
895 | { |
… | |
… | |
919 | |
919 | |
920 | SvREFCNT_dec (PL_diehook); |
920 | SvREFCNT_dec (PL_diehook); |
921 | SvREFCNT_dec (PL_warnhook); |
921 | SvREFCNT_dec (PL_warnhook); |
922 | |
922 | |
923 | SvREFCNT_dec (coro->saved_deffh); |
923 | SvREFCNT_dec (coro->saved_deffh); |
924 | SvREFCNT_dec (coro_throw); |
924 | SvREFCNT_dec (CORO_THROW); |
925 | |
925 | |
926 | coro_destruct_stacks (aTHX); |
926 | coro_destruct_stacks (aTHX); |
927 | } |
927 | } |
928 | |
928 | |
929 | INLINE void |
929 | INLINE void |
… | |
… | |
1840 | while (slf_frame.check (aTHX_ &slf_frame)); |
1840 | while (slf_frame.check (aTHX_ &slf_frame)); |
1841 | |
1841 | |
1842 | slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */ |
1842 | slf_frame.prepare = 0; /* invalidate the frame, we are done processing it */ |
1843 | |
1843 | |
1844 | /* exception handling */ |
1844 | /* exception handling */ |
1845 | if (expect_false (coro_throw)) |
1845 | if (expect_false (CORO_THROW)) |
1846 | { |
1846 | { |
1847 | SV *exception = sv_2mortal (coro_throw); |
1847 | SV *exception = sv_2mortal (CORO_THROW); |
1848 | |
1848 | |
1849 | coro_throw = 0; |
1849 | CORO_THROW = 0; |
1850 | sv_setsv (ERRSV, exception); |
1850 | sv_setsv (ERRSV, exception); |
1851 | croak (0); |
1851 | croak (0); |
1852 | } |
1852 | } |
1853 | |
1853 | |
1854 | /* return value handling - mostly like entersub */ |
1854 | /* return value handling - mostly like entersub */ |
… | |
… | |
2041 | { |
2041 | { |
2042 | AV *av = (AV *)frame->data; |
2042 | AV *av = (AV *)frame->data; |
2043 | SV *count_sv = AvARRAY (av)[0]; |
2043 | SV *count_sv = AvARRAY (av)[0]; |
2044 | |
2044 | |
2045 | /* if we are about to throw, don't actually acquire the lock, just throw */ |
2045 | /* if we are about to throw, don't actually acquire the lock, just throw */ |
2046 | if (coro_throw) |
2046 | if (CORO_THROW) |
2047 | return 0; |
2047 | return 0; |
2048 | else if (SvIVX (count_sv) > 0) |
2048 | else if (SvIVX (count_sv) > 0) |
2049 | { |
2049 | { |
2050 | SvSTATE_current->on_destroy = 0; |
2050 | SvSTATE_current->on_destroy = 0; |
2051 | SvIVX (count_sv) = SvIVX (count_sv) - 1; |
2051 | SvIVX (count_sv) = SvIVX (count_sv) - 1; |
… | |
… | |
2174 | AV *state = (AV *)frame->data; |
2174 | AV *state = (AV *)frame->data; |
2175 | |
2175 | |
2176 | /* if we are about to throw, return early */ |
2176 | /* if we are about to throw, return early */ |
2177 | /* this does not cancel the aio request, but at least */ |
2177 | /* this does not cancel the aio request, but at least */ |
2178 | /* it quickly returns */ |
2178 | /* it quickly returns */ |
2179 | if (coro_throw) |
2179 | if (CORO_THROW) |
2180 | return 0; |
2180 | return 0; |
2181 | |
2181 | |
2182 | /* one element that is an RV? repeat! */ |
2182 | /* one element that is an RV? repeat! */ |
2183 | if (AvFILLp (state) == 0 && SvROK (AvARRAY (state)[0])) |
2183 | if (AvFILLp (state) == 0 && SvROK (AvARRAY (state)[0])) |
2184 | return 1; |
2184 | return 1; |
… | |
… | |
2517 | throw (Coro::State self, SV *throw = &PL_sv_undef) |
2517 | throw (Coro::State self, SV *throw = &PL_sv_undef) |
2518 | PROTOTYPE: $;$ |
2518 | PROTOTYPE: $;$ |
2519 | CODE: |
2519 | CODE: |
2520 | { |
2520 | { |
2521 | struct coro *current = SvSTATE_current; |
2521 | struct coro *current = SvSTATE_current; |
2522 | SV **throwp = self == current ? &coro_throw : &self->throw; |
2522 | SV **throwp = self == current ? &CORO_THROW : &self->except; |
2523 | SvREFCNT_dec (*throwp); |
2523 | SvREFCNT_dec (*throwp); |
2524 | *throwp = SvOK (throw) ? newSVsv (throw) : 0; |
2524 | *throwp = SvOK (throw) ? newSVsv (throw) : 0; |
2525 | } |
2525 | } |
2526 | |
2526 | |
2527 | void |
2527 | void |
… | |
… | |
2616 | coroapi.ready = api_ready; |
2616 | coroapi.ready = api_ready; |
2617 | coroapi.is_ready = api_is_ready; |
2617 | coroapi.is_ready = api_is_ready; |
2618 | coroapi.nready = coro_nready; |
2618 | coroapi.nready = coro_nready; |
2619 | coroapi.current = coro_current; |
2619 | coroapi.current = coro_current; |
2620 | |
2620 | |
2621 | GCoroAPI = &coroapi; |
2621 | /*GCoroAPI = &coroapi;*/ |
2622 | sv_setiv (sv, (IV)&coroapi); |
2622 | sv_setiv (sv, (IV)&coroapi); |
2623 | SvREADONLY_on (sv); |
2623 | SvREADONLY_on (sv); |
2624 | } |
2624 | } |
2625 | } |
2625 | } |
2626 | |
2626 | |