ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Coro/State.xs
Revision: 1.2
Committed: Sun Jul 15 02:35:52 2001 UTC (22 years, 10 months ago) by root
Branch: MAIN
Changes since 1.1: +51 -42 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 struct coro {
6 U8 dowarn;
7
8 PERL_SI *curstackinfo;
9 AV *curstack;
10 AV *mainstack;
11 SV **stack_sp;
12 OP *op;
13 SV **curpad;
14 SV **stack_base;
15 SV **stack_max;
16 SV **tmps_stack;
17 I32 tmps_floor;
18 I32 tmps_ix;
19 I32 tmps_max;
20 I32 *markstack;
21 I32 *markstack_ptr;
22 I32 *markstack_max;
23 I32 *scopestack;
24 I32 scopestack_ix;
25 I32 scopestack_max;
26 ANY *savestack;
27 I32 savestack_ix;
28 I32 savestack_max;
29 OP **retstack;
30 I32 retstack_ix;
31 I32 retstack_max;
32 COP *curcop;
33
34 AV *defav;
35
36 SV *proc;
37 };
38
39 typedef struct coro *Coro__State;
40 typedef struct coro *Coro__State_or_hashref;
41
42 #define SAVE(c) \
43 c->dowarn = PL_dowarn; \
44 c->curstackinfo = PL_curstackinfo; \
45 c->curstack = PL_curstack; \
46 c->mainstack = PL_mainstack; \
47 c->stack_sp = PL_stack_sp; \
48 c->op = PL_op; \
49 c->curpad = PL_curpad; \
50 c->stack_base = PL_stack_base; \
51 c->stack_max = PL_stack_max; \
52 c->tmps_stack = PL_tmps_stack; \
53 c->tmps_floor = PL_tmps_floor; \
54 c->tmps_ix = PL_tmps_ix; \
55 c->tmps_max = PL_tmps_max; \
56 c->markstack = PL_markstack; \
57 c->markstack_ptr = PL_markstack_ptr; \
58 c->markstack_max = PL_markstack_max; \
59 c->scopestack = PL_scopestack; \
60 c->scopestack_ix = PL_scopestack_ix; \
61 c->scopestack_max = PL_scopestack_max;\
62 c->savestack = PL_savestack; \
63 c->savestack_ix = PL_savestack_ix; \
64 c->savestack_max = PL_savestack_max; \
65 c->retstack = PL_retstack; \
66 c->retstack_ix = PL_retstack_ix; \
67 c->retstack_max = PL_retstack_max; \
68 c->curcop = PL_curcop; \
69 c->defav = GvAV (PL_defgv);
70
71 #define LOAD(c) \
72 PL_dowarn = c->dowarn; \
73 PL_curstackinfo = c->curstackinfo; \
74 PL_curstack = c->curstack; \
75 PL_mainstack = c->mainstack; \
76 PL_stack_sp = c->stack_sp; \
77 PL_op = c->op; \
78 PL_curpad = c->curpad; \
79 PL_stack_base = c->stack_base; \
80 PL_stack_max = c->stack_max; \
81 PL_tmps_stack = c->tmps_stack; \
82 PL_tmps_floor = c->tmps_floor; \
83 PL_tmps_ix = c->tmps_ix; \
84 PL_tmps_max = c->tmps_max; \
85 PL_markstack = c->markstack; \
86 PL_markstack_ptr = c->markstack_ptr; \
87 PL_markstack_max = c->markstack_max; \
88 PL_scopestack = c->scopestack; \
89 PL_scopestack_ix = c->scopestack_ix; \
90 PL_scopestack_max = c->scopestack_max;\
91 PL_savestack = c->savestack; \
92 PL_savestack_ix = c->savestack_ix; \
93 PL_savestack_max = c->savestack_max; \
94 PL_retstack = c->retstack; \
95 PL_retstack_ix = c->retstack_ix; \
96 PL_retstack_max = c->retstack_max; \
97 PL_curcop = c->curcop; \
98 GvAV (PL_defgv) = c->defav;
99
100 /* this is an EXACT copy of S_nuke_stacks in perl.c, which is unfortunately static */
101 STATIC void
102 S_nuke_stacks(pTHX)
103 {
104 while (PL_curstackinfo->si_next)
105 PL_curstackinfo = PL_curstackinfo->si_next;
106 while (PL_curstackinfo) {
107 PERL_SI *p = PL_curstackinfo->si_prev;
108 /* curstackinfo->si_stack got nuked by sv_free_arenas() */
109 Safefree(PL_curstackinfo->si_cxstack);
110 Safefree(PL_curstackinfo);
111 PL_curstackinfo = p;
112 }
113 Safefree(PL_tmps_stack);
114 Safefree(PL_markstack);
115 Safefree(PL_scopestack);
116 Safefree(PL_savestack);
117 Safefree(PL_retstack);
118 }
119
120 MODULE = Coro::State PACKAGE = Coro::State
121
122 PROTOTYPES: ENABLE
123
124 Coro::State
125 newprocess(proc)
126 SV * proc
127 PROTOTYPE: &
128 CODE:
129 Coro__State coro;
130
131 New (0, coro, 1, struct coro);
132
133 coro->mainstack = 0; /* actual work is done inside transfer */
134 coro->proc = SvREFCNT_inc (proc);
135
136 RETVAL = coro;
137 OUTPUT:
138 RETVAL
139
140 void
141 transfer(prev,next)
142 Coro::State_or_hashref prev
143 Coro::State_or_hashref next
144 CODE:
145
146 if (prev != next)
147 {
148 PUTBACK;
149 SAVE (prev);
150
151 /*
152 * this could be done in newprocess which would to
153 * extremely elegant and fast (just PUTBACK/SAVE/LOAD/SPAGAIN)
154 * code here, but lazy allocation of stacks has also
155 * some virtues and the overhead of the if() is nil.
156 */
157 if (next->mainstack)
158 {
159 LOAD (next);
160 next->mainstack = 0; /* unnecessary but much cleaner */
161 SPAGAIN;
162 }
163 else
164 {
165 /*
166 * emulate part of the perl startup here.
167 */
168 UNOP myop;
169
170 init_stacks ();
171 PL_op = (OP *)&myop;
172 /*PL_curcop = 0;*/
173 GvAV (PL_defgv) = newAV ();
174
175 SPAGAIN;
176 Zero(&myop, 1, UNOP);
177 myop.op_next = Nullop;
178 myop.op_flags = OPf_WANT_VOID;
179
180 EXTEND (SP,1);
181 PUSHs (next->proc);
182
183 PUTBACK;
184 /*
185 * the next line is slightly wrong, as PL_op->op_next
186 * is actually being executed so we skip the first op
187 * that doens't matter, though, since it is only
188 * pp_nextstate and we never return...
189 */
190 PL_op = Perl_pp_entersub(aTHX);
191 SPAGAIN;
192
193 ENTER;
194 }
195 }
196
197 void
198 DESTROY(coro)
199 Coro::State coro
200 CODE:
201
202 if (coro->mainstack)
203 {
204 struct coro temp;
205
206 PUTBACK;
207 SAVE((&temp));
208 LOAD(coro);
209
210 S_nuke_stacks ();
211 SvREFCNT_dec ((SV *)GvAV (PL_defgv));
212
213 LOAD((&temp));
214 SPAGAIN;
215 }
216
217 SvREFCNT_dec (coro->proc);
218 Safefree (coro);
219
220