… | |
… | |
13 | #include "XSUB.h" |
13 | #include "XSUB.h" |
14 | #include "perliol.h" |
14 | #include "perliol.h" |
15 | |
15 | |
16 | #include "schmorp.h" |
16 | #include "schmorp.h" |
17 | |
17 | |
|
|
18 | #include <stddef.h> |
18 | #include <stdio.h> |
19 | #include <stdio.h> |
19 | #include <errno.h> |
20 | #include <errno.h> |
20 | #include <assert.h> |
21 | #include <assert.h> |
21 | |
22 | |
22 | #ifndef SVs_PADSTALE |
23 | #ifndef SVs_PADSTALE |
… | |
… | |
209 | enum |
210 | enum |
210 | { |
211 | { |
211 | CF_RUNNING = 0x0001, /* coroutine is running */ |
212 | CF_RUNNING = 0x0001, /* coroutine is running */ |
212 | CF_READY = 0x0002, /* coroutine is ready */ |
213 | CF_READY = 0x0002, /* coroutine is ready */ |
213 | CF_NEW = 0x0004, /* has never been switched to */ |
214 | CF_NEW = 0x0004, /* has never been switched to */ |
214 | CF_DESTROYED = 0x0008, /* coroutine data has been freed */ |
215 | CF_ZOMBIE = 0x0008, /* coroutine data has been freed */ |
215 | CF_SUSPENDED = 0x0010, /* coroutine can't be scheduled */ |
216 | CF_SUSPENDED = 0x0010, /* coroutine can't be scheduled */ |
216 | CF_NOCANCEL = 0x0020, /* cannot cancel, set slf_frame.data to 1 (hackish) */ |
217 | CF_NOCANCEL = 0x0020, /* cannot cancel, set slf_frame.data to 1 (hackish) */ |
217 | }; |
218 | }; |
218 | |
219 | |
219 | /* the structure where most of the perl state is stored, overlaid on the cxstack */ |
220 | /* the structure where most of the perl state is stored, overlaid on the cxstack */ |
… | |
… | |
496 | MAGIC *mg; |
497 | MAGIC *mg; |
497 | |
498 | |
498 | if (SvROK (coro)) |
499 | if (SvROK (coro)) |
499 | coro = SvRV (coro); |
500 | coro = SvRV (coro); |
500 | |
501 | |
501 | mg = SvSTATEhv_p (coro); |
502 | mg = SvSTATEhv_p (aTHX_ coro); |
502 | if (!mg) |
503 | if (!mg) |
503 | croak ("Coro::State object required"); |
504 | croak ("Coro::State object required"); |
504 | |
505 | |
505 | return (struct coro *)mg->mg_ptr; |
506 | return (struct coro *)mg->mg_ptr; |
506 | } |
507 | } |
… | |
… | |
967 | #endif |
968 | #endif |
968 | |
969 | |
969 | /* |
970 | /* |
970 | * This overrides the default magic get method of %SIG elements. |
971 | * This overrides the default magic get method of %SIG elements. |
971 | * The original one doesn't provide for reading back of PL_diehook/PL_warnhook |
972 | * The original one doesn't provide for reading back of PL_diehook/PL_warnhook |
972 | * and instead of trying to save and restore the hash elements, we just provide |
973 | * and instead of trying to save and restore the hash elements (extremely slow), |
973 | * readback here. |
974 | * we just provide our own readback here. |
974 | */ |
975 | */ |
975 | static int |
976 | static int |
976 | coro_sigelem_get (pTHX_ SV *sv, MAGIC *mg) |
977 | coro_sigelem_get (pTHX_ SV *sv, MAGIC *mg) |
977 | { |
978 | { |
978 | const char *s = MgPV_nolen_const (mg); |
979 | const char *s = MgPV_nolen_const (mg); |
… | |
… | |
1086 | PL_parser = 0; |
1087 | PL_parser = 0; |
1087 | #endif |
1088 | #endif |
1088 | PL_hints = 0; |
1089 | PL_hints = 0; |
1089 | |
1090 | |
1090 | /* recreate the die/warn hooks */ |
1091 | /* recreate the die/warn hooks */ |
1091 | PL_diehook = 0; SvSetMagicSV (*hv_fetch (hv_sig, "__DIE__" , sizeof ("__DIE__" ) - 1, 1), rv_diehook ); |
1092 | PL_diehook = SvREFCNT_inc (rv_diehook); |
1092 | PL_warnhook = 0; SvSetMagicSV (*hv_fetch (hv_sig, "__WARN__", sizeof ("__WARN__") - 1, 1), rv_warnhook); |
1093 | PL_warnhook = SvREFCNT_inc (rv_warnhook); |
1093 | |
1094 | |
1094 | GvSV (PL_defgv) = newSV (0); |
1095 | GvSV (PL_defgv) = newSV (0); |
1095 | GvAV (PL_defgv) = coro->args; coro->args = 0; |
1096 | GvAV (PL_defgv) = coro->args; coro->args = 0; |
1096 | GvSV (PL_errgv) = newSV (0); |
1097 | GvSV (PL_errgv) = newSV (0); |
1097 | GvSV (irsgv) = newSVpvn ("\n", 1); sv_magic (GvSV (irsgv), (SV *)irsgv, PERL_MAGIC_sv, "/", 0); |
1098 | GvSV (irsgv) = newSVpvn ("\n", 1); sv_magic (GvSV (irsgv), (SV *)irsgv, PERL_MAGIC_sv, "/", 0); |
… | |
… | |
1594 | if (expect_true (prev != next)) |
1595 | if (expect_true (prev != next)) |
1595 | { |
1596 | { |
1596 | if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) |
1597 | if (expect_false (!(prev->flags & (CF_RUNNING | CF_NEW)))) |
1597 | croak ("Coro::State::transfer called with a blocked prev Coro::State, but can only transfer from running or new states,"); |
1598 | croak ("Coro::State::transfer called with a blocked prev Coro::State, but can only transfer from running or new states,"); |
1598 | |
1599 | |
1599 | if (expect_false (next->flags & (CF_RUNNING | CF_DESTROYED | CF_SUSPENDED))) |
1600 | if (expect_false (next->flags & (CF_RUNNING | CF_ZOMBIE | CF_SUSPENDED))) |
1600 | croak ("Coro::State::transfer called with running, destroyed or suspended next Coro::State, but can only transfer to inactive states,"); |
1601 | croak ("Coro::State::transfer called with running, destroyed or suspended next Coro::State, but can only transfer to inactive states,"); |
1601 | |
1602 | |
1602 | #if !PERL_VERSION_ATLEAST (5,10,0) |
1603 | #if !PERL_VERSION_ATLEAST (5,10,0) |
1603 | if (expect_false (PL_lex_state != LEX_NOTPARSING)) |
1604 | if (expect_false (PL_lex_state != LEX_NOTPARSING)) |
1604 | croak ("Coro::State::transfer called while parsing, but this is not supported in your perl version,"); |
1605 | croak ("Coro::State::transfer called while parsing, but this is not supported in your perl version,"); |
… | |
… | |
1695 | coro_call_on_destroy (pTHX_ struct coro *coro); |
1696 | coro_call_on_destroy (pTHX_ struct coro *coro); |
1696 | |
1697 | |
1697 | static void |
1698 | static void |
1698 | coro_state_destroy (pTHX_ struct coro *coro) |
1699 | coro_state_destroy (pTHX_ struct coro *coro) |
1699 | { |
1700 | { |
1700 | if (coro->flags & CF_DESTROYED) |
1701 | if (coro->flags & CF_ZOMBIE) |
1701 | return; |
1702 | return; |
1702 | |
1703 | |
1703 | slf_destroy (aTHX_ coro); |
1704 | slf_destroy (aTHX_ coro); |
1704 | |
1705 | |
1705 | coro->flags |= CF_DESTROYED; |
1706 | coro->flags |= CF_ZOMBIE; |
1706 | |
1707 | |
1707 | if (coro->flags & CF_READY) |
1708 | if (coro->flags & CF_READY) |
1708 | { |
1709 | { |
1709 | /* reduce nready, as destroying a ready coro effectively unreadies it */ |
1710 | /* reduce nready, as destroying a ready coro effectively unreadies it */ |
1710 | /* alternative: look through all ready queues and remove the coro */ |
1711 | /* alternative: look through all ready queues and remove the coro */ |
… | |
… | |
1727 | SvREFCNT_dec (coro->startcv); |
1728 | SvREFCNT_dec (coro->startcv); |
1728 | SvREFCNT_dec (coro->args); |
1729 | SvREFCNT_dec (coro->args); |
1729 | SvREFCNT_dec (coro->swap_sv); |
1730 | SvREFCNT_dec (coro->swap_sv); |
1730 | SvREFCNT_dec (CORO_THROW); |
1731 | SvREFCNT_dec (CORO_THROW); |
1731 | |
1732 | |
1732 | coro_call_on_destroy (coro); |
1733 | coro_call_on_destroy (aTHX_ coro); |
1733 | |
1734 | |
1734 | /* more destruction mayhem in coro_state_free */ |
1735 | /* more destruction mayhem in coro_state_free */ |
1735 | } |
1736 | } |
1736 | |
1737 | |
1737 | static int |
1738 | static int |
1738 | coro_state_free (pTHX_ SV *sv, MAGIC *mg) |
1739 | coro_state_free (pTHX_ SV *sv, MAGIC *mg) |
1739 | { |
1740 | { |
1740 | struct coro *coro = (struct coro *)mg->mg_ptr; |
1741 | struct coro *coro = (struct coro *)mg->mg_ptr; |
1741 | mg->mg_ptr = 0; |
1742 | mg->mg_ptr = 0; |
1742 | |
1743 | |
1743 | coro_state_destroy (coro); |
1744 | coro_state_destroy (aTHX_ coro); |
1744 | SvREFCNT_dec (coro->on_destroy); |
1745 | SvREFCNT_dec (coro->on_destroy); |
1745 | SvREFCNT_dec (coro->status); |
1746 | SvREFCNT_dec (coro->status); |
1746 | |
1747 | |
1747 | Safefree (coro); |
1748 | Safefree (coro); |
1748 | |
1749 | |
… | |
… | |
1889 | struct coro *next = coro_deq (aTHX); |
1890 | struct coro *next = coro_deq (aTHX); |
1890 | |
1891 | |
1891 | if (expect_true (next)) |
1892 | if (expect_true (next)) |
1892 | { |
1893 | { |
1893 | /* cannot transfer to destroyed coros, skip and look for next */ |
1894 | /* cannot transfer to destroyed coros, skip and look for next */ |
1894 | if (expect_false (next->flags & (CF_DESTROYED | CF_SUSPENDED))) |
1895 | if (expect_false (next->flags & (CF_ZOMBIE | CF_SUSPENDED))) |
1895 | SvREFCNT_dec (next->hv); /* coro_nready has already been taken care of by destroy */ |
1896 | SvREFCNT_dec (next->hv); /* coro_nready has already been taken care of by destroy */ |
1896 | else |
1897 | else |
1897 | { |
1898 | { |
1898 | next->flags &= ~CF_READY; |
1899 | next->flags &= ~CF_READY; |
1899 | --coro_nready; |
1900 | --coro_nready; |
… | |
… | |
2054 | PUTBACK; |
2055 | PUTBACK; |
2055 | } |
2056 | } |
2056 | } |
2057 | } |
2057 | |
2058 | |
2058 | static void |
2059 | static void |
2059 | coro_push_on_destroy (aTHX_ struct coro *coro, SV *cb) |
2060 | coro_push_on_destroy (pTHX_ struct coro *coro, SV *cb) |
2060 | { |
2061 | { |
2061 | if (!coro->on_destroy) |
2062 | if (!coro->on_destroy) |
2062 | coro->on_destroy = newAV (); |
2063 | coro->on_destroy = newAV (); |
2063 | |
2064 | |
2064 | av_push (coro->on_destroy, cb); |
2065 | av_push (coro->on_destroy, cb); |
… | |
… | |
2078 | if (!coro->status) |
2079 | if (!coro->status) |
2079 | return 1; |
2080 | return 1; |
2080 | |
2081 | |
2081 | frame->destroy = 0; |
2082 | frame->destroy = 0; |
2082 | |
2083 | |
2083 | coro_push_av (coro->status, GIMME_V); |
2084 | coro_push_av (aTHX_ coro->status, GIMME_V); |
2084 | |
2085 | |
2085 | SvREFCNT_dec ((SV *)coro->hv); |
2086 | SvREFCNT_dec ((SV *)coro->hv); |
2086 | |
2087 | |
2087 | return 0; |
2088 | return 0; |
2088 | } |
2089 | } |
… | |
… | |
2135 | coro_push_av (aTHX_ coro->status, G_ARRAY); |
2136 | coro_push_av (aTHX_ coro->status, G_ARRAY); |
2136 | SPAGAIN; |
2137 | SPAGAIN; |
2137 | } |
2138 | } |
2138 | |
2139 | |
2139 | PUTBACK; |
2140 | PUTBACK; |
2140 | call_sv (sv_2mortal (cb), G_VOID | G_DISCARD); |
2141 | call_sv (cb, G_VOID | G_DISCARD); |
2141 | } |
2142 | } |
2142 | } |
2143 | } |
2143 | } |
2144 | } |
2144 | |
2145 | |
2145 | static void |
2146 | static void |
… | |
… | |
3547 | PROTOTYPE: $ |
3548 | PROTOTYPE: $ |
3548 | ALIAS: |
3549 | ALIAS: |
3549 | is_ready = CF_READY |
3550 | is_ready = CF_READY |
3550 | is_running = CF_RUNNING |
3551 | is_running = CF_RUNNING |
3551 | is_new = CF_NEW |
3552 | is_new = CF_NEW |
3552 | is_destroyed = CF_DESTROYED |
3553 | is_destroyed = CF_ZOMBIE |
|
|
3554 | is_zombie = CF_ZOMBIE |
3553 | is_suspended = CF_SUSPENDED |
3555 | is_suspended = CF_SUSPENDED |
3554 | CODE: |
3556 | CODE: |
3555 | RETVAL = boolSV (coro->flags & ix); |
3557 | RETVAL = boolSV (coro->flags & ix); |
3556 | OUTPUT: |
3558 | OUTPUT: |
3557 | RETVAL |
3559 | RETVAL |