… | |
… | |
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 | |
734 | static void |
741 | static void |
735 | coro_destroy (pTHX_ struct coro *coro) |
742 | coro_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 |
1578 | void |
1586 | void |
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 | |
1678 | bool |
1633 | bool |
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); |