… | |
… | |
110 | static AV *main_mainstack; /* used to differentiate between $main and others */ |
110 | static AV *main_mainstack; /* used to differentiate between $main and others */ |
111 | static HV *coro_state_stash; |
111 | static HV *coro_state_stash; |
112 | static SV *ucoro_state_sv; |
112 | static SV *ucoro_state_sv; |
113 | static U32 ucoro_state_hash; |
113 | static U32 ucoro_state_hash; |
114 | static HV *padlist_cache; |
114 | static HV *padlist_cache; |
|
|
115 | |
|
|
116 | /* for Coro.pm */ |
|
|
117 | static GV *coro_current, *coro_idle; |
|
|
118 | static AV *coro_ready; |
115 | |
119 | |
116 | /* mostly copied from op.c:cv_clone2 */ |
120 | /* mostly copied from op.c:cv_clone2 */ |
117 | STATIC AV * |
121 | STATIC AV * |
118 | clone_padlist (AV *protopadlist) |
122 | clone_padlist (AV *protopadlist) |
119 | { |
123 | { |
… | |
… | |
748 | } |
752 | } |
749 | |
753 | |
750 | next->cursp = stacklevel; |
754 | next->cursp = stacklevel; |
751 | } |
755 | } |
752 | |
756 | |
|
|
757 | static struct coro * |
|
|
758 | sv_to_coro (SV *arg, const char *funcname, const char *varname) |
|
|
759 | { |
|
|
760 | if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVHV) |
|
|
761 | { |
|
|
762 | HE *he = hv_fetch_ent((HV *)SvRV(arg), ucoro_state_sv, 0, ucoro_state_hash); |
|
|
763 | |
|
|
764 | if (!he) |
|
|
765 | croak ("%s() -- %s is a hashref but lacks the " UCORO_STATE " key", funcname, varname); |
|
|
766 | |
|
|
767 | arg = HeVAL(he); |
|
|
768 | } |
|
|
769 | |
|
|
770 | /* must also be changed inside Coro::Cont::yield */ |
|
|
771 | if (SvROK(arg) && SvSTASH(SvRV(arg)) == coro_state_stash) |
|
|
772 | return (struct coro *) SvIV((SV*)SvRV(arg)); |
|
|
773 | else |
|
|
774 | croak ("%s() -- %s is not (and contains not) a Coro::State object", funcname, varname); |
|
|
775 | } |
|
|
776 | |
753 | MODULE = Coro::State PACKAGE = Coro::State |
777 | MODULE = Coro::State PACKAGE = Coro::State |
754 | |
778 | |
755 | PROTOTYPES: ENABLE |
779 | PROTOTYPES: ENABLE |
756 | |
780 | |
757 | BOOT: |
781 | BOOT: |
… | |
… | |
790 | RETVAL = coro; |
814 | RETVAL = coro; |
791 | OUTPUT: |
815 | OUTPUT: |
792 | RETVAL |
816 | RETVAL |
793 | |
817 | |
794 | void |
818 | void |
795 | transfer(prev, next, flags = TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK) |
819 | transfer(prev, next, flags) |
796 | Coro::State_or_hashref prev |
820 | Coro::State_or_hashref prev |
797 | Coro::State_or_hashref next |
821 | Coro::State_or_hashref next |
798 | int flags |
822 | int flags |
799 | PROTOTYPE: @ |
823 | PROTOTYPE: @ |
800 | CODE: |
824 | CODE: |
… | |
… | |
845 | exit (code); |
869 | exit (code); |
846 | #endif |
870 | #endif |
847 | |
871 | |
848 | MODULE = Coro::State PACKAGE = Coro::Cont |
872 | MODULE = Coro::State PACKAGE = Coro::Cont |
849 | |
873 | |
850 | # this is slightly dirty |
874 | # this is slightly dirty (should expose a c-level api) |
851 | |
875 | |
852 | void |
876 | void |
853 | yield(...) |
877 | yield(...) |
854 | PROTOTYPE: @ |
878 | PROTOTYPE: @ |
855 | CODE: |
879 | CODE: |
… | |
… | |
873 | next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0))); |
897 | next = (struct coro *)SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0))); |
874 | SvREFCNT_dec (sv); |
898 | SvREFCNT_dec (sv); |
875 | |
899 | |
876 | transfer(aTHX_ prev, next, 0); |
900 | transfer(aTHX_ prev, next, 0); |
877 | |
901 | |
|
|
902 | MODULE = Coro::State PACKAGE = Coro |
|
|
903 | |
|
|
904 | # this is slightly dirty (should expose a c-level api) |
|
|
905 | |
|
|
906 | BOOT: |
|
|
907 | { |
|
|
908 | coro_current = gv_fetchpv ("Coro::current", TRUE, SVt_PV); |
|
|
909 | coro_ready = newAV (); |
|
|
910 | coro_idle = gv_fetchpv ("Coro::idle" , TRUE, SVt_PV); |
|
|
911 | } |
|
|
912 | |
|
|
913 | void |
|
|
914 | ready(self) |
|
|
915 | SV * self |
|
|
916 | CODE: |
|
|
917 | av_push (coro_ready, SvREFCNT_inc (self)); |
|
|
918 | |
|
|
919 | void |
|
|
920 | schedule(...) |
|
|
921 | ALIAS: |
|
|
922 | cede = 1 |
|
|
923 | CODE: |
|
|
924 | SV *prev = GvSV (coro_current); |
|
|
925 | SV *next = av_shift (coro_ready); |
|
|
926 | |
|
|
927 | if (next == &PL_sv_undef) |
|
|
928 | next = SvREFCNT_inc (GvSV (coro_idle)); |
|
|
929 | |
|
|
930 | if (ix) |
|
|
931 | av_push (coro_ready, SvREFCNT_inc (prev)); |
|
|
932 | |
|
|
933 | GvSV (coro_current) = SvREFCNT_inc (next); |
|
|
934 | transfer (sv_to_coro (prev, "Coro::schedule", "current coroutine"), |
|
|
935 | sv_to_coro (next, "Coro::schedule", "next coroutine"), |
|
|
936 | TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK); |
|
|
937 | SvREFCNT_dec (next); |
|
|
938 | SvREFCNT_dec (prev); |
|
|
939 | |