- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- Location:
- EcnlProtoTool/trunk/mruby-1.3.0
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/mruby-1.3.0/mrbgems/mruby-fiber/src/fiber.c
r321 r331 1 #include "mruby.h"2 #include "mruby/array.h"3 #include "mruby/class.h"4 #include "mruby/proc.h"1 #include <mruby.h> 2 #include <mruby/array.h> 3 #include <mruby/class.h> 4 #include <mruby/proc.h> 5 5 6 6 #define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o)) … … 8 8 #define FIBER_STACK_INIT_SIZE 64 9 9 #define FIBER_CI_INIT_SIZE 8 10 #define CI_ACC_RESUMED -3 10 11 11 12 /* … … 74 75 mrb_get_args(mrb, "&", &blk); 75 76 77 if (f->cxt) { 78 mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice"); 79 } 76 80 if (mrb_nil_p(blk)) { 77 81 mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block"); … … 82 86 } 83 87 84 f->cxt= (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));85 * f->cxt= mrb_context_zero;86 c = f->cxt;88 c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); 89 *c = mrb_context_zero; 90 f->cxt = c; 87 91 88 92 /* initialize VM stack */ … … 156 160 #define MARK_CONTEXT_MODIFY(c) (c)->ci->target_class = NULL 157 161 158 static mrb_value 159 fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume) 160 { 161 struct mrb_context *c = fiber_check(mrb, self); 162 static void 163 fiber_check_cfunc(mrb_state *mrb, struct mrb_context *c) 164 { 162 165 mrb_callinfo *ci; 163 166 … … 167 170 } 168 171 } 172 } 173 174 static void 175 fiber_switch_context(mrb_state *mrb, struct mrb_context *c) 176 { 177 if (mrb->c->fib) { 178 mrb_write_barrier(mrb, (struct RBasic*)mrb->c->fib); 179 } 180 c->status = MRB_FIBER_RUNNING; 181 mrb->c = c; 182 } 183 184 static mrb_value 185 fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume, mrb_bool vmexec) 186 { 187 struct mrb_context *c = fiber_check(mrb, self); 188 struct mrb_context *old_c = mrb->c; 189 mrb_value value; 190 191 fiber_check_cfunc(mrb, c); 169 192 if (resume && c->status == MRB_FIBER_TRANSFERRED) { 170 193 mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber"); 171 194 } 172 if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUM ING) {173 mrb_raise(mrb, E_FIBER_ERROR, "double resume ");195 if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) { 196 mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)"); 174 197 } 175 198 if (c->status == MRB_FIBER_TERMINATED) { 176 199 mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber"); 177 200 } 178 mrb->c->status = resume ? MRB_FIBER_RESUM ING: MRB_FIBER_TRANSFERRED;201 mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED; 179 202 c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c); 180 203 if (c->status == MRB_FIBER_CREATED) { 181 mrb_value *b = c->stack+1; 182 mrb_value *e = b + len; 183 204 mrb_value *b, *e; 205 206 if (len >= c->stend - c->stack) { 207 mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber"); 208 } 209 b = c->stack+1; 210 e = b + len; 184 211 while (b<e) { 185 212 *b++ = *a++; 186 213 } 187 214 c->cibase->argc = len; 188 if (c->prev->fib) 189 mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); 190 mrb_write_barrier(mrb, (struct RBasic*)c->fib); 191 c->status = MRB_FIBER_RUNNING; 192 mrb->c = c; 193 215 value = c->stack[0] = c->ci->proc->env->stack[0]; 216 } 217 else { 218 value = fiber_result(mrb, a, len); 219 } 220 fiber_switch_context(mrb, c); 221 222 if (vmexec) { 223 c->vmexec = TRUE; 224 value = mrb_vm_exec(mrb, c->ci[-1].proc, c->ci->pc); 225 mrb->c = old_c; 226 } 227 else { 194 228 MARK_CONTEXT_MODIFY(c); 195 return c->ci->proc->env->stack[0]; 196 } 197 MARK_CONTEXT_MODIFY(c); 198 if (c->prev->fib) 199 mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); 200 mrb_write_barrier(mrb, (struct RBasic*)c->fib); 201 c->status = MRB_FIBER_RUNNING; 202 mrb->c = c; 203 return fiber_result(mrb, a, len); 229 } 230 return value; 204 231 } 205 232 … … 224 251 mrb_value *a; 225 252 mrb_int len; 253 mrb_bool vmexec = FALSE; 226 254 227 255 mrb_get_args(mrb, "*", &a, &len); 228 return fiber_switch(mrb, self, len, a, TRUE); 256 if (mrb->c->ci->acc < 0) { 257 vmexec = TRUE; 258 } 259 return fiber_switch(mrb, self, len, a, TRUE, vmexec); 229 260 } 230 261 … … 233 264 mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a) 234 265 { 235 return fiber_switch(mrb, fib, len, a, TRUE );266 return fiber_switch(mrb, fib, len, a, TRUE, TRUE); 236 267 } 237 268 … … 281 312 mrb_int len; 282 313 314 fiber_check_cfunc(mrb, mrb->c); 283 315 mrb_get_args(mrb, "*", &a, &len); 284 316 285 317 if (c == mrb->root_c) { 286 318 mrb->c->status = MRB_FIBER_TRANSFERRED; 287 mrb->c = c; 288 c->status = MRB_FIBER_RUNNING; 319 fiber_switch_context(mrb, c); 289 320 MARK_CONTEXT_MODIFY(c); 290 mrb_write_barrier(mrb, (struct RBasic*)c->fib);291 321 return fiber_result(mrb, a, len); 292 322 } … … 296 326 } 297 327 298 return fiber_switch(mrb, self, len, a, FALSE );328 return fiber_switch(mrb, self, len, a, FALSE, FALSE); 299 329 } 300 330 … … 305 335 { 306 336 struct mrb_context *c = mrb->c; 307 mrb_callinfo *ci; 308 309 for (ci = c->ci; ci >= c->cibase; ci--) { 310 if (ci->acc < 0) { 311 mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary"); 312 } 313 } 337 314 338 if (!c->prev) { 315 339 mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber"); 316 340 } 317 341 342 fiber_check_cfunc(mrb, c); 318 343 c->prev->status = MRB_FIBER_RUNNING; 319 344 c->status = MRB_FIBER_SUSPENDED; 320 mrb->c = c->prev;345 fiber_switch_context(mrb, c->prev); 321 346 c->prev = NULL; 347 if (c->vmexec) { 348 c->vmexec = FALSE; 349 mrb->c->ci->acc = CI_ACC_RESUMED; 350 } 322 351 MARK_CONTEXT_MODIFY(mrb->c); 323 mrb_write_barrier(mrb, (struct RBasic*)c->fib);324 352 return fiber_result(mrb, a, len); 325 353 } … … 333 361 * processing at this point when <code>resume</code> is called next. 334 362 * Any arguments passed to the next <code>resume</code> will be the 335 * value that this <code>Fiber.yield</code> expression evaluates to. 363 * 364 * mruby limitation: Fiber resume/yield cannot cross C function boundary. 365 * thus you cannot yield from #initialize which is called by mrb_funcall(). 336 366 */ 337 367 static mrb_value
Note:
See TracChangeset
for help on using the changeset viewer.