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