/** * Send the Java thread that represents this fiber to sleep until it recieves a resume or exit * message. On entry, assumes that the GIL is not held. On exit, holding the GIL. */ public Object waitForResume() { RubyNode.notDesignedForCompilation(); FiberMessage message = null; do { try { // TODO(cs) what is a suitable timeout? message = messageQueue.poll(1, TimeUnit.SECONDS); } catch (InterruptedException e) { // Poll again } } while (message == null); if (message instanceof FiberExitMessage) { throw new FiberExitException(); } final FiberResumeMessage resumeMessage = (FiberResumeMessage) message; threadManager.enterGlobalLock(resumeMessage.getThread()); fiberManager.setCurrentFiber(this); lastResumedByFiber = resumeMessage.getSendingFiber(); return resumeMessage.getArg(); }
/** * Send a message to a fiber by posting into a message queue. Doesn't explicitly notify the Java * thread (although the queue implementation may) and doesn't wait for the message to be received. * On entry, assumes the the GIL is held. On exit, not holding the GIL. */ public void resume(RubyFiber sendingFiber, Object... args) { RubyNode.notDesignedForCompilation(); Object arg; if (args.length == 0) { arg = getContext().getCoreLibrary().getNilObject(); } else if (args.length == 1) { arg = args[0]; } else { arg = RubyArray.fromObjects(getContext().getCoreLibrary().getArrayClass(), args); } final RubyThread runningThread = threadManager.leaveGlobalLock(); messageQueue.add(new FiberResumeMessage(runningThread, sendingFiber, arg)); }