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.315 by root, Thu Nov 20 05:25:17 2008 UTC vs.
Revision 1.317 by root, Thu Nov 20 06:28:52 2008 UTC

1612api_is_ready (pTHX_ SV *coro_sv) 1612api_is_ready (pTHX_ SV *coro_sv)
1613{ 1613{
1614 return !!(SvSTATE (coro_sv)->flags & CF_READY); 1614 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1615} 1615}
1616 1616
1617/* expects to own a reference to next->hv */
1617INLINE void 1618INLINE void
1619prepare_schedule_to (pTHX_ struct coro_transfer_args *ta, struct coro *next)
1620{
1621 SV *prev_sv = SvRV (coro_current);
1622
1623 ta->prev = SvSTATE_hv (prev_sv);
1624 ta->next = next;
1625
1626 TRANSFER_CHECK (*ta);
1627
1628 SvRV_set (coro_current, (SV *)next->hv);
1629
1630 free_coro_mortal (aTHX);
1631 coro_mortal = prev_sv;
1632}
1633
1634static void
1618prepare_schedule (pTHX_ struct coro_transfer_args *ta) 1635prepare_schedule (pTHX_ struct coro_transfer_args *ta)
1619{ 1636{
1620 SV *prev_sv, *next_sv;
1621
1622 for (;;) 1637 for (;;)
1623 { 1638 {
1624 next_sv = coro_deq (aTHX); 1639 SV *next_sv = coro_deq (aTHX);
1625 1640
1626 /* nothing to schedule: call the idle handler */
1627 if (expect_false (!next_sv)) 1641 if (expect_true (next_sv))
1628 { 1642 {
1643 struct coro *next = SvSTATE_hv (next_sv);
1644
1645 /* cannot transfer to destroyed coros, skip and look for next */
1646 if (expect_false (next->flags & CF_DESTROYED))
1647 SvREFCNT_dec (next_sv); /* coro_nready has already been taken care of by destroy */
1648 else
1649 {
1650 next->flags &= ~CF_READY;
1651 --coro_nready;
1652
1653 return prepare_schedule_to (aTHX_ ta, next);
1654 }
1655 }
1656 else
1657 {
1658 /* nothing to schedule: call the idle handler */
1629 dSP; 1659 dSP;
1630 1660
1631 ENTER; 1661 ENTER;
1632 SAVETMPS; 1662 SAVETMPS;
1633 1663
1635 PUTBACK; 1665 PUTBACK;
1636 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD); 1666 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD);
1637 1667
1638 FREETMPS; 1668 FREETMPS;
1639 LEAVE; 1669 LEAVE;
1640 continue;
1641 } 1670 }
1642
1643 ta->next = SvSTATE_hv (next_sv);
1644
1645 /* cannot transfer to destroyed coros, skip and look for next */
1646 if (expect_false (ta->next->flags & CF_DESTROYED))
1647 {
1648 SvREFCNT_dec (next_sv);
1649 /* coro_nready has already been taken care of by destroy */
1650 continue;
1651 }
1652
1653 --coro_nready;
1654 break;
1655 } 1671 }
1656
1657 /* free this only after the transfer */
1658 prev_sv = SvRV (coro_current);
1659 ta->prev = SvSTATE_hv (prev_sv);
1660 TRANSFER_CHECK (*ta);
1661 assert (("FATAL: next coroutine isn't marked as ready in Coro (please report)", ta->next->flags & CF_READY));
1662 ta->next->flags &= ~CF_READY;
1663 SvRV_set (coro_current, next_sv);
1664
1665 free_coro_mortal (aTHX);
1666 coro_mortal = prev_sv;
1667} 1672}
1668 1673
1669INLINE void 1674INLINE void
1670prepare_cede (pTHX_ struct coro_transfer_args *ta) 1675prepare_cede (pTHX_ struct coro_transfer_args *ta)
1671{ 1676{
1692{ 1697{
1693 struct coro_transfer_args ta; 1698 struct coro_transfer_args ta;
1694 1699
1695 prepare_schedule (aTHX_ &ta); 1700 prepare_schedule (aTHX_ &ta);
1696 TRANSFER (ta, 1); 1701 TRANSFER (ta, 1);
1702}
1703
1704static void
1705api_schedule_to (pTHX_ SV *coro_sv)
1706{
1707 struct coro_transfer_args ta;
1708 struct coro *next = SvSTATE (coro_sv);
1709
1710 SvREFCNT_inc_NN (coro_sv);
1711 prepare_schedule_to (aTHX_ &ta, next);
1697} 1712}
1698 1713
1699static int 1714static int
1700api_cede (pTHX) 1715api_cede (pTHX)
1701{ 1716{
1990static void 2005static void
1991slf_init_schedule (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2006slf_init_schedule (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1992{ 2007{
1993 frame->prepare = prepare_schedule; 2008 frame->prepare = prepare_schedule;
1994 frame->check = slf_check_nop; 2009 frame->check = slf_check_nop;
2010}
2011
2012static void
2013slf_prepare_schedule_to (pTHX_ struct coro_transfer_args *ta)
2014{
2015 struct coro *next = (struct coro *)slf_frame.data;
2016
2017 SvREFCNT_inc_NN (next->hv);
2018 prepare_schedule_to (aTHX_ ta, next);
2019}
2020
2021static void
2022slf_init_schedule_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2023{
2024 if (!items)
2025 croak ("Coro::schedule_to expects a coroutine argument, caught");
2026
2027 frame->data = (void *)SvSTATE (arg [0]);
2028 frame->prepare = slf_prepare_schedule_to;
2029 frame->check = slf_check_nop;
2030}
2031
2032static void
2033slf_init_cede_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2034{
2035 api_ready (aTHX_ SvRV (coro_current));
2036
2037 slf_init_schedule_to (aTHX_ frame, cv, arg, items);
1995} 2038}
1996 2039
1997static void 2040static void
1998slf_init_cede (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2041slf_init_cede (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1999{ 2042{
2981 3024
2982 { 3025 {
2983 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE); 3026 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE);
2984 3027
2985 coroapi.schedule = api_schedule; 3028 coroapi.schedule = api_schedule;
3029 coroapi.schedule_to = api_schedule_to;
2986 coroapi.cede = api_cede; 3030 coroapi.cede = api_cede;
2987 coroapi.cede_notself = api_cede_notself; 3031 coroapi.cede_notself = api_cede_notself;
2988 coroapi.ready = api_ready; 3032 coroapi.ready = api_ready;
2989 coroapi.is_ready = api_is_ready; 3033 coroapi.is_ready = api_is_ready;
2990 coroapi.nready = coro_nready; 3034 coroapi.nready = coro_nready;
2998 3042
2999void 3043void
3000schedule (...) 3044schedule (...)
3001 CODE: 3045 CODE:
3002 CORO_EXECUTE_SLF_XS (slf_init_schedule); 3046 CORO_EXECUTE_SLF_XS (slf_init_schedule);
3047
3048void
3049schedule_to (...)
3050 CODE:
3051 CORO_EXECUTE_SLF_XS (slf_init_schedule_to);
3052
3053void
3054cede_to (...)
3055 CODE:
3056 CORO_EXECUTE_SLF_XS (slf_init_cede_to);
3003 3057
3004void 3058void
3005cede (...) 3059cede (...)
3006 CODE: 3060 CODE:
3007 CORO_EXECUTE_SLF_XS (slf_init_cede); 3061 CORO_EXECUTE_SLF_XS (slf_init_cede);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines