ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
(Generate patch)

Comparing Coro/Coro/State.xs (file contents):
Revision 1.397 by root, Fri May 6 21:15:17 2011 UTC vs.
Revision 1.398 by root, Sat May 7 14:11:10 2011 UTC

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 */
231struct coro { 232struct 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
840static void 840static void
841coro_init_stacks (pTHX) 841coro_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
2047static void 2047static void
2048coro_set_status (HV *coro_hv, SV **arg, int items) 2048coro_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)
2080static void 2080static void
2081slf_init_terminate (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2081slf_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
2089static void 2089static void
2090slf_init_cancel (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2090slf_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
2147static int 2147static int
2148slf_check_safe_cancel (pTHX_ struct CoroSLF *frame) 2148slf_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 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines