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.4 by root, Tue Jul 17 02:21:56 2001 UTC vs.
Revision 1.11 by root, Sat Jul 21 18:21:45 2001 UTC

1#include "EXTERN.h" 1#include "EXTERN.h"
2#include "perl.h" 2#include "perl.h"
3#include "XSUB.h" 3#include "XSUB.h"
4 4
5#if 0 5#if 1
6# define CHK(x) (void *)0 6# define CHK(x) (void *)0
7#else 7#else
8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x) 8# define CHK(x) if (!(x)) croak("FATAL, CHK: " #x)
9#endif 9#endif
10 10
11#define MAY_FLUSH /* increases codesize */
12
13#define SUB_INIT "Coro::State::initialize"
14
15#define SAVE_DEFAV 0x00000001
16#define SAVE_DEFSV 0x00000002
17#define SAVE_ERRSV 0x00000004
18
19#define SAVE_ALL -1
20
11struct coro { 21struct coro {
22 /* optionally saved, might be zero */
23 AV *defav;
24 SV *defsv;
25 SV *errsv;
26
27 /* saved global state not related to stacks */
12 U8 dowarn; 28 U8 dowarn;
13 AV *defav; 29
14 30 /* the stacks and related info (callchain etc..) */
15 PERL_SI *curstackinfo; 31 PERL_SI *curstackinfo;
16 AV *curstack; 32 AV *curstack;
17 AV *mainstack; 33 AV *mainstack;
18 SV **stack_sp; 34 SV **stack_sp;
19 OP *op; 35 OP *op;
36 OP **retstack; 52 OP **retstack;
37 I32 retstack_ix; 53 I32 retstack_ix;
38 I32 retstack_max; 54 I32 retstack_max;
39 COP *curcop; 55 COP *curcop;
40 56
57 /* data associated with this coroutine (initial args) */
41 AV *args; 58 AV *args;
42}; 59};
43 60
44typedef struct coro *Coro__State; 61typedef struct coro *Coro__State;
45typedef struct coro *Coro__State_or_hashref; 62typedef struct coro *Coro__State_or_hashref;
115 SvPADTMP_on (sv); 132 SvPADTMP_on (sv);
116 npad[ix] = sv; 133 npad[ix] = sv;
117 } 134 }
118 } 135 }
119 136
120#if 0 /* NONOTUNDERSTOOD */ 137#if 0 /* return -ENOTUNDERSTOOD */
121 /* Now that vars are all in place, clone nested closures. */ 138 /* Now that vars are all in place, clone nested closures. */
122 139
123 for (ix = fpad; ix > 0; ix--) { 140 for (ix = fpad; ix > 0; ix--) {
124 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv; 141 SV* namesv = (ix <= fname) ? pname[ix] : Nullsv;
125 if (namesv 142 if (namesv
138#endif 155#endif
139 156
140 return newpadlist; 157 return newpadlist;
141} 158}
142 159
160#ifdef MAY_FLUSH
143STATIC AV * 161STATIC AV *
144free_padlist (AV *padlist) 162free_padlist (AV *padlist)
145{ 163{
146 /* may be during global destruction */ 164 /* may be during global destruction */
147 if (SvREFCNT(padlist)) 165 if (SvREFCNT(padlist))
156 } 174 }
157 175
158 SvREFCNT_dec((SV*)padlist); 176 SvREFCNT_dec((SV*)padlist);
159 } 177 }
160} 178}
179#endif
161 180
162/* the next tow functions merely cache the padlists */ 181/* the next two functions merely cache the padlists */
163STATIC void 182STATIC void
164get_padlist (CV *cv) 183get_padlist (CV *cv)
165{ 184{
166 SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 0); 185 SV **he = hv_fetch (padlist_cache, (void *)&cv, sizeof (CV *), 0);
167 186
183 } 202 }
184 203
185 av_push ((AV *)*he, (SV *)CvPADLIST (cv)); 204 av_push ((AV *)*he, (SV *)CvPADLIST (cv));
186} 205}
187 206
207#ifdef MAY_FLUSH
208STATIC void
209flush_padlist_cache ()
210{
211 HV *hv = padlist_cache;
212 padlist_cache = newHV ();
213
214 if (hv_iterinit (hv))
215 {
216 HE *he;
217 AV *padlist;
218
219 while (!!(he = hv_iternext (hv)))
220 {
221 AV *av = (AV *)HeVAL(he);
222
223 /* casting is fun. */
224 while (&PL_sv_undef != (SV *)(padlist = (AV *)av_pop (av)))
225 free_padlist (padlist);
226 }
227 }
228
229 SvREFCNT_dec (hv);
230}
231#endif
232
233#define SB do {
234#define SE } while (0)
235
236#define LOAD(state) SB load_state(aTHX_ state); SPAGAIN; SE
237#define SAVE(state,flags) SB PUTBACK; save_state(aTHX_ state,flags); SE
238
239#define REPLACE_SV(sv,val) SB SvREFCNT_dec(sv); (sv) = (val); SE
240
188static void 241static void
189SAVE(pTHX_ Coro__State c) 242load_state(pTHX_ Coro__State c)
243{
244 PL_dowarn = c->dowarn;
245
246 PL_curstackinfo = c->curstackinfo;
247 PL_curstack = c->curstack;
248 PL_mainstack = c->mainstack;
249 PL_stack_sp = c->stack_sp;
250 PL_op = c->op;
251 PL_curpad = c->curpad;
252 PL_stack_base = c->stack_base;
253 PL_stack_max = c->stack_max;
254 PL_tmps_stack = c->tmps_stack;
255 PL_tmps_floor = c->tmps_floor;
256 PL_tmps_ix = c->tmps_ix;
257 PL_tmps_max = c->tmps_max;
258 PL_markstack = c->markstack;
259 PL_markstack_ptr = c->markstack_ptr;
260 PL_markstack_max = c->markstack_max;
261 PL_scopestack = c->scopestack;
262 PL_scopestack_ix = c->scopestack_ix;
263 PL_scopestack_max = c->scopestack_max;
264 PL_savestack = c->savestack;
265 PL_savestack_ix = c->savestack_ix;
266 PL_savestack_max = c->savestack_max;
267 PL_retstack = c->retstack;
268 PL_retstack_ix = c->retstack_ix;
269 PL_retstack_max = c->retstack_max;
270 PL_curcop = c->curcop;
271
272 if (c->defav) REPLACE_SV (GvAV (PL_defgv), c->defav);
273 if (c->defsv) REPLACE_SV (DEFSV , c->defsv);
274 if (c->errsv) REPLACE_SV (ERRSV , c->errsv);
275
276 {
277 dSP;
278 CV *cv;
279
280 /* now do the ugly restore mess */
281 while ((cv = (CV *)POPs))
282 {
283 AV *padlist = (AV *)POPs;
284
285 if (padlist)
286 {
287 put_padlist (cv); /* mark this padlist as available */
288 CvPADLIST(cv) = padlist;
289#ifdef USE_THREADS
290 /*CvOWNER(cv) = (struct perl_thread *)POPs;*/
291#endif
292 }
293
294 ++CvDEPTH(cv);
295 }
296
297 PUTBACK;
298 }
299}
300
301static void
302save_state(pTHX_ Coro__State c, int flags)
190{ 303{
191 { 304 {
192 dSP; 305 dSP;
193 I32 cxix = cxstack_ix; 306 I32 cxix = cxstack_ix;
307 PERL_CONTEXT *ccstk = cxstack;
194 PERL_SI *top_si = PL_curstackinfo; 308 PERL_SI *top_si = PL_curstackinfo;
195 PERL_CONTEXT *ccstk = cxstack;
196 309
197 /* 310 /*
198 * the worst thing you can imagine happens first - we have to save 311 * the worst thing you can imagine happens first - we have to save
199 * (and reinitialize) all cv's in the whole callchain :( 312 * (and reinitialize) all cv's in the whole callchain :(
200 */ 313 */
201 314
202 PUSHs (Nullsv); 315 PUSHs (Nullsv);
203 /* this loop was inspired by pp_caller */ 316 /* this loop was inspired by pp_caller */
204 for (;;) 317 for (;;)
205 { 318 {
206 while (cxix >= 0) 319 do
207 { 320 {
208 PERL_CONTEXT *cx = &ccstk[cxix--]; 321 PERL_CONTEXT *cx = &ccstk[cxix--];
209 322
210 if (CxTYPE(cx) == CXt_SUB) 323 if (CxTYPE(cx) == CXt_SUB)
211 { 324 {
212 CV *cv = cx->blk_sub.cv; 325 CV *cv = cx->blk_sub.cv;
213 if (CvDEPTH(cv)) 326 if (CvDEPTH(cv))
214 { 327 {
215#ifdef USE_THREADS 328#ifdef USE_THREADS
216 XPUSHs ((SV *)CvOWNER(cv)); 329 /*XPUSHs ((SV *)CvOWNER(cv));*/
330 /*CvOWNER(cv) = 0;*/
331 /*error must unlock this cv etc.. etc...*/
217#endif 332#endif
218 EXTEND (SP, 3); 333 EXTEND (SP, CvDEPTH(cv)*2);
334
335 while (--CvDEPTH(cv))
336 {
337 /* this tells the restore code to increment CvDEPTH */
338 PUSHs (Nullsv);
219 PUSHs ((SV *)CvDEPTH(cv)); 339 PUSHs ((SV *)cv);
340 }
341
220 PUSHs ((SV *)CvPADLIST(cv)); 342 PUSHs ((SV *)CvPADLIST(cv));
221 PUSHs ((SV *)cv); 343 PUSHs ((SV *)cv);
222 344
223 get_padlist (cv); 345 get_padlist (cv); /* this is a monster */
224
225 CvDEPTH(cv) = 0;
226#ifdef USE_THREADS
227 CvOWNER(cv) = 0;
228 error must unlock this cv etc.. etc...
229 if you are here wondering about this error message then
230 the reason is that it will not work as advertised yet
231#endif
232 } 346 }
233 } 347 }
234 else if (CxTYPE(cx) == CXt_FORMAT) 348 else if (CxTYPE(cx) == CXt_FORMAT)
235 { 349 {
236 /* I never used formats, so how should I know how these are implemented? */ 350 /* I never used formats, so how should I know how these are implemented? */
237 /* my bold guess is as a simple, plain sub... */ 351 /* my bold guess is as a simple, plain sub... */
238 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats"); 352 croak ("CXt_FORMAT not yet handled. Don't switch coroutines from within formats");
239 } 353 }
240 } 354 }
355 while (cxix >= 0);
241 356
242 if (top_si->si_type == PERLSI_MAIN) 357 if (top_si->si_type == PERLSI_MAIN)
243 break; 358 break;
244 359
245 top_si = top_si->si_prev; 360 top_si = top_si->si_prev;
248 } 363 }
249 364
250 PUTBACK; 365 PUTBACK;
251 } 366 }
252 367
368 c->defav = flags & SAVE_DEFAV ? (AV *)SvREFCNT_inc (GvAV (PL_defgv)) : 0;
369 c->defsv = flags & SAVE_DEFSV ? SvREFCNT_inc (DEFSV) : 0;
370 c->errsv = flags & SAVE_ERRSV ? SvREFCNT_inc (ERRSV) : 0;
371
372 /* I have not the slightest idea of why av_reify is necessary */
373 /* but if it's missing the defav contents magically get replaced sometimes */
374 if (c->defav)
375 av_reify (c->defav);
376
253 c->dowarn = PL_dowarn; 377 c->dowarn = PL_dowarn;
254 c->defav = GvAV (PL_defgv); 378
255 c->curstackinfo = PL_curstackinfo; 379 c->curstackinfo = PL_curstackinfo;
256 c->curstack = PL_curstack; 380 c->curstack = PL_curstack;
257 c->mainstack = PL_mainstack; 381 c->mainstack = PL_mainstack;
258 c->stack_sp = PL_stack_sp; 382 c->stack_sp = PL_stack_sp;
259 c->op = PL_op; 383 c->op = PL_op;
277 c->retstack_ix = PL_retstack_ix; 401 c->retstack_ix = PL_retstack_ix;
278 c->retstack_max = PL_retstack_max; 402 c->retstack_max = PL_retstack_max;
279 c->curcop = PL_curcop; 403 c->curcop = PL_curcop;
280} 404}
281 405
282static void 406/*
283LOAD(pTHX_ Coro__State c) 407 * destroy the stacks, the callchain etc...
284{ 408 * still there is a memleak of 128 bytes...
285 PL_dowarn = c->dowarn; 409 */
286 GvAV (PL_defgv) = c->defav;
287 PL_curstackinfo = c->curstackinfo;
288 PL_curstack = c->curstack;
289 PL_mainstack = c->mainstack;
290 PL_stack_sp = c->stack_sp;
291 PL_op = c->op;
292 PL_curpad = c->curpad;
293 PL_stack_base = c->stack_base;
294 PL_stack_max = c->stack_max;
295 PL_tmps_stack = c->tmps_stack;
296 PL_tmps_floor = c->tmps_floor;
297 PL_tmps_ix = c->tmps_ix;
298 PL_tmps_max = c->tmps_max;
299 PL_markstack = c->markstack;
300 PL_markstack_ptr = c->markstack_ptr;
301 PL_markstack_max = c->markstack_max;
302 PL_scopestack = c->scopestack;
303 PL_scopestack_ix = c->scopestack_ix;
304 PL_scopestack_max = c->scopestack_max;
305 PL_savestack = c->savestack;
306 PL_savestack_ix = c->savestack_ix;
307 PL_savestack_max = c->savestack_max;
308 PL_retstack = c->retstack;
309 PL_retstack_ix = c->retstack_ix;
310 PL_retstack_max = c->retstack_max;
311 PL_curcop = c->curcop;
312
313 {
314 dSP;
315 CV *cv;
316
317 /* now do the ugly restore mess */
318 while ((cv = (CV *)POPs))
319 {
320 AV *padlist = (AV *)POPs;
321
322 put_padlist (cv);
323 CvPADLIST(cv) = padlist;
324 CvDEPTH(cv) = (I32)POPs;
325
326#ifdef USE_THREADS
327 CvOWNER(cv) = (struct perl_thread *)POPs;
328 error does not work either
329#endif
330 }
331
332 PUTBACK;
333 }
334}
335
336/* this is an EXACT copy of S_nuke_stacks in perl.c, which is unfortunately static */
337STATIC void 410STATIC void
338destroy_stacks(pTHX) 411destroy_stacks(pTHX)
339{ 412{
340 dSP;
341
342 /* die does this while calling POPSTACK, but I just don't see why. */
343 dounwind(-1);
344
345 /* is this ugly, I ask? */ 413 /* is this ugly, I ask? */
346 while (PL_scopestack_ix) 414 while (PL_scopestack_ix)
347 LEAVE; 415 LEAVE;
348 416
417 /* sure it is, but more important: is it correct?? :/ */
418 while (PL_tmps_ix > PL_tmps_floor) /* should only ever be one iteration */
419 FREETMPS;
420
349 while (PL_curstackinfo->si_next) 421 while (PL_curstackinfo->si_next)
350 PL_curstackinfo = PL_curstackinfo->si_next; 422 PL_curstackinfo = PL_curstackinfo->si_next;
351 423
352 while (PL_curstackinfo) 424 while (PL_curstackinfo)
353 { 425 {
354 PERL_SI *p = PL_curstackinfo->si_prev; 426 PERL_SI *p = PL_curstackinfo->si_prev;
427
428 {
429 dSP;
430 SWITCHSTACK (PL_curstack, PL_curstackinfo->si_stack);
431 PUTBACK; /* possibly superfluous */
432 }
433
434 dounwind(-1);
355 435
356 SvREFCNT_dec(PL_curstackinfo->si_stack); 436 SvREFCNT_dec(PL_curstackinfo->si_stack);
357 Safefree(PL_curstackinfo->si_cxstack); 437 Safefree(PL_curstackinfo->si_cxstack);
358 Safefree(PL_curstackinfo); 438 Safefree(PL_curstackinfo);
359 PL_curstackinfo = p; 439 PL_curstackinfo = p;
360 } 440 }
361 441
362 if (PL_scopestack_ix != 0)
363 Perl_warner(aTHX_ WARN_INTERNAL,
364 "Unbalanced scopes: %ld more ENTERs than LEAVEs\n",
365 (long)PL_scopestack_ix);
366 if (PL_savestack_ix != 0)
367 Perl_warner(aTHX_ WARN_INTERNAL,
368 "Unbalanced saves: %ld more saves than restores\n",
369 (long)PL_savestack_ix);
370 if (PL_tmps_floor != -1)
371 Perl_warner(aTHX_ WARN_INTERNAL,"Unbalanced tmps: %ld more allocs than frees\n",
372 (long)PL_tmps_floor + 1);
373 /*
374 */
375 Safefree(PL_tmps_stack); 442 Safefree(PL_tmps_stack);
376 Safefree(PL_markstack); 443 Safefree(PL_markstack);
377 Safefree(PL_scopestack); 444 Safefree(PL_scopestack);
378 Safefree(PL_savestack); 445 Safefree(PL_savestack);
379 Safefree(PL_retstack); 446 Safefree(PL_retstack);
380} 447}
381 448
382#define SUB_INIT "Coro::State::_newcoro" 449STATIC void
450transfer(pTHX_ struct coro *prev, struct coro *next, int flags)
451{
452 dSP;
453
454 if (prev != next)
455 {
456 /*
457 * this could be done in newprocess which would lead to
458 * extremely elegant and fast (just SAVE/LOAD)
459 * code here, but lazy allocation of stacks has also
460 * some virtues and the overhead of the if() is nil.
461 */
462 if (next->mainstack)
463 {
464 SAVE (prev, flags);
465 LOAD (next);
466 /* mark this state as in-use */
467 next->mainstack = 0;
468 next->tmps_ix = -2;
469 }
470 else if (next->tmps_ix == -2)
471 {
472 croak ("tried to transfer to running coroutine");
473 }
474 else
475 {
476 /*
477 * emulate part of the perl startup here.
478 */
479 UNOP myop;
480
481 SAVE (prev, -1); /* first get rid of the old state */
482
483 init_stacks (); /* from perl.c */
484 SPAGAIN;
485
486 PL_op = (OP *)&myop;
487 /*PL_curcop = 0;*/
488 SvREFCNT_dec (GvAV (PL_defgv));
489 GvAV (PL_defgv) = next->args;
490
491 Zero(&myop, 1, UNOP);
492 myop.op_next = Nullop;
493 myop.op_flags = OPf_WANT_VOID;
494
495 PUSHMARK(SP);
496 XPUSHs ((SV*)get_cv(SUB_INIT, TRUE));
497 /*
498 * the next line is slightly wrong, as PL_op->op_next
499 * is actually being executed so we skip the first op.
500 * that doesn't matter, though, since it is only
501 * pp_nextstate and we never return...
502 * ah yes, and I don't care anyways ;)
503 */
504 PUTBACK;
505 PL_op = pp_entersub(aTHX);
506 SPAGAIN;
507
508 ENTER; /* necessary e.g. for dounwind */
509 }
510 }
511}
383 512
384MODULE = Coro::State PACKAGE = Coro::State 513MODULE = Coro::State PACKAGE = Coro::State
385 514
386PROTOTYPES: ENABLE 515PROTOTYPES: ENABLE
387 516
388BOOT: 517BOOT:
518{ /* {} necessary for stoopid perl-5.6.x */
519 HV * stash = gv_stashpvn("Coro::State", 10, TRUE);
520
521 newCONSTSUB (stash, "SAVE_DEFAV", newSViv (SAVE_DEFAV));
522 newCONSTSUB (stash, "SAVE_DEFSV", newSViv (SAVE_DEFSV));
523 newCONSTSUB (stash, "SAVE_ERRSV", newSViv (SAVE_ERRSV));
524
389 if (!padlist_cache) 525 if (!padlist_cache)
390 padlist_cache = newHV (); 526 padlist_cache = newHV ();
527}
391 528
392Coro::State 529Coro::State
393_newprocess(args) 530_newprocess(args)
394 SV * args 531 SV * args
395 PROTOTYPE: $ 532 PROTOTYPE: $
396 CODE: 533 CODE:
397 Coro__State coro; 534 Coro__State coro;
398 535
399 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV) 536 if (!SvROK (args) || SvTYPE (SvRV (args)) != SVt_PVAV)
400 croak ("Coro::State::newprocess expects an arrayref"); 537 croak ("Coro::State::_newprocess expects an arrayref");
401 538
402 New (0, coro, 1, struct coro); 539 New (0, coro, 1, struct coro);
403 540
404 coro->mainstack = 0; /* actual work is done inside transfer */ 541 coro->mainstack = 0; /* actual work is done inside transfer */
405 coro->args = (AV *)SvREFCNT_inc (SvRV (args)); 542 coro->args = (AV *)SvREFCNT_inc (SvRV (args));
407 RETVAL = coro; 544 RETVAL = coro;
408 OUTPUT: 545 OUTPUT:
409 RETVAL 546 RETVAL
410 547
411void 548void
412transfer(prev,next) 549transfer(prev, next, flags = SAVE_ALL)
413 Coro::State_or_hashref prev 550 Coro::State_or_hashref prev
414 Coro::State_or_hashref next 551 Coro::State_or_hashref next
552 int flags
553 PROTOTYPE: @
415 CODE: 554 CODE:
416 555
417 if (prev != next) 556 transfer (aTHX_ prev, next, flags);
418 {
419 PUTBACK;
420 SAVE (aTHX_ prev);
421
422 /*
423 * this could be done in newprocess which would lead to
424 * extremely elegant and fast (just PUTBACK/SAVE/LOAD/SPAGAIN)
425 * code here, but lazy allocation of stacks has also
426 * some virtues and the overhead of the if() is nil.
427 */
428 if (next->mainstack)
429 {
430 LOAD (aTHX_ next);
431 next->mainstack = 0; /* unnecessary but much cleaner */
432 SPAGAIN;
433 }
434 else
435 {
436 /*
437 * emulate part of the perl startup here.
438 */
439 UNOP myop;
440
441 init_stacks (); /* from perl.c */
442 PL_op = (OP *)&myop;
443 /*PL_curcop = 0;*/
444 GvAV (PL_defgv) = (SV *)SvREFCNT_inc (next->args);
445
446 SPAGAIN;
447 Zero(&myop, 1, UNOP);
448 myop.op_next = Nullop;
449 myop.op_flags = OPf_WANT_VOID;
450
451 PUSHMARK(SP);
452 XPUSHs ((SV*)get_cv(SUB_INIT, TRUE));
453 PUTBACK;
454 /*
455 * the next line is slightly wrong, as PL_op->op_next
456 * is actually being executed so we skip the first op.
457 * that doesn't matter, though, since it is only
458 * pp_nextstate and we never return...
459 */
460 PL_op = Perl_pp_entersub(aTHX);
461 SPAGAIN;
462
463 ENTER;
464 }
465 }
466 557
467void 558void
468DESTROY(coro) 559DESTROY(coro)
469 Coro::State coro 560 Coro::State coro
470 CODE: 561 CODE:
471 562
472 if (coro->mainstack) 563 if (coro->mainstack)
473 { 564 {
474 struct coro temp; 565 struct coro temp;
475 566
476 PUTBACK;
477 SAVE(aTHX_ (&temp)); 567 SAVE(aTHX_ (&temp), SAVE_ALL);
478 LOAD(aTHX_ coro); 568 LOAD(aTHX_ coro);
479 569
480 destroy_stacks (); 570 destroy_stacks ();
481 SvREFCNT_dec ((SV *)GvAV (PL_defgv));
482 571
483 LOAD((&temp)); 572 LOAD((&temp)); /* this will get rid of defsv etc.. */
484 SPAGAIN;
485 } 573 }
486 574
487 SvREFCNT_dec (coro->args);
488 Safefree (coro); 575 Safefree (coro);
489 576
577void
578flush()
579 CODE:
580#ifdef MAY_FLUSH
581 flush_padlist_cache ();
582#endif
490 583
584MODULE = Coro::State PACKAGE = Coro::Cont
585
586# this is dirty (do you hear me?) and should be in it's own .xs
587
588void
589result(...)
590 PROTOTYPE: @
591 CODE:
592 static SV *returnstk;
593 SV *sv;
594 AV *defav = GvAV (PL_defgv);
595 struct coro *prev, *next;
596
597 if (!returnstk)
598 returnstk = SvRV (get_sv ("Coro::Cont::return", FALSE));
599
600 /* set up @_ -- ugly */
601 av_clear (defav);
602 av_fill (defav, items - 1);
603 while (items--)
604 av_store (defav, items, SvREFCNT_inc (ST(items)));
605
606 mg_get (returnstk); /* isn't documentation wrong for mg_get? */
607 sv = av_pop ((AV *)SvRV (returnstk));
608 prev = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0)));
609 next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0)));
610 SvREFCNT_dec (sv);
611 transfer(prev, next, 0);
612

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines