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.208 by root, Wed Oct 10 00:53:18 2007 UTC vs.
Revision 1.211 by root, Wed Oct 10 03:37:58 2007 UTC

10#include "patchlevel.h" 10#include "patchlevel.h"
11 11
12#include <stdio.h> 12#include <stdio.h>
13#include <errno.h> 13#include <errno.h>
14#include <assert.h> 14#include <assert.h>
15#include <inttypes.h> /* portable stdint.h */
15 16
16#ifdef HAVE_MMAP 17#ifdef HAVE_MMAP
17# include <unistd.h> 18# include <unistd.h>
18# include <sys/mman.h> 19# include <sys/mman.h>
19# ifndef MAP_ANONYMOUS 20# ifndef MAP_ANONYMOUS
712 PL_op = (OP *)&myop; 713 PL_op = (OP *)&myop;
713 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 714 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
714 SPAGAIN; 715 SPAGAIN;
715 } 716 }
716 717
717 ENTER; /* necessary e.g. for dounwind and to balance the xsub-entersub */ 718 /* this newly created coroutine might be run on an existing cctx which most
719 * likely was suspended in set_stacklevel, called from entersub.
720 * set_stacklevl doesn't do anything on return, but entersub does LEAVE,
721 * so we ENTER here for symmetry
722 */
723 ENTER;
718} 724}
719 725
720static void 726static void
721coro_destroy (pTHX_ struct coro *coro) 727coro_destroy (pTHX_ struct coro *coro)
722{ 728{
1523 1529
1524 while (main_top_env->je_prev) 1530 while (main_top_env->je_prev)
1525 main_top_env = main_top_env->je_prev; 1531 main_top_env = main_top_env->je_prev;
1526 1532
1527 coroapi.ver = CORO_API_VERSION; 1533 coroapi.ver = CORO_API_VERSION;
1534 coroapi.rev = CORO_API_REVISION;
1528 coroapi.transfer = api_transfer; 1535 coroapi.transfer = api_transfer;
1529 1536
1530 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL)); 1537 assert (("PRIO_NORMAL must be 0", !PRIO_NORMAL));
1531} 1538}
1532 1539
1561# function to increase chances that they all will call transfer with the same 1568# function to increase chances that they all will call transfer with the same
1562# stack offset 1569# stack offset
1563void 1570void
1564_set_stacklevel (...) 1571_set_stacklevel (...)
1565 ALIAS: 1572 ALIAS:
1566 Coro::State::transfer = 1 1573 Coro::State::transfer = 1
1567 Coro::schedule = 2 1574 Coro::schedule = 2
1568 Coro::cede = 3 1575 Coro::cede = 3
1569 Coro::cede_notself = 4 1576 Coro::cede_notself = 4
1570 Coro::Event::next = 5
1571 Coro::Event::next_cancel = 6
1572 PPCODE: 1577 CODE:
1573{ 1578{
1574 struct transfer_args ta; 1579 struct transfer_args ta;
1575 int again = 0;
1576 1580
1577 do 1581 switch (ix)
1578 { 1582 {
1579 switch (ix)
1580 {
1581 case 0: 1583 case 0:
1582 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0))); 1584 ta.prev = (struct coro *)INT2PTR (coro_cctx *, SvIV (ST (0)));
1583 ta.next = 0; 1585 ta.next = 0;
1584 break; 1586 break;
1585 1587
1586 case 1: 1588 case 1:
1587 if (items != 2) 1589 if (items != 2)
1588 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items); 1590 croak ("Coro::State::transfer (prev,next) expects two arguments, not %d", items);
1589 1591
1590 prepare_transfer (aTHX_ &ta, ST (0), ST (1)); 1592 prepare_transfer (aTHX_ &ta, ST (0), ST (1));
1591 break; 1593 break;
1592 1594
1593 case 2: 1595 case 2:
1594 prepare_schedule (aTHX_ &ta); 1596 prepare_schedule (aTHX_ &ta);
1595 break; 1597 break;
1596 1598
1597 case 3: 1599 case 3:
1598 prepare_cede (aTHX_ &ta); 1600 prepare_cede (aTHX_ &ta);
1599 break; 1601 break;
1600 1602
1601 case 4: 1603 case 4:
1602 if (!prepare_cede_notself (aTHX_ &ta)) 1604 if (!prepare_cede_notself (aTHX_ &ta))
1603 XSRETURN_EMPTY; 1605 XSRETURN_EMPTY;
1604 1606
1605 break; 1607 break;
1606
1607 case 5:
1608 case 6:
1609 if (items != 1)
1610 croak ("Coro::Event::next (watcher) expects one argument, not %d", items);
1611
1612 {
1613 SV *ev = coroapi.coro_event_next (ST (0), ix == 6, GIMME_V != G_VOID);
1614
1615 if (ev)
1616 {
1617 if (GIMME_V != G_VOID)
1618 {
1619 XPUSHs (ev);
1620 XSRETURN (1);
1621 }
1622 else
1623 XSRETURN_EMPTY;
1624 }
1625 }
1626
1627 prepare_schedule (aTHX_ &ta);
1628 again = 1;
1629 break;
1630 }
1631
1632 BARRIER;
1633 TRANSFER (ta);
1634 BARRIER;
1635 } 1608 }
1636 while (again);
1637 1609
1638 if (expect_false (GIMME_V != G_VOID && ta.next != ta.prev)) 1610 BARRIER;
1639 XSRETURN_YES; 1611 PUTBACK;
1640 1612 TRANSFER (ta);
1641 XSRETURN_EMPTY; /* not understood why this is necessary, likely some stack handling bug */ 1613 SPAGAIN; /* might be the sp of a different coroutine now */
1614 /* be extra careful not to ever do anything after TRANSFER */
1615}
1642 1616
1643bool 1617bool
1644_destroy (SV *coro_sv) 1618_destroy (SV *coro_sv)
1645 CODE: 1619 CODE:
1646 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv)); 1620 RETVAL = coro_state_destroy (aTHX_ SvSTATE (coro_sv));
1715 eval_sv (coderef, 0); 1689 eval_sv (coderef, 0);
1716 else 1690 else
1717 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 1691 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1718 1692
1719 POPSTACK; 1693 POPSTACK;
1694 SPAGAIN;
1720 FREETMPS; 1695 FREETMPS;
1721 LEAVE; 1696 LEAVE;
1697 PUTBACK;
1722 } 1698 }
1723 1699
1724 if (!(coro->flags & CF_RUNNING)) 1700 if (!(coro->flags & CF_RUNNING))
1725 { 1701 {
1726 save_perl (aTHX_ coro); 1702 save_perl (aTHX_ coro);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines