protected IRubyObject resumeOrTransfer(ThreadContext context, IRubyObject arg, boolean transfer) { CoroutineFiber current = (CoroutineFiber) context.getFiber(); slot = arg; try { switch (state) { case SUSPENDED_YIELD: if (transfer) { current.state = CoroutineFiberState.SUSPENDED_TRANSFER; } else { current.state = CoroutineFiberState.SUSPENDED_RESUME; lastFiber = (CoroutineFiber) context.getFiber(); } state = CoroutineFiberState.RUNNING; context.getRuntime().getThreadService().setCurrentContext(context); context.setThread(context.getThread()); Coroutine.yieldTo(coro); break; case SUSPENDED_TRANSFER: if (!transfer) { throw context.getRuntime().newFiberError("double resume"); } current.state = CoroutineFiberState.SUSPENDED_TRANSFER; state = CoroutineFiberState.RUNNING; context.getRuntime().getThreadService().setCurrentContext(context); context.setThread(context.getThread()); Coroutine.yieldTo(coro); break; case FINISHED: throw context.getRuntime().newFiberError("dead fiber called"); default: throw context.getRuntime().newFiberError("fiber in an invalid state: " + state); } } catch (OutOfMemoryError oome) { if (oome.getMessage().equals("unable to create new native thread")) { throw context.runtime.newThreadError("too many threads, can't create a new Fiber"); } throw oome; } // back from fiber, poll events and proceed out of resume context.pollThreadEvents(); return slot; }
public IRubyObject yield(ThreadContext context, IRubyObject arg) { assert !root; if (lastFiber.state != CoroutineFiberState.SUSPENDED_RESUME) { if (lastFiber.state == CoroutineFiberState.SUSPENDED_TRANSFER) { throw context.getRuntime().newFiberError("a Fiber that was transferred to cannot yield"); } throw context .getRuntime() .newFiberError("invalid state of last Fiber at yield: " + lastFiber.state); } slot = arg; state = CoroutineFiberState.SUSPENDED_YIELD; lastFiber.state = CoroutineFiberState.RUNNING; context.getRuntime().getThreadService().setCurrentContext(lastFiber.context); Object o = lastFiber.context; lastFiber.context.setThread(context.getThread()); Coroutine.yieldTo(lastFiber.coro); // back from fiber, poll events and proceed out of resume context.pollThreadEvents(); return slot; }