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.210 by root, Wed Oct 10 03:24:40 2007 UTC vs.
Revision 1.211 by root, Wed Oct 10 03:37:58 2007 UTC

161/* async_pool helper stuff */ 161/* async_pool helper stuff */
162static SV *sv_pool_rss; 162static SV *sv_pool_rss;
163static SV *sv_pool_size; 163static SV *sv_pool_size;
164static AV *av_async_pool; 164static AV *av_async_pool;
165 165
166static struct coro_cctx *cctx_first[3]; /* index by GIMME_V type, void, scalar, array */ 166static struct coro_cctx *cctx_first;
167static int cctx_count, cctx_idle[3]; 167static int cctx_count, cctx_idle;
168 168
169enum { 169enum {
170 CC_MAPPED = 0x01, 170 CC_MAPPED = 0x01,
171 CC_NOREUSE = 0x02, /* throw this away after tracing */ 171 CC_NOREUSE = 0x02, /* throw this away after tracing */
172 CC_TRACE = 0x04, 172 CC_TRACE = 0x04,
217 217
218/* this is a structure representing a perl-level coroutine */ 218/* this is a structure representing a perl-level coroutine */
219struct coro { 219struct coro {
220 /* the c coroutine allocated to this perl coroutine, if any */ 220 /* the c coroutine allocated to this perl coroutine, if any */
221 coro_cctx *cctx; 221 coro_cctx *cctx;
222 int gimme;
223 222
224 /* process data */ 223 /* process data */
225 AV *mainstack; 224 AV *mainstack;
226 perl_slots *slot; /* basically the saved sp */ 225 perl_slots *slot; /* basically the saved sp */
227 226
712 XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv)))); 711 XPUSHs (sv_2mortal (av_shift (GvAV (PL_defgv))));
713 PUTBACK; 712 PUTBACK;
714 PL_op = (OP *)&myop; 713 PL_op = (OP *)&myop;
715 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX); 714 PL_op = PL_ppaddr[OP_ENTERSUB](aTHX);
716 SPAGAIN; 715 SPAGAIN;
717
718 /*
719 * now its very tricky. the "tail" of the next transfer might end up
720 * either in a new cctx, or an existing one.
721 * in case of an existing one we have to take care of whatever
722 * entersub and transfer do to the perl stack.
723 */
724 ENTER;
725 EXTEND (SP, 4);
726 PUSHs ((SV *)0); /* items */
727 PUSHs ((SV *)0); /* ix, set_stacklevel */
728 PUSHs ((SV *)(sp - PL_stack_base + 1)); /* ax */
729 PUSHs ((SV *)0); /* again */
730 PUTBACK;
731 } 716 }
732 717
733 /* this newly created coroutine might be run on an existing cctx which most 718 /* this newly created coroutine might be run on an existing cctx which most
734 * likely was suspended in set_stacklevel, called from entersub. 719 * likely was suspended in set_stacklevel, called from entersub.
735 * set_stacklevl doesn't do anything on return, but entersub does LEAVE, 720 * set_stacklevl doesn't do anything on return, but entersub does LEAVE,
1039 1024
1040/* wether this cctx should be destructed */ 1025/* wether this cctx should be destructed */
1041#define CCTX_EXPIRED(cctx) ((cctx)->ssize < coro_stacksize || ((cctx)->flags & CC_NOREUSE)) 1026#define CCTX_EXPIRED(cctx) ((cctx)->ssize < coro_stacksize || ((cctx)->flags & CC_NOREUSE))
1042 1027
1043static coro_cctx * 1028static coro_cctx *
1044cctx_get (pTHX_ int gimme) 1029cctx_get (pTHX)
1045{ 1030{
1046 while (expect_true (cctx_first[gimme])) 1031 while (expect_true (cctx_first))
1047 { 1032 {
1048 coro_cctx *cctx = cctx_first[gimme]; 1033 coro_cctx *cctx = cctx_first;
1049 cctx_first[gimme] = cctx->next; 1034 cctx_first = cctx->next;
1050 --cctx_idle[gimme]; 1035 --cctx_idle;
1051 1036
1052 if (expect_true (!CCTX_EXPIRED (cctx))) 1037 if (expect_true (!CCTX_EXPIRED (cctx)))
1053 return cctx; 1038 return cctx;
1054 1039
1055 cctx_destroy (cctx); 1040 cctx_destroy (cctx);
1056 } 1041 }
1057 1042
1058 assert (!gimme);
1059 return cctx_new (); 1043 return cctx_new ();
1060} 1044}
1061 1045
1062static void 1046static void
1063cctx_put (coro_cctx *cctx, int gimme) 1047cctx_put (coro_cctx *cctx)
1064{ 1048{
1065 /* free another cctx if overlimit */ 1049 /* free another cctx if overlimit */
1066 if (expect_false (cctx_idle[gimme] >= MAX_IDLE_CCTX)) 1050 if (expect_false (cctx_idle >= MAX_IDLE_CCTX))
1067 { 1051 {
1068 coro_cctx *first = cctx_first[gimme]; 1052 coro_cctx *first = cctx_first;
1069 cctx_first[gimme] = first->next; 1053 cctx_first = first->next;
1070 --cctx_idle[gimme]; 1054 --cctx_idle;
1071 1055
1072 cctx_destroy (first); 1056 cctx_destroy (first);
1073 } 1057 }
1074 1058
1075 ++cctx_idle[gimme]; 1059 ++cctx_idle;
1076 cctx->next = cctx_first[gimme]; 1060 cctx->next = cctx_first;
1077 cctx_first[gimme] = cctx; 1061 cctx_first = cctx;
1078} 1062}
1079 1063
1080/** coroutine switching *****************************************************/ 1064/** coroutine switching *****************************************************/
1081 1065
1082static void 1066static void
1161 1145
1162 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */ 1146 /* if the cctx is about to be destroyed we need to make sure we won't see it in cctx_get */
1163 /* without this the next cctx_get might destroy the prev__cctx while still in use */ 1147 /* without this the next cctx_get might destroy the prev__cctx while still in use */
1164 if (expect_false (CCTX_EXPIRED (prev__cctx))) 1148 if (expect_false (CCTX_EXPIRED (prev__cctx)))
1165 if (!next->cctx) 1149 if (!next->cctx)
1166 next->cctx = cctx_get (aTHX_ next->gimme); 1150 next->cctx = cctx_get (aTHX);
1167 1151
1168 cctx_put (prev__cctx, prev->gimme); 1152 cctx_put (prev__cctx);
1169 } 1153 }
1170 1154
1171 ++next->usecount; 1155 ++next->usecount;
1172 1156
1173 if (expect_true (!next->cctx)) 1157 if (expect_true (!next->cctx))
1174 next->cctx = cctx_get (aTHX_ next->gimme); 1158 next->cctx = cctx_get (aTHX);
1175 1159
1176 if (expect_false (prev__cctx != next->cctx)) 1160 if (expect_false (prev__cctx != next->cctx))
1177 { 1161 {
1178 prev__cctx->top_env = PL_top_env; 1162 prev__cctx->top_env = PL_top_env;
1179 PL_top_env = next->cctx->top_env; 1163 PL_top_env = next->cctx->top_env;
1661 RETVAL 1645 RETVAL
1662 1646
1663int 1647int
1664cctx_idle () 1648cctx_idle ()
1665 CODE: 1649 CODE:
1666 RETVAL = cctx_idle[0] + cctx_idle[1] + cctx_idle[2]; 1650 RETVAL = cctx_idle;
1667 OUTPUT: 1651 OUTPUT:
1668 RETVAL 1652 RETVAL
1669 1653
1670void 1654void
1671list () 1655list ()
1705 eval_sv (coderef, 0); 1689 eval_sv (coderef, 0);
1706 else 1690 else
1707 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD); 1691 call_sv (coderef, G_KEEPERR | G_EVAL | G_VOID | G_DISCARD);
1708 1692
1709 POPSTACK; 1693 POPSTACK;
1694 SPAGAIN;
1710 FREETMPS; 1695 FREETMPS;
1711 LEAVE; 1696 LEAVE;
1712 PUTBACK; 1697 PUTBACK;
1713 } 1698 }
1714 1699

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines