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.316 by root, Thu Nov 20 06:01:40 2008 UTC vs.
Revision 1.321 by root, Sat Nov 22 02:09:54 2008 UTC

1#define CORO_CLONE 1 //D
2
1#include "libcoro/coro.c" 3#include "libcoro/coro.c"
2 4
3#define PERL_NO_GET_CONTEXT 5#define PERL_NO_GET_CONTEXT
4#define PERL_EXT 6#define PERL_EXT
5 7
101# define CvISXSUB_on(cv) (void)cv 103# define CvISXSUB_on(cv) (void)cv
102#endif 104#endif
103#ifndef CvISXSUB 105#ifndef CvISXSUB
104# define CvISXSUB(cv) (CvXSUB (cv) ? TRUE : FALSE) 106# define CvISXSUB(cv) (CvXSUB (cv) ? TRUE : FALSE)
105#endif 107#endif
108#ifndef Newx
109# define Newx(ptr,nitems,type) New (0,ptr,nitems,type)
110#endif
106 111
107/* 5.8.7 */ 112/* 5.8.7 */
108#ifndef SvRV_set 113#ifndef SvRV_set
109# define SvRV_set(s,v) SvRV(s) = (v) 114# define SvRV_set(s,v) SvRV(s) = (v)
110#endif 115#endif
170static AV *main_mainstack; /* used to differentiate between $main and others */ 175static AV *main_mainstack; /* used to differentiate between $main and others */
171static JMPENV *main_top_env; 176static JMPENV *main_top_env;
172static HV *coro_state_stash, *coro_stash; 177static HV *coro_state_stash, *coro_stash;
173static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */ 178static volatile SV *coro_mortal; /* will be freed/thrown after next transfer */
174 179
180static AV *av_destroy; /* destruction queue */
181static SV *sv_manager; /* the manager coro */
182
175static GV *irsgv; /* $/ */ 183static GV *irsgv; /* $/ */
176static GV *stdoutgv; /* *STDOUT */ 184static GV *stdoutgv; /* *STDOUT */
177static SV *rv_diehook; 185static SV *rv_diehook;
178static SV *rv_warnhook; 186static SV *rv_warnhook;
179static HV *hv_sig; /* %SIG */ 187static HV *hv_sig; /* %SIG */
180 188
181/* async_pool helper stuff */ 189/* async_pool helper stuff */
182static SV *sv_pool_rss; 190static SV *sv_pool_rss;
183static SV *sv_pool_size; 191static SV *sv_pool_size;
184static SV *sv_async_pool_idle; 192static SV *sv_async_pool_idle; /* description string */
185static AV *av_async_pool; 193static AV *av_async_pool; /* idle pool */
186static SV *sv_Coro; 194static SV *sv_Coro; /* class string */
187static CV *cv_pool_handler; 195static CV *cv_pool_handler;
188static CV *cv_coro_state_new; 196static CV *cv_coro_state_new;
189 197
190/* Coro::AnyEvent */ 198/* Coro::AnyEvent */
191static SV *sv_activity; 199static SV *sv_activity;
344 GV *gvp; 352 GV *gvp;
345 return sv_2cv (sv, &st, &gvp, 0); 353 return sv_2cv (sv, &st, &gvp, 0);
346} 354}
347 355
348static AV * 356static AV *
349coro_clone_padlist (pTHX_ CV *cv) 357coro_derive_padlist (pTHX_ CV *cv)
350{ 358{
351 AV *padlist = CvPADLIST (cv); 359 AV *padlist = CvPADLIST (cv);
352 AV *newpadlist, *newpad; 360 AV *newpadlist, *newpad;
353 361
354 newpadlist = newAV (); 362 newpadlist = newAV ();
474 CV *cp = Perl_cv_clone (aTHX_ cv); 482 CV *cp = Perl_cv_clone (aTHX_ cv);
475 CvPADLIST (cv) = CvPADLIST (cp); 483 CvPADLIST (cv) = CvPADLIST (cp);
476 CvPADLIST (cp) = 0; 484 CvPADLIST (cp) = 0;
477 SvREFCNT_dec (cp); 485 SvREFCNT_dec (cp);
478#else 486#else
479 CvPADLIST (cv) = coro_clone_padlist (aTHX_ cv); 487 CvPADLIST (cv) = coro_derive_padlist (aTHX_ cv);
480#endif 488#endif
481 } 489 }
482} 490}
483 491
484static void 492static void
834slf_check_nop (pTHX_ struct CoroSLF *frame) 842slf_check_nop (pTHX_ struct CoroSLF *frame)
835{ 843{
836 return 0; 844 return 0;
837} 845}
838 846
847static int
848slf_check_repeat (pTHX_ struct CoroSLF *frame)
849{
850 return 1;
851}
852
839static UNOP coro_setup_op; 853static UNOP coro_setup_op;
840 854
841static void NOINLINE /* noinline to keep it out of the transfer fast path */ 855static void NOINLINE /* noinline to keep it out of the transfer fast path */
842coro_setup (pTHX_ struct coro *coro) 856coro_setup (pTHX_ struct coro *coro)
843{ 857{
892 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */ 906 slf_frame.prepare = prepare_nop; /* provide a nop function for an eventual pp_slf */
893 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */ 907 slf_frame.check = slf_check_nop; /* signal pp_slf to not repeat */
894 908
895 /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */ 909 /* and we have to provide the pp_slf op in any case, so pp_slf can skip it */
896 coro_setup_op.op_next = PL_op; 910 coro_setup_op.op_next = PL_op;
897 coro_setup_op.op_type = OP_CUSTOM; 911 coro_setup_op.op_type = OP_ENTERSUB;
898 coro_setup_op.op_ppaddr = pp_slf; 912 coro_setup_op.op_ppaddr = pp_slf;
899 /* no flags etc. required, as an init function won't be called */ 913 /* no flags etc. required, as an init function won't be called */
900 914
901 PL_op = (OP *)&coro_setup_op; 915 PL_op = (OP *)&coro_setup_op;
902 916
1017 { 1031 {
1018 PERL_CONTEXT *cx = &cxstack[cxstack_ix]; 1032 PERL_CONTEXT *cx = &cxstack[cxstack_ix];
1019 1033
1020 if (CxTYPE (cx) == CXt_SUB && oldcxix < cxstack_ix) 1034 if (CxTYPE (cx) == CXt_SUB && oldcxix < cxstack_ix)
1021 { 1035 {
1022 runops_proc_t old_runops = PL_runops;
1023 dSP; 1036 dSP;
1024 GV *gv = CvGV (cx->blk_sub.cv); 1037 GV *gv = CvGV (cx->blk_sub.cv);
1025 SV *fullname = sv_2mortal (newSV (0)); 1038 SV *fullname = sv_2mortal (newSV (0));
1026 1039
1027 if (isGV (gv)) 1040 if (isGV (gv))
1614 return !!(SvSTATE (coro_sv)->flags & CF_READY); 1627 return !!(SvSTATE (coro_sv)->flags & CF_READY);
1615} 1628}
1616 1629
1617/* expects to own a reference to next->hv */ 1630/* expects to own a reference to next->hv */
1618INLINE void 1631INLINE void
1619prepare_cede_to (pTHX_ struct coro_transfer_args *ta, struct coro *next) 1632prepare_schedule_to (pTHX_ struct coro_transfer_args *ta, struct coro *next)
1620{ 1633{
1621 SV *prev_sv = SvRV (coro_current); 1634 SV *prev_sv = SvRV (coro_current);
1622 1635
1623 ta->prev = SvSTATE_hv (prev_sv); 1636 ta->prev = SvSTATE_hv (prev_sv);
1624 ta->next = next; 1637 ta->next = next;
1625 1638
1626 TRANSFER_CHECK (*ta); 1639 TRANSFER_CHECK (*ta);
1627 1640
1628 SvRV_set (coro_current, next->hv); 1641 SvRV_set (coro_current, (SV *)next->hv);
1629 1642
1630 free_coro_mortal (aTHX); 1643 free_coro_mortal (aTHX);
1631 coro_mortal = prev_sv; 1644 coro_mortal = prev_sv;
1632} 1645}
1633 1646
1636{ 1649{
1637 for (;;) 1650 for (;;)
1638 { 1651 {
1639 SV *next_sv = coro_deq (aTHX); 1652 SV *next_sv = coro_deq (aTHX);
1640 1653
1641 if (expect_false (!next_sv)) 1654 if (expect_true (next_sv))
1642 {
1643 /* nothing to schedule: call the idle handler */
1644 dSP;
1645
1646 ENTER;
1647 SAVETMPS;
1648
1649 PUSHMARK (SP);
1650 PUTBACK;
1651 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD);
1652
1653 FREETMPS;
1654 LEAVE;
1655 }
1656 else
1657 { 1655 {
1658 struct coro *next = SvSTATE_hv (next_sv); 1656 struct coro *next = SvSTATE_hv (next_sv);
1659 1657
1660 /* cannot transfer to destroyed coros, skip and look for next */ 1658 /* cannot transfer to destroyed coros, skip and look for next */
1661 if (expect_false (next->flags & CF_DESTROYED)) 1659 if (expect_false (next->flags & CF_DESTROYED))
1663 else 1661 else
1664 { 1662 {
1665 next->flags &= ~CF_READY; 1663 next->flags &= ~CF_READY;
1666 --coro_nready; 1664 --coro_nready;
1667 1665
1668 return prepare_cede_to (aTHX_ ta, next); 1666 prepare_schedule_to (aTHX_ ta, next);
1667 break;
1669 } 1668 }
1670 } 1669 }
1670 else
1671 {
1672 /* nothing to schedule: call the idle handler */
1673 dSP;
1674
1675 ENTER;
1676 SAVETMPS;
1677
1678 PUSHMARK (SP);
1679 PUTBACK;
1680 call_sv (get_sv ("Coro::idle", FALSE), G_VOID | G_DISCARD);
1681
1682 FREETMPS;
1683 LEAVE;
1684 }
1671 } 1685 }
1672} 1686}
1673 1687
1674INLINE void 1688INLINE void
1675prepare_cede (pTHX_ struct coro_transfer_args *ta) 1689prepare_cede (pTHX_ struct coro_transfer_args *ta)
1697{ 1711{
1698 struct coro_transfer_args ta; 1712 struct coro_transfer_args ta;
1699 1713
1700 prepare_schedule (aTHX_ &ta); 1714 prepare_schedule (aTHX_ &ta);
1701 TRANSFER (ta, 1); 1715 TRANSFER (ta, 1);
1716}
1717
1718static void
1719api_schedule_to (pTHX_ SV *coro_sv)
1720{
1721 struct coro_transfer_args ta;
1722 struct coro *next = SvSTATE (coro_sv);
1723
1724 SvREFCNT_inc_NN (coro_sv);
1725 prepare_schedule_to (aTHX_ &ta, next);
1702} 1726}
1703 1727
1704static int 1728static int
1705api_cede (pTHX) 1729api_cede (pTHX)
1706{ 1730{
1753 if (coro->flags & CF_RUNNING) 1777 if (coro->flags & CF_RUNNING)
1754 PL_runops = RUNOPS_DEFAULT; 1778 PL_runops = RUNOPS_DEFAULT;
1755 else 1779 else
1756 coro->slot->runops = RUNOPS_DEFAULT; 1780 coro->slot->runops = RUNOPS_DEFAULT;
1757 } 1781 }
1782}
1783
1784static void
1785coro_call_on_destroy (pTHX_ struct coro *coro)
1786{
1787 SV **on_destroyp = hv_fetch (coro->hv, "_on_destroy", sizeof ("_on_destroy") - 1, 0);
1788 SV **statusp = hv_fetch (coro->hv, "_status", sizeof ("_status") - 1, 0);
1789
1790 if (on_destroyp)
1791 {
1792 AV *on_destroy = (AV *)SvRV (*on_destroyp);
1793
1794 while (AvFILLp (on_destroy) >= 0)
1795 {
1796 dSP; /* don't disturb outer sp */
1797 SV *cb = av_pop (on_destroy);
1798
1799 PUSHMARK (SP);
1800
1801 if (statusp)
1802 {
1803 int i;
1804 AV *status = (AV *)SvRV (*statusp);
1805 EXTEND (SP, AvFILLp (status) + 1);
1806
1807 for (i = 0; i <= AvFILLp (status); ++i)
1808 PUSHs (AvARRAY (status)[i]);
1809 }
1810
1811 PUTBACK;
1812 call_sv (sv_2mortal (cb), G_VOID | G_DISCARD);
1813 }
1814 }
1815}
1816
1817static void
1818slf_init_terminate (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1819{
1820 int i;
1821 HV *hv = (HV *)SvRV (coro_current);
1822 AV *av = newAV ();
1823
1824 av_extend (av, items - 1);
1825 for (i = 0; i < items; ++i)
1826 av_push (av, SvREFCNT_inc_NN (arg [i]));
1827
1828 hv_store (hv, "_status", sizeof ("_status") - 1, newRV_noinc ((SV *)av), 0);
1829
1830 av_push (av_destroy, (SV *)newRV_inc ((SV *)hv)); /* RVinc for perl */
1831 api_ready (aTHX_ sv_manager);
1832
1833 frame->prepare = prepare_schedule;
1834 frame->check = slf_check_repeat;
1758} 1835}
1759 1836
1760/*****************************************************************************/ 1837/*****************************************************************************/
1761/* async pool handler */ 1838/* async pool handler */
1762 1839
1995static void 2072static void
1996slf_init_schedule (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2073slf_init_schedule (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
1997{ 2074{
1998 frame->prepare = prepare_schedule; 2075 frame->prepare = prepare_schedule;
1999 frame->check = slf_check_nop; 2076 frame->check = slf_check_nop;
2077}
2078
2079static void
2080slf_prepare_schedule_to (pTHX_ struct coro_transfer_args *ta)
2081{
2082 struct coro *next = (struct coro *)slf_frame.data;
2083
2084 SvREFCNT_inc_NN (next->hv);
2085 prepare_schedule_to (aTHX_ ta, next);
2086}
2087
2088static void
2089slf_init_schedule_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2090{
2091 if (!items)
2092 croak ("Coro::schedule_to expects a coroutine argument, caught");
2093
2094 frame->data = (void *)SvSTATE (arg [0]);
2095 frame->prepare = slf_prepare_schedule_to;
2096 frame->check = slf_check_nop;
2097}
2098
2099static void
2100slf_init_cede_to (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2101{
2102 api_ready (aTHX_ SvRV (coro_current));
2103
2104 slf_init_schedule_to (aTHX_ frame, cv, arg, items);
2000} 2105}
2001 2106
2002static void 2107static void
2003slf_init_cede (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items) 2108slf_init_cede (pTHX_ struct CoroSLF *frame, CV *cv, SV **arg, int items)
2004{ 2109{
2150 } 2255 }
2151 else 2256 else
2152 slf_argc = 0; 2257 slf_argc = 0;
2153 2258
2154 PL_op->op_ppaddr = pp_slf; 2259 PL_op->op_ppaddr = pp_slf;
2155 PL_op->op_type = OP_CUSTOM; /* maybe we should leave it at entersub? */ 2260 /*PL_op->op_type = OP_CUSTOM; /* we do behave like entersub still */
2156 2261
2157 PL_op = (OP *)&slf_restore; 2262 PL_op = (OP *)&slf_restore;
2158} 2263}
2159 2264
2160/*****************************************************************************/ 2265/*****************************************************************************/
2624 XSRETURN_EMPTY; 2729 XSRETURN_EMPTY;
2625} 2730}
2626 2731
2627/*****************************************************************************/ 2732/*****************************************************************************/
2628 2733
2734#if CORO_CLONE
2735# include "clone.c"
2736#endif
2737
2629MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_ 2738MODULE = Coro::State PACKAGE = Coro::State PREFIX = api_
2630 2739
2631PROTOTYPES: DISABLE 2740PROTOTYPES: DISABLE
2632 2741
2633BOOT: 2742BOOT:
2665 2774
2666 { 2775 {
2667 SV *slf = sv_2mortal (newSViv (PTR2IV (pp_slf))); 2776 SV *slf = sv_2mortal (newSViv (PTR2IV (pp_slf)));
2668 2777
2669 if (!PL_custom_op_names) PL_custom_op_names = newHV (); 2778 if (!PL_custom_op_names) PL_custom_op_names = newHV ();
2670 hv_store_ent (PL_custom_op_names, slf, 2779 hv_store_ent (PL_custom_op_names, slf, newSVpv ("coro_slf", 0), 0);
2671 newSVpv ("coro_slf", 0), 0);
2672 2780
2673 if (!PL_custom_op_descs) PL_custom_op_descs = newHV (); 2781 if (!PL_custom_op_descs) PL_custom_op_descs = newHV ();
2674 hv_store_ent (PL_custom_op_descs, slf, 2782 hv_store_ent (PL_custom_op_descs, slf, newSVpv ("coro schedule like function", 0), 0);
2675 newSVpv ("coro schedule like function", 0), 0);
2676 } 2783 }
2677 2784
2678 coroapi.ver = CORO_API_VERSION; 2785 coroapi.ver = CORO_API_VERSION;
2679 coroapi.rev = CORO_API_REVISION; 2786 coroapi.rev = CORO_API_REVISION;
2680 2787
2773void 2880void
2774_exit (int code) 2881_exit (int code)
2775 PROTOTYPE: $ 2882 PROTOTYPE: $
2776 CODE: 2883 CODE:
2777 _exit (code); 2884 _exit (code);
2885
2886#if CORO_CLONE
2887
2888SV *
2889clone (Coro::State coro)
2890 CODE:
2891{
2892 struct coro *ncoro = coro_clone (coro);
2893 MAGIC *mg;
2894 /* TODO: too much duplication */
2895 ncoro->hv = newHV ();
2896 mg = sv_magicext ((SV *)ncoro->hv, 0, CORO_MAGIC_type_state, &coro_state_vtbl, (char *)ncoro, 0);
2897 mg->mg_flags |= MGf_DUP;
2898 RETVAL = sv_bless (newRV_noinc ((SV *)ncoro->hv), SvSTASH (coro->hv));
2899}
2900 OUTPUT:
2901 RETVAL
2902
2903#endif
2778 2904
2779int 2905int
2780cctx_stacksize (int new_stacksize = 0) 2906cctx_stacksize (int new_stacksize = 0)
2781 PROTOTYPE: ;$ 2907 PROTOTYPE: ;$
2782 CODE: 2908 CODE:
2958 3084
2959BOOT: 3085BOOT:
2960{ 3086{
2961 int i; 3087 int i;
2962 3088
2963 av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE);
2964 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE); 3089 sv_pool_rss = coro_get_sv (aTHX_ "Coro::POOL_RSS" , TRUE);
2965 sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE); 3090 sv_pool_size = coro_get_sv (aTHX_ "Coro::POOL_SIZE" , TRUE);
2966 cv_coro_run = get_cv ( "Coro::_terminate", GV_ADD); 3091 cv_coro_run = get_cv ( "Coro::_terminate", GV_ADD);
2967 cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD); 3092 cv_coro_terminate = get_cv ( "Coro::terminate" , GV_ADD);
2968 coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current); 3093 coro_current = coro_get_sv (aTHX_ "Coro::current" , FALSE); SvREADONLY_on (coro_current);
3094 av_async_pool = coro_get_av (aTHX_ "Coro::async_pool", TRUE);
3095 av_destroy = coro_get_av (aTHX_ "Coro::destroy" , TRUE);
3096 sv_manager = coro_get_sv (aTHX_ "Coro::manager" , TRUE);
2969 3097
2970 sv_async_pool_idle = newSVpv ("[async pool idle]", 0); SvREADONLY_on (sv_async_pool_idle); 3098 sv_async_pool_idle = newSVpv ("[async pool idle]", 0); SvREADONLY_on (sv_async_pool_idle);
2971 sv_Coro = newSVpv ("Coro", 0); SvREADONLY_on (sv_Coro); 3099 sv_Coro = newSVpv ("Coro", 0); SvREADONLY_on (sv_Coro);
2972 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler); 3100 cv_pool_handler = get_cv ("Coro::pool_handler", GV_ADD); SvREADONLY_on (cv_pool_handler);
2973 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new); 3101 cv_coro_state_new = get_cv ("Coro::State::new", 0); SvREADONLY_on (cv_coro_state_new);
2986 3114
2987 { 3115 {
2988 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE); 3116 SV *sv = coro_get_sv (aTHX_ "Coro::API", TRUE);
2989 3117
2990 coroapi.schedule = api_schedule; 3118 coroapi.schedule = api_schedule;
3119 coroapi.schedule_to = api_schedule_to;
2991 coroapi.cede = api_cede; 3120 coroapi.cede = api_cede;
2992 coroapi.cede_notself = api_cede_notself; 3121 coroapi.cede_notself = api_cede_notself;
2993 coroapi.ready = api_ready; 3122 coroapi.ready = api_ready;
2994 coroapi.is_ready = api_is_ready; 3123 coroapi.is_ready = api_is_ready;
2995 coroapi.nready = coro_nready; 3124 coroapi.nready = coro_nready;
3000 SvREADONLY_on (sv); 3129 SvREADONLY_on (sv);
3001 } 3130 }
3002} 3131}
3003 3132
3004void 3133void
3134terminate (...)
3135 CODE:
3136 CORO_EXECUTE_SLF_XS (slf_init_terminate);
3137
3138void
3005schedule (...) 3139schedule (...)
3006 CODE: 3140 CODE:
3007 CORO_EXECUTE_SLF_XS (slf_init_schedule); 3141 CORO_EXECUTE_SLF_XS (slf_init_schedule);
3142
3143void
3144schedule_to (...)
3145 CODE:
3146 CORO_EXECUTE_SLF_XS (slf_init_schedule_to);
3147
3148void
3149cede_to (...)
3150 CODE:
3151 CORO_EXECUTE_SLF_XS (slf_init_cede_to);
3008 3152
3009void 3153void
3010cede (...) 3154cede (...)
3011 CODE: 3155 CODE:
3012 CORO_EXECUTE_SLF_XS (slf_init_cede); 3156 CORO_EXECUTE_SLF_XS (slf_init_cede);
3013 3157
3014void 3158void
3015cede_notself (...) 3159cede_notself (...)
3016 CODE: 3160 CODE:
3017 CORO_EXECUTE_SLF_XS (slf_init_cede_notself); 3161 CORO_EXECUTE_SLF_XS (slf_init_cede_notself);
3162
3163void
3164_cancel (Coro::State self)
3165 CODE:
3166 coro_state_destroy (aTHX_ self);
3167 coro_call_on_destroy (aTHX_ self);
3018 3168
3019void 3169void
3020_set_current (SV *current) 3170_set_current (SV *current)
3021 PROTOTYPE: $ 3171 PROTOTYPE: $
3022 CODE: 3172 CODE:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines