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.399 by root, Thu May 12 23:24:28 2011 UTC vs.
Revision 1.403 by root, Sun May 22 20:13:33 2011 UTC

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
209enum 210enum
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 */
975static int 976static int
976coro_sigelem_get (pTHX_ SV *sv, MAGIC *mg) 977coro_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,");
1695coro_call_on_destroy (pTHX_ struct coro *coro); 1696coro_call_on_destroy (pTHX_ struct coro *coro);
1696 1697
1697static void 1698static void
1698coro_state_destroy (pTHX_ struct coro *coro) 1699coro_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
1737static int 1738static int
1738coro_state_free (pTHX_ SV *sv, MAGIC *mg) 1739coro_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
2058static void 2059static void
2059coro_push_on_destroy (aTHX_ struct coro *coro, SV *cb) 2060coro_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
2145static void 2146static 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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines