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.134 by root, Thu Jan 4 23:49:27 2007 UTC vs.
Revision 1.138 by root, Sun Jan 14 20:49:45 2007 UTC

112#else 112#else
113# define LOCK (void)0 113# define LOCK (void)0
114# define UNLOCK (void)0 114# define UNLOCK (void)0
115#endif 115#endif
116 116
117/* helper storage struct for Coro::AIO */
117struct io_state 118struct io_state
118{ 119{
119 int errorno; 120 int errorno;
120 I32 laststype; 121 I32 laststype;
121 int laststatval; 122 int laststatval;
184 int prio; 185 int prio;
185}; 186};
186 187
187typedef struct coro *Coro__State; 188typedef struct coro *Coro__State;
188typedef struct coro *Coro__State_or_hashref; 189typedef struct coro *Coro__State_or_hashref;
190
191/** Coro ********************************************************************/
192
193#define PRIO_MAX 3
194#define PRIO_HIGH 1
195#define PRIO_NORMAL 0
196#define PRIO_LOW -1
197#define PRIO_IDLE -3
198#define PRIO_MIN -4
199
200/* for Coro.pm */
201static SV *coro_current;
202static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
203static int coro_nready;
204
205/** lowlevel stuff **********************************************************/
189 206
190static AV * 207static AV *
191coro_clone_padlist (CV *cv) 208coro_clone_padlist (CV *cv)
192{ 209{
193 AV *padlist = CvPADLIST (cv); 210 AV *padlist = CvPADLIST (cv);
302 av_extend (av, AvMAX (av) + 1); 319 av_extend (av, AvMAX (av) + 1);
303 320
304 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv); 321 AvARRAY (av)[++AvFILLp (av)] = (SV *)CvPADLIST (cv);
305} 322}
306 323
324/** load & save, init *******************************************************/
325
307#define SB do { 326#define SB do {
308#define SE } while (0) 327#define SE } while (0)
309 328
310#define REPLACE_SV(sv,val) SB SvREFCNT_dec (sv); (sv) = (val); (val) = 0; SE 329#define REPLACE_SV(sv,val) SB SvREFCNT_dec (sv); (sv) = (val); (val) = 0; SE
311 330
503#if !PERL_VERSION_ATLEAST (5,9,0) 522#if !PERL_VERSION_ATLEAST (5,9,0)
504 Safefree (PL_retstack); 523 Safefree (PL_retstack);
505#endif 524#endif
506} 525}
507 526
527/** coroutine stack handling ************************************************/
528
508static void 529static void
509setup_coro (struct coro *coro) 530setup_coro (struct coro *coro)
510{ 531{
511 /* 532 /*
512 * emulate part of the perl startup here. 533 * emulate part of the perl startup here.
703 724
704 ++cctx_idle; 725 ++cctx_idle;
705 cctx->next = cctx_first; 726 cctx->next = cctx_first;
706 cctx_first = cctx; 727 cctx_first = cctx;
707} 728}
729
730/** coroutine switching *****************************************************/
708 731
709/* never call directly, always through the coro_state_transfer global variable */ 732/* never call directly, always through the coro_state_transfer global variable */
710static void NOINLINE 733static void NOINLINE
711transfer (struct coro *prev, struct coro *next) 734transfer (struct coro *prev, struct coro *next)
712{ 735{
802 struct coro *prev, *next; 825 struct coro *prev, *next;
803}; 826};
804 827
805#define TRANSFER(ta) transfer ((ta).prev, (ta).next) 828#define TRANSFER(ta) transfer ((ta).prev, (ta).next)
806 829
830/** high level stuff ********************************************************/
831
807static int 832static int
808coro_state_destroy (struct coro *coro) 833coro_state_destroy (struct coro *coro)
809{ 834{
810 if (coro->flags & CF_DESTROYED) 835 if (coro->flags & CF_DESTROYED)
811 return 0; 836 return 0;
812 837
813 coro->flags |= CF_DESTROYED; 838 coro->flags |= CF_DESTROYED;
839
840 if (coro->flags & CF_READY)
841 {
842 /* reduce nready, as destroying a ready coro effectively unreadies it */
843 /* alternative: look through all ready queues and remove it */
844 LOCK;
845 --coro_nready;
846 UNLOCK;
847 }
848 else
849 coro->flags |= CF_READY; /* make sure it is NOT put into the readyqueue */
814 850
815 if (coro->mainstack && coro->mainstack != main_mainstack) 851 if (coro->mainstack && coro->mainstack != main_mainstack)
816 { 852 {
817 assert (!(coro->flags & CF_RUNNING)); 853 assert (!(coro->flags & CF_RUNNING));
818 854
925 return old_save; 961 return old_save;
926} 962}
927 963
928/** Coro ********************************************************************/ 964/** Coro ********************************************************************/
929 965
930#define PRIO_MAX 3
931#define PRIO_HIGH 1
932#define PRIO_NORMAL 0
933#define PRIO_LOW -1
934#define PRIO_IDLE -3
935#define PRIO_MIN -4
936
937/* for Coro.pm */
938static SV *coro_current;
939static AV *coro_ready [PRIO_MAX-PRIO_MIN+1];
940static int coro_nready;
941
942static void 966static void
943coro_enq (SV *coro_sv) 967coro_enq (SV *coro_sv)
944{ 968{
945 av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv); 969 av_push (coro_ready [SvSTATE (coro_sv)->prio - PRIO_MIN], coro_sv);
946 coro_nready++;
947} 970}
948 971
949static SV * 972static SV *
950coro_deq (int min_prio) 973coro_deq (int min_prio)
951{ 974{
955 if (min_prio < 0) 978 if (min_prio < 0)
956 min_prio = 0; 979 min_prio = 0;
957 980
958 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; ) 981 for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; )
959 if (AvFILLp (coro_ready [prio]) >= 0) 982 if (AvFILLp (coro_ready [prio]) >= 0)
960 {
961 coro_nready--;
962 return av_shift (coro_ready [prio]); 983 return av_shift (coro_ready [prio]);
963 }
964 984
965 return 0; 985 return 0;
966} 986}
967 987
968static int 988static int
980 1000
981 coro->flags |= CF_READY; 1001 coro->flags |= CF_READY;
982 1002
983 LOCK; 1003 LOCK;
984 coro_enq (SvREFCNT_inc (coro_sv)); 1004 coro_enq (SvREFCNT_inc (coro_sv));
1005 ++coro_nready;
985 UNLOCK; 1006 UNLOCK;
986 1007
987 return 1; 1008 return 1;
988} 1009}
989 1010
1000 1021
1001 for (;;) 1022 for (;;)
1002 { 1023 {
1003 LOCK; 1024 LOCK;
1004 next_sv = coro_deq (PRIO_MIN); 1025 next_sv = coro_deq (PRIO_MIN);
1005 UNLOCK;
1006 1026
1007 /* nothing to schedule: call the idle handler */ 1027 /* nothing to schedule: call the idle handler */
1008 if (!next_sv) 1028 if (!next_sv)
1009 { 1029 {
1030 UNLOCK;
1010 dSP; 1031 dSP;
1011 1032
1012 ENTER; 1033 ENTER;
1013 SAVETMPS; 1034 SAVETMPS;
1014 1035
1024 ta->next = SvSTATE (next_sv); 1045 ta->next = SvSTATE (next_sv);
1025 1046
1026 /* cannot transfer to destroyed coros, skip and look for next */ 1047 /* cannot transfer to destroyed coros, skip and look for next */
1027 if (ta->next->flags & CF_DESTROYED) 1048 if (ta->next->flags & CF_DESTROYED)
1028 { 1049 {
1050 UNLOCK;
1029 SvREFCNT_dec (next_sv); 1051 SvREFCNT_dec (next_sv);
1052 /* coro_nready is already taken care of by destroy */
1030 continue; 1053 continue;
1031 } 1054 }
1032 1055
1056 --coro_nready;
1057 UNLOCK;
1033 break; 1058 break;
1034 } 1059 }
1035 1060
1036 /* free this only after the transfer */ 1061 /* free this only after the transfer */
1037 prev_sv = SvRV (coro_current); 1062 prev_sv = SvRV (coro_current);
1204 break; 1229 break;
1205 } 1230 }
1206 1231
1207 BARRIER; 1232 BARRIER;
1208 TRANSFER (ta); 1233 TRANSFER (ta);
1234
1235 if (GIMME_V != G_VOID && ta.next != ta.prev)
1236 XSRETURN_YES;
1209} 1237}
1210 1238
1211bool 1239bool
1212_destroy (SV *coro_sv) 1240_destroy (SV *coro_sv)
1213 CODE: 1241 CODE:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines