… | |
… | |
667 | CALLRUNOPS(aTHX); |
667 | CALLRUNOPS(aTHX); |
668 | |
668 | |
669 | abort (); |
669 | abort (); |
670 | } |
670 | } |
671 | |
671 | |
|
|
672 | /* never call directly, always through the coro_state_transfer global variable */ |
672 | static void |
673 | static void |
673 | transfer (pTHX_ struct coro *prev, struct coro *next, int flags) |
674 | transfer_impl (pTHX_ struct coro *prev, struct coro *next, int flags) |
674 | { |
675 | { |
675 | dSTACKLEVEL; |
676 | dSTACKLEVEL; |
676 | |
677 | |
677 | if (prev != next) |
678 | if (prev != next) |
678 | { |
679 | { |
… | |
… | |
771 | coro_mortal = 0; |
772 | coro_mortal = 0; |
772 | } |
773 | } |
773 | UNLOCK; |
774 | UNLOCK; |
774 | } |
775 | } |
775 | |
776 | |
|
|
777 | void (*coro_state_transfer)(pTHX_ struct coro *prev, struct coro *next, int flags) = transfer_impl; |
|
|
778 | |
776 | #define SV_CORO(sv,func) \ |
779 | #define SV_CORO(sv,func) \ |
777 | do { \ |
780 | do { \ |
778 | if (SvROK (sv)) \ |
781 | if (SvROK (sv)) \ |
779 | sv = SvRV (sv); \ |
782 | sv = SvRV (sv); \ |
780 | \ |
783 | \ |
… | |
… | |
792 | if (!SvOBJECT (sv) || SvSTASH (sv) != coro_state_stash) \ |
795 | if (!SvOBJECT (sv) || SvSTASH (sv) != coro_state_stash) \ |
793 | croak ("%s() -- %s is not (and contains not) a Coro::State object", func, # sv); \ |
796 | croak ("%s() -- %s is not (and contains not) a Coro::State object", func, # sv); \ |
794 | \ |
797 | \ |
795 | } while(0) |
798 | } while(0) |
796 | |
799 | |
797 | #define SvSTATE(sv) INT2PTR (struct coro *, SvIV (sv)) |
800 | #define SvSTATE(sv) INT2PTR (struct coro *, SvIVX (sv)) |
798 | |
801 | |
799 | static void |
802 | static void |
800 | api_transfer(pTHX_ SV *prev, SV *next, int flags) |
803 | api_transfer (pTHX_ SV *prev, SV *next, int flags) |
801 | { |
804 | { |
802 | SV_CORO (prev, "Coro::transfer"); |
805 | SV_CORO (prev, "Coro::transfer"); |
803 | SV_CORO (next, "Coro::transfer"); |
806 | SV_CORO (next, "Coro::transfer"); |
804 | |
807 | |
805 | transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags); |
808 | coro_state_transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags); |
806 | } |
809 | } |
807 | |
810 | |
808 | /** Coro ********************************************************************/ |
811 | /** Coro ********************************************************************/ |
809 | |
812 | |
810 | #define PRIO_MAX 3 |
813 | #define PRIO_MAX 3 |
… | |
… | |
814 | #define PRIO_IDLE -3 |
817 | #define PRIO_IDLE -3 |
815 | #define PRIO_MIN -4 |
818 | #define PRIO_MIN -4 |
816 | |
819 | |
817 | /* for Coro.pm */ |
820 | /* for Coro.pm */ |
818 | static GV *coro_current, *coro_idle; |
821 | static GV *coro_current, *coro_idle; |
819 | static AV *coro_ready[PRIO_MAX-PRIO_MIN+1]; |
822 | static AV *coro_ready [PRIO_MAX-PRIO_MIN+1]; |
820 | static int coro_nready; |
823 | static int coro_nready; |
821 | |
824 | |
822 | static void |
825 | static void |
823 | coro_enq (pTHX_ SV *sv) |
826 | coro_enq (pTHX_ SV *sv) |
824 | { |
827 | { |
… | |
… | |
847 | min_prio -= PRIO_MIN; |
850 | min_prio -= PRIO_MIN; |
848 | if (min_prio < 0) |
851 | if (min_prio < 0) |
849 | min_prio = 0; |
852 | min_prio = 0; |
850 | |
853 | |
851 | for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; ) |
854 | for (prio = PRIO_MAX - PRIO_MIN + 1; --prio >= min_prio; ) |
852 | if (av_len (coro_ready[prio]) >= 0) |
855 | if (AvFILLp (coro_ready [prio]) >= 0) |
853 | { |
856 | { |
854 | coro_nready--; |
857 | coro_nready--; |
855 | return av_shift (coro_ready[prio]); |
858 | return av_shift (coro_ready [prio]); |
856 | } |
859 | } |
857 | |
860 | |
858 | return 0; |
861 | return 0; |
859 | } |
862 | } |
860 | |
863 | |
… | |
… | |
894 | |
897 | |
895 | SV_CORO (next, "Coro::schedule"); |
898 | SV_CORO (next, "Coro::schedule"); |
896 | |
899 | |
897 | UNLOCK; |
900 | UNLOCK; |
898 | |
901 | |
899 | transfer (aTHX_ SvSTATE (prev), SvSTATE (next), |
902 | coro_state_transfer (aTHX_ SvSTATE (prev), SvSTATE (next), |
900 | TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK); |
903 | TRANSFER_SAVE_ALL | TRANSFER_LAZY_STACK); |
901 | } |
904 | } |
902 | |
905 | |
903 | static void |
906 | static void |
904 | api_cede (void) |
907 | api_cede (void) |
905 | { |
908 | { |
… | |
… | |
966 | PROTOTYPE: @ |
969 | PROTOTYPE: @ |
967 | CODE: |
970 | CODE: |
968 | PUTBACK; |
971 | PUTBACK; |
969 | SV_CORO (next, "Coro::transfer"); |
972 | SV_CORO (next, "Coro::transfer"); |
970 | SV_CORO (prev, "Coro::transfer"); |
973 | SV_CORO (prev, "Coro::transfer"); |
971 | transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags); |
974 | coro_state_transfer (aTHX_ SvSTATE (prev), SvSTATE (next), flags); |
972 | SPAGAIN; |
975 | SPAGAIN; |
973 | |
976 | |
974 | void |
977 | void |
975 | DESTROY(coro) |
978 | DESTROY(coro) |
976 | Coro::State coro |
979 | Coro::State coro |
… | |
… | |
1026 | av_fill (defav, items - 1); |
1029 | av_fill (defav, items - 1); |
1027 | while (items--) |
1030 | while (items--) |
1028 | av_store (defav, items, SvREFCNT_inc (ST(items))); |
1031 | av_store (defav, items, SvREFCNT_inc (ST(items))); |
1029 | |
1032 | |
1030 | sv = av_pop ((AV *)SvRV (yieldstack)); |
1033 | sv = av_pop ((AV *)SvRV (yieldstack)); |
1031 | prev = INT2PTR (struct coro *, SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0)))); |
1034 | prev = SvSTATE ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 0, 0))); |
1032 | next = INT2PTR (struct coro *, SvIV ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0)))); |
1035 | next = SvSTATE ((SV*)SvRV (*av_fetch ((AV *)SvRV (sv), 1, 0))); |
1033 | SvREFCNT_dec (sv); |
1036 | SvREFCNT_dec (sv); |
1034 | |
1037 | |
1035 | transfer (aTHX_ prev, next, 0); |
1038 | coro_state_transfer (aTHX_ prev, next, 0); |
1036 | |
1039 | |
1037 | MODULE = Coro::State PACKAGE = Coro |
1040 | MODULE = Coro::State PACKAGE = Coro |
1038 | |
1041 | |
1039 | BOOT: |
1042 | BOOT: |
1040 | { |
1043 | { |