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.132 by root, Fri Dec 29 13:03:05 2006 UTC vs.
Revision 1.134 by root, Thu Jan 4 23:49:27 2007 UTC

150 int valgrind_id; 150 int valgrind_id;
151#endif 151#endif
152} coro_cctx; 152} coro_cctx;
153 153
154enum { 154enum {
155 CF_RUNNING = 0x0001, /* coroutine is running */ 155 CF_RUNNING = 0x0001, /* coroutine is running */
156 CF_READY = 0x0002, /* coroutine is ready */ 156 CF_READY = 0x0002, /* coroutine is ready */
157 CF_NEW = 0x0004, /* ahs never been switched to */ 157 CF_NEW = 0x0004, /* has never been switched to */
158 CF_DESTROYED = 0x0008, /* coroutine data has been freed */
158}; 159};
159 160
160/* this is a structure representing a perl-level coroutine */ 161/* this is a structure representing a perl-level coroutine */
161struct coro { 162struct coro {
162 /* the c coroutine allocated to this perl coroutine, if any */ 163 /* the c coroutine allocated to this perl coroutine, if any */
471 472
472 /* free all temporaries */ 473 /* free all temporaries */
473 FREETMPS; 474 FREETMPS;
474 assert (PL_tmps_ix == -1); 475 assert (PL_tmps_ix == -1);
475 476
477 /* unwind all extra stacks */
476 POPSTACK_TO (PL_mainstack); 478 POPSTACK_TO (PL_mainstack);
479
480 /* unwind main stack */
481 dounwind (-1);
477 } 482 }
478 483
479 while (PL_curstackinfo->si_next) 484 while (PL_curstackinfo->si_next)
480 PL_curstackinfo = PL_curstackinfo->si_next; 485 PL_curstackinfo = PL_curstackinfo->si_next;
481 486
730 if (!prev->flags & CF_RUNNING) 735 if (!prev->flags & CF_RUNNING)
731 croak ("Coro::State::transfer called with non-running prev Coro::State, but can only transfer from running states"); 736 croak ("Coro::State::transfer called with non-running prev Coro::State, but can only transfer from running states");
732 737
733 if (next->flags & CF_RUNNING) 738 if (next->flags & CF_RUNNING)
734 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states"); 739 croak ("Coro::State::transfer called with running next Coro::State, but can only transfer to inactive states");
740
741 if (next->flags & CF_DESTROYED)
742 croak ("Coro::State::transfer called with destroyed next Coro::State, but can only transfer to inactive states");
735 743
736 prev->flags &= ~CF_RUNNING; 744 prev->flags &= ~CF_RUNNING;
737 next->flags |= CF_RUNNING; 745 next->flags |= CF_RUNNING;
738 746
739 LOCK; 747 LOCK;
783 PL_top_env = next->cctx->top_env; 791 PL_top_env = next->cctx->top_env;
784 coro_transfer (&prev__cctx->cctx, &next->cctx->cctx); 792 coro_transfer (&prev__cctx->cctx, &next->cctx->cctx);
785 } 793 }
786 794
787 free_coro_mortal (); 795 free_coro_mortal ();
788
789 UNLOCK; 796 UNLOCK;
790 } 797 }
791} 798}
792 799
793struct transfer_args 800struct transfer_args
795 struct coro *prev, *next; 802 struct coro *prev, *next;
796}; 803};
797 804
798#define TRANSFER(ta) transfer ((ta).prev, (ta).next) 805#define TRANSFER(ta) transfer ((ta).prev, (ta).next)
799 806
800static void 807static int
801coro_state_destroy (struct coro *coro) 808coro_state_destroy (struct coro *coro)
802{ 809{
803 if (coro->refcnt--) 810 if (coro->flags & CF_DESTROYED)
804 return; 811 return 0;
812
813 coro->flags |= CF_DESTROYED;
805 814
806 if (coro->mainstack && coro->mainstack != main_mainstack) 815 if (coro->mainstack && coro->mainstack != main_mainstack)
807 { 816 {
817 assert (!(coro->flags & CF_RUNNING));
818
808 struct coro temp; 819 struct coro temp;
809 Zero (&temp, 1, struct coro); 820 Zero (&temp, 1, struct coro);
810 temp.save = CORO_SAVE_ALL; 821 temp.save = CORO_SAVE_ALL;
811 822
812 if (coro->flags & CF_RUNNING) 823 if (coro->flags & CF_RUNNING)
822 coro->mainstack = 0; 833 coro->mainstack = 0;
823 } 834 }
824 835
825 cctx_destroy (coro->cctx); 836 cctx_destroy (coro->cctx);
826 SvREFCNT_dec (coro->args); 837 SvREFCNT_dec (coro->args);
827 Safefree (coro); 838
839 return 1;
828} 840}
829 841
830static int 842static int
831coro_state_clear (pTHX_ SV *sv, MAGIC *mg) 843coro_state_free (pTHX_ SV *sv, MAGIC *mg)
832{ 844{
833 struct coro *coro = (struct coro *)mg->mg_ptr; 845 struct coro *coro = (struct coro *)mg->mg_ptr;
834 mg->mg_ptr = 0; 846 mg->mg_ptr = 0;
835 847
848 if (--coro->refcnt < 0)
849 {
836 coro_state_destroy (coro); 850 coro_state_destroy (coro);
851 Safefree (coro);
852 }
837 853
838 return 0; 854 return 0;
839} 855}
840 856
841static int 857static int
848 return 0; 864 return 0;
849} 865}
850 866
851static MGVTBL coro_state_vtbl = { 867static MGVTBL coro_state_vtbl = {
852 0, 0, 0, 0, 868 0, 0, 0, 0,
853 coro_state_clear, 869 coro_state_free,
854 0, 870 0,
855#ifdef MGf_DUP 871#ifdef MGf_DUP
856 coro_state_dup, 872 coro_state_dup,
857#else 873#else
858# define MGf_DUP 0 874# define MGf_DUP 0
978} 994}
979 995
980static void 996static void
981prepare_schedule (struct transfer_args *ta) 997prepare_schedule (struct transfer_args *ta)
982{ 998{
983 SV *prev, *next; 999 SV *prev_sv, *next_sv;
984 1000
985 for (;;) 1001 for (;;)
986 { 1002 {
987 LOCK; 1003 LOCK;
988 next = coro_deq (PRIO_MIN); 1004 next_sv = coro_deq (PRIO_MIN);
989 UNLOCK; 1005 UNLOCK;
990 1006
1007 /* nothing to schedule: call the idle handler */
991 if (next) 1008 if (!next_sv)
992 break;
993
994 { 1009 {
995 dSP; 1010 dSP;
996 1011
997 ENTER; 1012 ENTER;
998 SAVETMPS; 1013 SAVETMPS;
999 1014
1000 PUSHMARK (SP); 1015 PUSHMARK (SP);
1001 PUTBACK; 1016 PUTBACK;
1002 call_sv (get_sv ("Coro::idle", FALSE), G_DISCARD); 1017 call_sv (get_sv ("Coro::idle", FALSE), G_DISCARD);
1003 1018
1004 FREETMPS; 1019 FREETMPS;
1005 LEAVE; 1020 LEAVE;
1021 continue;
1006 } 1022 }
1007 }
1008 1023
1009 prev = SvRV (coro_current); 1024 ta->next = SvSTATE (next_sv);
1010 SvRV_set (coro_current, next); 1025
1026 /* cannot transfer to destroyed coros, skip and look for next */
1027 if (ta->next->flags & CF_DESTROYED)
1028 {
1029 SvREFCNT_dec (next_sv);
1030 continue;
1031 }
1032
1033 break;
1034 }
1011 1035
1012 /* free this only after the transfer */ 1036 /* free this only after the transfer */
1037 prev_sv = SvRV (coro_current);
1038 SvRV_set (coro_current, next_sv);
1039 ta->prev = SvSTATE (prev_sv);
1040
1041 assert (ta->next->flags & CF_READY);
1042 ta->next->flags &= ~CF_READY;
1043
1013 LOCK; 1044 LOCK;
1014 free_coro_mortal (); 1045 free_coro_mortal ();
1046 coro_mortal = prev_sv;
1015 UNLOCK; 1047 UNLOCK;
1016 coro_mortal = prev;
1017
1018 assert (!SvROK(prev));//D
1019 assert (!SvROK(next));//D
1020
1021 ta->prev = SvSTATE (prev);
1022 ta->next = SvSTATE (next);
1023
1024 assert (ta->next->flags & CF_READY);
1025 ta->next->flags &= ~CF_READY;
1026} 1048}
1027 1049
1028static void 1050static void
1029prepare_cede (struct transfer_args *ta) 1051prepare_cede (struct transfer_args *ta)
1030{ 1052{
1184 1206
1185 BARRIER; 1207 BARRIER;
1186 TRANSFER (ta); 1208 TRANSFER (ta);
1187} 1209}
1188 1210
1189void 1211bool
1190_clone_state_from (SV *dst, SV *src) 1212_destroy (SV *coro_sv)
1191 CODE: 1213 CODE:
1192{ 1214 RETVAL = coro_state_destroy (SvSTATE (coro_sv));
1193 struct coro *coro_src = SvSTATE (src); 1215 OUTPUT:
1194 1216 RETVAL
1195 sv_unmagic (SvRV (dst), PERL_MAGIC_ext);
1196
1197 ++coro_src->refcnt;
1198 sv_magicext (SvRV (dst), 0, PERL_MAGIC_ext, &coro_state_vtbl, (char *)coro_src, 0)->mg_flags |= MGf_DUP;
1199}
1200 1217
1201void 1218void
1202_exit (code) 1219_exit (code)
1203 int code 1220 int code
1204 PROTOTYPE: $ 1221 PROTOTYPE: $

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines