public void initialize(RubyProc block) { RubyNode.notDesignedForCompilation(); final RubyFiber finalFiber = this; final RubyProc finalBlock = block; new Thread( new Runnable() { @Override public void run() { fiberManager.registerFiber(finalFiber); try { try { final Object arg = finalFiber.waitForResume(); final Object result = finalBlock.rootCall(arg); finalFiber.lastResumedByFiber.resume(finalFiber, result); } catch (FiberExitException e) { // Naturally exit the thread on catching this } } finally { fiberManager.unregisterFiber(finalFiber); } } }) .start(); }
/** * 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(); }
/** Given a reference, produce either {@code nil} or the object. . */ public static Object instanceOrNil(Object object) { RubyNode.notDesignedForCompilation(); if (object == null) { return NilPlaceholder.INSTANCE; } else { return object; } }
/** * 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)); }
public void shutdown() { RubyNode.notDesignedForCompilation(); messageQueue.add(new FiberExitMessage()); }
public static boolean isNil(Object block) { RubyNode.notDesignedForCompilation(); return block == NilPlaceholder.INSTANCE || block instanceof RubyNilClass; }
@Override public boolean equals(Object other) { RubyNode.notDesignedForCompilation(); return other instanceof RubyNilClass || other instanceof NilPlaceholder; }
public static boolean assignableTo(RubyClass thisClass, RubyModule otherClass) { RubyNode.notDesignedForCompilation(); return includesModule(thisClass, otherClass); }