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.209 by root, Wed Oct 10 02:58:17 2007 UTC vs.
Revision 1.210 by root, Wed Oct 10 03:24:40 2007 UTC

727 PUSHs ((SV *)0); /* ix, set_stacklevel */ 727 PUSHs ((SV *)0); /* ix, set_stacklevel */
728 PUSHs ((SV *)(sp - PL_stack_base + 1)); /* ax */ 728 PUSHs ((SV *)(sp - PL_stack_base + 1)); /* ax */
729 PUSHs ((SV *)0); /* again */ 729 PUSHs ((SV *)0); /* again */
730 PUTBACK; 730 PUTBACK;
731 } 731 }
732
733 /* this newly created coroutine might be run on an existing cctx which most
734 * likely was suspended in set_stacklevel, called from entersub.
735 * set_stacklevl doesn't do anything on return, but entersub does LEAVE,
736 * so we ENTER here for symmetry
737 */
738 ENTER;
732} 739}
733 740
734static void 741static void
735coro_destroy (pTHX_ struct coro *coro) 742coro_destroy (pTHX_ struct coro *coro)
736{ 743{
1538 1545
1539 while (main_top_env->je_prev) 1546 while (main_top_env->je_prev)
1540 main_top_env = main_top_env->je_prev; 1547 main_top_env = main_top_env->je_prev;
1541 1548
1542 coroapi.ver = CORO_API_VERSION; 1549 coroapi.ver = CORO_API_VERSION;
1550 coroapi.rev = CORO_API_REVISION;
1543 coroapi.transfer = api_transfer; 1551 coroapi.transfer = api_transfer;
1544 1552
1545 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL)); 1553 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL));
1546} 1554}
1547 1555
1576# function to increase chances that they all will call transfer with the same 1584# function to increase chances that they all will call transfer with the same
1577# stack offset 1585# stack offset
1578void 1586void
1579_set_stacklevel (...) 1587_set_stacklevel (...)
1580 ALIAS: 1588 ALIAS:
1581 Coro::State::transfer = 1 1589 Coro::State::transfer = 1
1582 Coro::schedule = 2 1590 Coro::schedule = 2
1583 Coro::cede = 3 1591 Coro::cede = 3
1584 Coro::cede_notself = 4 1592 Coro::cede_notself = 4
1585 Coro::Event::next = 5
1586 Coro::Event::next_cancel = 6
1587 PPCODE: 1593 CODE:
1588{ 1594{
1589 struct transfer_args ta; 1595 struct transfer_args ta;
1590 int again = 0;
1591 1596
1592 do 1597 switch (ix)
1593 { 1598 {
1594 switch (ix)
1595 {
1596 case 0: 1599 case 0:
1597 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0))); 1600 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0)));
1598 ta.next = 0; 1601 ta.next = 0;
1599 break; 1602 break;
1600 1603
1601 case 1: 1604 case 1:
1602 if (items != 2) 1605 if (items != 2)
1603 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items); 1606 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items);
1604 1607
1605 prepare_transfer (aTHX_ &ta, ST(0), ST(1)); 1608 prepare_transfer (aTHX_ &ta, ST (0), ST (1));
1606 break; 1609 break;
1607 1610
1608 case 2: 1611 case 2:
1609 prepare_schedule (aTHX_ &ta); 1612 prepare_schedule (aTHX_ &ta);
1610 break; 1613 break;
1611 1614
1612 case 3: 1615 case 3:
1613 prepare_cede (aTHX_ &ta); 1616 prepare_cede (aTHX_ &ta);
1614 break; 1617 break;
1615 1618
1616 case 4: 1619 case 4:
1617 if (!prepare_cede_notself (aTHX_ &ta)) 1620 if (!prepare_cede_notself (aTHX_ &ta))
1618 XSRETURN_EMPTY; 1621 XSRETURN_EMPTY;
1619 1622
1620 break; 1623 break;
1621
1622 case 5:
1623 case 6:
1624 if (items != 1)
1625 croak ("Coro::Event::next (watcher) expects one argument, not %d", items);
1626
1627 {
1628 SV *ev = coroapi.coro_event_next (ST (0), ix == 6, GIMME_V != G_VOID);
1629
1630 if (ev)
1631 {
1632 if (GIMME_V != G_VOID)
1633 {
1634 XPUSHs (ev);
1635 XSRETURN (1);
1636 }
1637 else
1638 XSRETURN_EMPTY;
1639 }
1640 }
1641
1642 prepare_schedule (aTHX_ &ta);
1643 again = 1;
1644 break;
1645 }
1646
1647 /* our caller, entersub, caches *only* this value */
1648 ta.prev->gimme = GIMME_V == G_VOID ? 0
1649 : GIMME_V == G_SCALAR ? 1
1650 : 2;
1651
1652 /* we need to save all local variables, as we might execute a different coroutine when transfer returns */
1653 sp += 2; /* save args */
1654 EXTEND (SP, 4);
1655 PUSHs ((SV *)(intptr_t)items);
1656 PUSHs ((SV *)(intptr_t)ix);
1657 PUSHs ((SV *)(intptr_t)ax);
1658 PUSHs ((SV *)(intptr_t)again);
1659 PUTBACK;
1660 BARRIER;
1661 TRANSFER (ta);
1662 BARRIER;
1663 SPAGAIN;
1664 again = (intptr_t)POPs;
1665 ax = (intptr_t)POPs;
1666 ix = (intptr_t)POPs;
1667 items = (intptr_t)POPs;
1668 sp -= 2; /* restore args */
1669 } 1624 }
1670 while (again);
1671 1625
1672 if (expect_false (GIMME_V != G_VOID && ta.next != ta.prev)) 1626 BARRIER;
1673 XSRETURN_YES; 1627 PUTBACK;
1674 1628 TRANSFER (ta);
1675 XSRETURN_EMPTY; /* not understood why this is necessary, likely some stack handling bug */ 1629 SPAGAIN; /* might be the sp of a different coroutine now */
1630 /* be extra careful not to ever do anything after TRANSFER */
1676} 1631}
1677 1632
1678bool 1633bool
1679_destroy (SV *coro_sv) 1634_destroy (SV *coro_sv)
1680 CODE: 1635 CODE:
1752 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 1707 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1753 1708
1754 POPSTACK; 1709 POPSTACK;
1755 FREETMPS; 1710 FREETMPS;
1756 LEAVE; 1711 LEAVE;
1712 PUTBACK;
1757 } 1713 }
1758 1714
1759 if (!(coro->flags & CF_RUNNING)) 1715 if (!(coro->flags & CF_RUNNING))
1760 { 1716 {
1761 save_perl (aTHX_ coro); 1717 save_perl (aTHX_ coro);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines