… | |
… | |
223 | #define VAR(name,type) type name; |
223 | #define VAR(name,type) type name; |
224 | # include "state.h" |
224 | # include "state.h" |
225 | #undef VAR |
225 | #undef VAR |
226 | } perl_slots; |
226 | } perl_slots; |
227 | |
227 | |
|
|
228 | // how many context stack entries do we need for perl_slots |
228 | #define SLOT_COUNT ((sizeof (perl_slots) + sizeof (PERL_CONTEXT) - 1) / sizeof (PERL_CONTEXT)) |
229 | #define SLOT_COUNT ((sizeof (perl_slots) + sizeof (PERL_CONTEXT) - 1) / sizeof (PERL_CONTEXT)) |
229 | |
230 | |
230 | /* this is a structure representing a perl-level coroutine */ |
231 | /* this is a structure representing a perl-level coroutine */ |
231 | struct coro { |
232 | struct coro { |
232 | /* the C coroutine allocated to this perl coroutine, if any */ |
233 | /* the C coroutine allocated to this perl coroutine, if any */ |
… | |
… | |
798 | |
799 | |
799 | PUTBACK; |
800 | PUTBACK; |
800 | } |
801 | } |
801 | |
802 | |
802 | /* allocate some space on the context stack for our purposes */ |
803 | /* allocate some space on the context stack for our purposes */ |
803 | /* we manually unroll here, as usually 2 slots is enough */ |
804 | if (expect_false (cxstack_ix + SLOT_COUNT >= cxstack_max)) |
804 | if (SLOT_COUNT >= 1) CXINC; |
|
|
805 | if (SLOT_COUNT >= 2) CXINC; |
|
|
806 | if (SLOT_COUNT >= 3) CXINC; |
|
|
807 | { |
805 | { |
808 | unsigned int i; |
806 | unsigned int i; |
|
|
807 | |
809 | for (i = 3; i < SLOT_COUNT; ++i) |
808 | for (i = 0; i < SLOT_COUNT; ++i) |
810 | CXINC; |
809 | CXINC; |
811 | } |
810 | |
812 | cxstack_ix -= SLOT_COUNT; /* undo allocation */ |
811 | cxstack_ix -= SLOT_COUNT; /* undo allocation */ |
|
|
812 | } |
813 | |
813 | |
814 | c->mainstack = PL_mainstack; |
814 | c->mainstack = PL_mainstack; |
815 | |
815 | |
816 | { |
816 | { |
817 | perl_slots *slot = c->slot = (perl_slots *)(cxstack + cxstack_ix + 1); |
817 | perl_slots *slot = c->slot = (perl_slots *)(cxstack + cxstack_ix + 1); |
… | |
… | |
838 | # define coro_init_stacks(thx) init_stacks () |
838 | # define coro_init_stacks(thx) init_stacks () |
839 | #else |
839 | #else |
840 | static void |
840 | static void |
841 | coro_init_stacks (pTHX) |
841 | coro_init_stacks (pTHX) |
842 | { |
842 | { |
843 | PL_curstackinfo = new_stackinfo(32, 8); |
843 | PL_curstackinfo = new_stackinfo(32, 4 + SLOT_COUNT); /* 3 is minimum due to perl rounding down in scope.c:GROW() */ |
844 | PL_curstackinfo->si_type = PERLSI_MAIN; |
844 | PL_curstackinfo->si_type = PERLSI_MAIN; |
845 | PL_curstack = PL_curstackinfo->si_stack; |
845 | PL_curstack = PL_curstackinfo->si_stack; |
846 | PL_mainstack = PL_curstack; /* remember in case we switch stacks */ |
846 | PL_mainstack = PL_curstack; /* remember in case we switch stacks */ |
847 | |
847 | |
848 | PL_stack_base = AvARRAY(PL_curstack); |
848 | PL_stack_base = AvARRAY(PL_curstack); |
… | |
… | |
2043 | } |
2043 | } |
2044 | } |
2044 | } |
2045 | } |
2045 | } |
2046 | |
2046 | |
2047 | static void |
2047 | static void |
2048 | coro_set_status (HV *coro_hv, SV **arg, int items) |
2048 | coro_set_status (pTHX_ HV *coro_hv, SV **arg, int items) |
2049 | { |
2049 | { |
2050 | AV *av = newAV (); |
2050 | AV *av = newAV (); |
2051 | |
2051 | |
2052 | /* items are actually not so common, so optimise for this case */ |
2052 | /* items are actually not so common, so optimise for this case */ |
2053 | if (items) |
2053 | if (items) |
… | |
… | |
2080 | static void |
2080 | static void |
2081 | slf_init_terminate (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
2081 | slf_init_terminate (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
2082 | { |
2082 | { |
2083 | HV *coro_hv = (HV *)SvRV (coro_current); |
2083 | HV *coro_hv = (HV *)SvRV (coro_current); |
2084 | |
2084 | |
2085 | coro_set_status (coro_hv, arg, items); |
2085 | coro_set_status (aTHX_ coro_hv, arg, items); |
2086 | slf_init_terminate_cancel_common (frame, coro_hv); |
2086 | slf_init_terminate_cancel_common (aTHX_ frame, coro_hv); |
2087 | } |
2087 | } |
2088 | |
2088 | |
2089 | static void |
2089 | static void |
2090 | slf_init_cancel (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
2090 | slf_init_cancel (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) |
2091 | { |
2091 | { |
… | |
… | |
2096 | croak ("Coro::cancel called without coro object,"); |
2096 | croak ("Coro::cancel called without coro object,"); |
2097 | |
2097 | |
2098 | coro = SvSTATE (arg [0]); |
2098 | coro = SvSTATE (arg [0]); |
2099 | coro_hv = coro->hv; |
2099 | coro_hv = coro->hv; |
2100 | |
2100 | |
2101 | coro_set_status (coro_hv, arg + 1, items - 1); |
2101 | coro_set_status (aTHX_ coro_hv, arg + 1, items - 1); |
2102 | |
2102 | |
2103 | if (expect_false (coro->flags & CF_NOCANCEL)) |
2103 | if (expect_false (coro->flags & CF_NOCANCEL)) |
2104 | { |
2104 | { |
2105 | /* coro currently busy cancelling something, so just notify it */ |
2105 | /* coro currently busy cancelling something, so just notify it */ |
2106 | coro->slf_frame.data = (void *)coro; |
2106 | coro->slf_frame.data = (void *)coro; |
… | |
… | |
2109 | frame->check = slf_check_nop; |
2109 | frame->check = slf_check_nop; |
2110 | } |
2110 | } |
2111 | else if (coro_hv == (HV *)SvRV (coro_current)) |
2111 | else if (coro_hv == (HV *)SvRV (coro_current)) |
2112 | { |
2112 | { |
2113 | /* cancelling the current coro is allowed, and equals terminate */ |
2113 | /* cancelling the current coro is allowed, and equals terminate */ |
2114 | slf_init_terminate_cancel_common (frame, coro_hv); |
2114 | slf_init_terminate_cancel_common (aTHX_ frame, coro_hv); |
2115 | } |
2115 | } |
2116 | else |
2116 | else |
2117 | { |
2117 | { |
2118 | struct coro *self = SvSTATE_current; |
2118 | struct coro *self = SvSTATE_current; |
2119 | |
2119 | |
… | |
… | |
2132 | self->flags &= ~CF_NOCANCEL; |
2132 | self->flags &= ~CF_NOCANCEL; |
2133 | |
2133 | |
2134 | if (slf_frame.data) |
2134 | if (slf_frame.data) |
2135 | { |
2135 | { |
2136 | /* while we were busy we have been cancelled, so terminate */ |
2136 | /* while we were busy we have been cancelled, so terminate */ |
2137 | slf_init_terminate_cancel_common (frame, self->hv); |
2137 | slf_init_terminate_cancel_common (aTHX_ frame, self->hv); |
2138 | } |
2138 | } |
2139 | else |
2139 | else |
2140 | { |
2140 | { |
2141 | frame->prepare = prepare_nop; |
2141 | frame->prepare = prepare_nop; |
2142 | frame->check = slf_check_nop; |
2142 | frame->check = slf_check_nop; |
… | |
… | |
2146 | |
2146 | |
2147 | static int |
2147 | static int |
2148 | slf_check_safe_cancel (pTHX_ struct CoroSLF *frame) |
2148 | slf_check_safe_cancel (pTHX_ struct CoroSLF *frame) |
2149 | { |
2149 | { |
2150 | frame->prepare = 0; |
2150 | frame->prepare = 0; |
2151 | coro_unwind_stacks (); |
2151 | coro_unwind_stacks (aTHX); |
2152 | |
2152 | |
2153 | slf_init_terminate_cancel_common (aTHX_ frame, (HV *)SvRV (coro_current)); |
2153 | slf_init_terminate_cancel_common (aTHX_ frame, (HV *)SvRV (coro_current)); |
2154 | |
2154 | |
2155 | return 1; |
2155 | return 1; |
2156 | } |
2156 | } |
… | |
… | |
2161 | if (coro->cctx) |
2161 | if (coro->cctx) |
2162 | croak ("coro inside C callback, unable to cancel at this time, caught"); |
2162 | croak ("coro inside C callback, unable to cancel at this time, caught"); |
2163 | |
2163 | |
2164 | if (coro->flags & CF_NEW) |
2164 | if (coro->flags & CF_NEW) |
2165 | { |
2165 | { |
2166 | coro_set_status (coro->hv, arg, items); |
2166 | coro_set_status (aTHX_ coro->hv, arg, items); |
2167 | coro_state_destroy (aTHX_ coro); |
2167 | coro_state_destroy (aTHX_ coro); |
2168 | coro_call_on_destroy (aTHX_ coro); |
2168 | coro_call_on_destroy (aTHX_ coro); |
2169 | } |
2169 | } |
2170 | else |
2170 | else |
2171 | { |
2171 | { |
2172 | if (!coro->slf_frame.prepare) |
2172 | if (!coro->slf_frame.prepare) |
2173 | croak ("coro outside an SLF function, unable to cancel at this time, caught"); |
2173 | croak ("coro outside an SLF function, unable to cancel at this time, caught"); |
2174 | |
2174 | |
2175 | slf_destroy (coro); |
2175 | slf_destroy (aTHX_ coro); |
2176 | |
2176 | |
2177 | coro_set_status (coro->hv, arg, items); |
2177 | coro_set_status (aTHX_ coro->hv, arg, items); |
2178 | coro->slf_frame.prepare = prepare_nop; |
2178 | coro->slf_frame.prepare = prepare_nop; |
2179 | coro->slf_frame.check = slf_check_safe_cancel; |
2179 | coro->slf_frame.check = slf_check_safe_cancel; |
2180 | |
2180 | |
2181 | api_ready (aTHX_ coro->hv); |
2181 | api_ready (aTHX_ coro->hv); |
2182 | } |
2182 | } |