Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: EPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Eclipse Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/epl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2002 Jason Voegele <jason@jvoegele.com> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2004 Thomas E Enebo <enebo@acm.org> Copyright (C) 2004-2005 Charles O Nutter <headius@headius.com> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the EPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the EPL, the GPL or the LGPL. END LICENSE BLOCK ***
  
  package org.jruby;
  
  import java.util.Vector;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import java.util.Set;
  
  import static org.jruby.runtime.Visibility.*;
  
  
  import static org.jruby.CompatVersion.*;
Implementation of Ruby's Thread class. Each Ruby thread is mapped to an underlying Java Virtual Machine thread.

Thread encapsulates the behavior of a thread of execution, including the main thread of the Ruby script. In the descriptions that follow, the parameter aSymbol refers to a symbol, which is either a quoted string or a Symbol (such as :name). Note: For CVS history, see ThreadClass.java.

  
  @JRubyClass(name="Thread")
  public class RubyThread extends RubyObject implements ExecutionContext {
  
     private static final Logger LOG = LoggerFactory.getLogger("RubyThread");

    
The thread-like think that is actually executing
 
     private ThreadLike threadImpl;

    
Normal thread-local variables
 
     private transient Map<IRubyObjectIRubyObjectthreadLocalVariables;

    
Context-local variables, internal-ish thread locals
 
     private final Map<ObjectIRubyObjectcontextVariables = new WeakHashMap<ObjectIRubyObject>();

    
Whether this thread should try to abort the program on exception
 
     private boolean abortOnException;

    
The final value resulting from the thread's execution
 
     private IRubyObject finalResult;

    
The exception currently being raised out of the thread. We reference it here to continue propagating it while handling thread shutdown logic and abort_on_exception.
 
     private RaiseException exitingException;

    
The ThreadGroup to which this thread belongs
 
     private RubyThreadGroup threadGroup;

    
Per-thread "current exception"
 
     private IRubyObject errorInfo;

    
Weak reference to the ThreadContext for this thread.
 
     private volatile WeakReference<ThreadContextcontextRef;
 
     private static final boolean DEBUG = false;
     private int RUBY_MIN_THREAD_PRIORITY = -3;
     private int RUBY_MAX_THREAD_PRIORITY = 3;

    
Thread statuses
 
     public static enum Status { 
         RUN, SLEEP, ABORTING, DEAD;
         
         public final ByteList bytes;
         
         Status() {
              = new ByteList(toString().toLowerCase().getBytes(.));
         }
     }

    
Current status in an atomic reference
 
     private final AtomicReference<Statusstatus = new AtomicReference<Status>(.);

    
Mail slot for cross-thread events
 
     private final AtomicReference<ThreadService.Eventmail = new AtomicReference<ThreadService.Event>();

    
The current task blocking a thread, to allow interrupting it in an appropriate way
 
     private volatile BlockingTask currentBlockingTask;

    
The list of locks this thread currently holds, so they can be released on exit
 
     private final List<LockheldLocks = new Vector<Lock>();

    
Whether or not this thread has been disposed of
 
     private volatile boolean disposed = false;

    
The thread's initial priority, for use in thread pooled mode
 
     private int initialPriority;
 
     protected RubyThread(Ruby runtimeRubyClass type) {
         super(runtimetype);
 
          = runtime.getNil();
          = runtime.getNil();
     }
     
     public RubyThread(Ruby runtimeRubyClass klassThreadedRunnable runnable) {
         this(runtimeklass);
         
         startWith(runnable);
     }
 
     public void receiveMail(ThreadService.Event event) {
         synchronized (this) {
             // if we're already aborting, we can receive no further mail
             if (.get() == .return;
 
             // FIXME: this was not checking null before, but maybe it should
             .set(event);
             switch (event.type) {
             case :
                 .set(.);
             }
 
             // If this thread is sleeping or stopped, wake it
             notify();
         }
 
         // interrupt the target thread in case it's blocking or waiting
         // WARNING: We no longer interrupt the target thread, since this usually means
         // interrupting IO and with NIO that means the channel is no longer usable.
         // We either need a new way to handle waking a target thread that's waiting
         // on IO, or we need to accept that we can't wake such threads and must wait
         // for them to complete their operation.
         //threadImpl.interrupt();
 
         // new interrupt, to hopefully wake it out of any blocking IO
         this.interrupt();
 
     }
 
     public void checkMail(ThreadContext context) {
         ThreadService.Event myEvent = .getAndSet(null);
         
         if (myEvent != null) {
             switch (myEvent.type) {
             case :
                 receivedAnException(contextmyEvent.exception);
             case :
                 throwThreadKill();
             }
         }
     }
 
     public IRubyObject getErrorInfo() {
         return ;
     }
 
     public IRubyObject setErrorInfo(IRubyObject errorInfo) {
         this. = errorInfo;
         return errorInfo;
     }
 
     public void setContext(ThreadContext context) {
         this. = new WeakReference<ThreadContext>(context);
     }
 
     public ThreadContext getContext() {
         return  == null ? null : .get();
     }
 
 
     public Thread getNativeThread() {
         return .nativeThread();
     }

    
Perform pre-execution tasks once the native thread is running, but we have not yet called the Ruby code for the thread.
 
     public void beforeStart() {
         // store initial priority, for restoring pooled threads to normal
         this. = Thread.currentThread().getPriority();
     }

    
Dispose of the current thread by tidying up connections to other stuff
 
     public void dispose() {
         if (return;
         
         synchronized (this) {
             if (return;
             
              = true;
 
             // remove from parent thread group
             .remove(this);
 
             // unlock all locked locks
             unlockAll();
 
             // reset thread priority to initial if pooling
             if (..load()) {
                 .setPriority();
             }
 
             // mark thread as DEAD
             beDead();
         }
 
         // unregister from runtime's ThreadService
         getRuntime().getThreadService().unregisterThread(this);
     }
    
     public static RubyClass createThreadClass(Ruby runtime) {
         // FIXME: In order for Thread to play well with the standard 'new' behavior,
         // it must provide an allocator that can create empty object instances which
         // initialize then fills with appropriate data.
         RubyClass threadClass = runtime.defineClass("Thread"runtime.getObject(), .);
         runtime.setThread(threadClass);
 
         threadClass.index = .;
         threadClass.setReifiedClass(RubyThread.class);
 
         threadClass.defineAnnotatedMethods(RubyThread.class);
 
         RubyThread rubyThread = new RubyThread(runtimethreadClass);
         // TODO: need to isolate the "current" thread from class creation
         rubyThread.threadImpl = new NativeThread(rubyThread, Thread.currentThread());
         runtime.getThreadService().setMainThread(Thread.currentThread(), rubyThread);
         
         // set to default thread group
         runtime.getDefaultThreadGroup().addDirectly(rubyThread);
         
         threadClass.setMarshal(.);
         
         if (runtime.is2_0()) {
             // set up Thread::Backtrace::Location class
             RubyClass backtrace = threadClass.defineClassUnder("Backtrace"runtime.getObject(), .);
             RubyClass location = backtrace.defineClassUnder("Location"runtime.getObject(), .);
             
             location.defineAnnotatedMethods(Location.class);
             
             runtime.setLocation(location);
         }
         
         return threadClass;
     }
     
     public static class Location extends RubyObject {
         public Location(Ruby runtimeRubyClass klassRubyStackTraceElement element) {
             super(runtimeklass);
             this. = element;
         }
         
         @JRubyMethod
         public IRubyObject absolute_path(ThreadContext context) {
             return context.runtime.newString(.getFileName());
         }
         
         @JRubyMethod
         public IRubyObject base_label(ThreadContext context) {
             return context.runtime.newString(.getMethodName());
         }
         
         @JRubyMethod
         public IRubyObject inspect(ThreadContext context) {
             return to_s(context).inspect();
         }
         
         @JRubyMethod
         public IRubyObject label(ThreadContext context) {
             return context.runtime.newString(.getMethodName());
         }
         
         @JRubyMethod
         public IRubyObject lineno(ThreadContext context) {
             return context.runtime.newFixnum(.getLineNumber());
         }
         
         @JRubyMethod
         public IRubyObject path(ThreadContext context) {
             return context.runtime.newString(.getFileName());
         }
         
         @JRubyMethod
         public IRubyObject to_s(ThreadContext context) {
             return context.runtime.newString(.mriStyleString());
         }
 
         public static IRubyObject newLocationArray(Ruby runtimeRubyStackTraceElement[] elements) {
             RubyArray ary = runtime.newArray(elements.length);
 
             for (RubyStackTraceElement element : elements) {
                 ary.append(new RubyThread.Location(runtimeruntime.getLocation(), element));
             }
 
             return ary;
         }
         
         private final RubyStackTraceElement element;
     }

    
Thread.new

Thread.new( [ arg ]* ) {| args | block } -> aThread

Creates a new thread to execute the instructions given in block, and begins running it. Any arguments passed to Thread.new are passed into the block.

 x = Thread.new { sleep .1; print "x"; print "y"; print "z" }
 a = Thread.new { print "a"; print "b"; sleep .2; print "c" }
 x.join # Let the threads finish before
 a.join # main thread exits...
 
produces: abxyzc
 
     @JRubyMethod(name = {"new""fork"}, rest = true, meta = true)
     public static IRubyObject newInstance(IRubyObject recvIRubyObject[] argsBlock block) {
         return startThread(recvargstrueblock);
     }

    
Basically the same as Thread.new . However, if class Thread is subclassed, then calling start in that subclass will not invoke the subclass's initialize method.
 
     @JRubyMethod(rest = true, meta = true, compat = )
     public static RubyThread start(IRubyObject recvIRubyObject[] argsBlock block) {
         return startThread(recvargsfalseblock);
     }
     
     @JRubyMethod(rest = true, name = "start", meta = true, compat = )
     public static RubyThread start19(IRubyObject recvIRubyObject[] argsBlock block) {
         Ruby runtime = recv.getRuntime();
         // The error message may appear incongruous here, due to the difference
         // between JRuby's Thread model and MRI's.
         // We mimic MRI's message in the name of compatibility.
         if (! block.isGiven()) throw runtime.newArgumentError("tried to create Proc object without a block");
         return startThread(recvargsfalseblock);
     }
     
     public static RubyThread adopt(IRubyObject recvThread t) {
         return adoptThread(recvt.);
     }
 
     private static RubyThread adoptThread(final IRubyObject recvThread tBlock block) {
         final Ruby runtime = recv.getRuntime();
         final RubyThread rubyThread = new RubyThread(runtime, (RubyClassrecv);
         
         rubyThread.threadImpl = new NativeThread(rubyThreadt);
         ThreadContext context = runtime.getThreadService().registerNewThread(rubyThread);
         runtime.getThreadService().associateThread(trubyThread);
         
         context.preAdoptThread();
         
         // set to default thread group
         runtime.getDefaultThreadGroup().addDirectly(rubyThread);
         
         return rubyThread;
     }
     
     @JRubyMethod(rest = true, visibility = )
     public IRubyObject initialize(ThreadContext contextIRubyObject[] argsBlock block) {
         Ruby runtime = getRuntime();
         if (!block.isGiven()) throw runtime.newThreadError("must be called with a block");
         if ( != nullthrow runtime.newThreadError("already initialized thread");
 
         RubyRunnable runnable = new RubyRunnable(thisargsblock);
         
         return startWith(runnable);
     }
 
     private IRubyObject startWith(ThreadedRunnable runnablethrows RaiseExceptionOutOfMemoryError {
         Ruby runtime = getRuntime();
         ThreadContext context = runtime.getCurrentContext();
         
         try {
             if (.) {
                 FutureThread futureThread = new FutureThread(thisrunnable);
                  = futureThread;
 
                 addToCorrectThreadGroup(context);
 
                 .start();
 
                 // JRUBY-2380, associate future early so it shows up in Thread.list right away, in case it doesn't run immediately
                 runtime.getThreadService().associateThread(futureThread.getFuture(), this);
             } else {
                 Thread thread = new Thread(runnable);
                 thread.setDaemon(true);
                 thread.setName("Ruby-" + runtime.getRuntimeNumber() + "-" + thread.getName() + ": " + context.getFile() + ":" + (context.getLine() + 1));
                  = new NativeThread(thisthread);
 
                 addToCorrectThreadGroup(context);
 
                 // JRUBY-2380, associate thread early so it shows up in Thread.list right away, in case it doesn't run immediately
                 runtime.getThreadService().associateThread(threadthis);
 
                 .start();
             }
 
             // We yield here to hopefully permit the target thread to schedule
             // MRI immediately schedules it, so this is close but not exact
             Thread.yield();
         
             return this;
         } catch (OutOfMemoryError oome) {
             if (oome.getMessage().equals("unable to create new native thread")) {
                 throw runtime.newThreadError(oome.getMessage());
             }
             throw oome;
         } catch (SecurityException ex) {
           throw runtime.newThreadError(ex.getMessage());
         }
     }
     
     private static RubyThread startThread(final IRubyObject recvfinal IRubyObject[] argsboolean callInitBlock block) {
         RubyThread rubyThread = new RubyThread(recv.getRuntime(), (RubyClassrecv);
         
         if (callInit) {
             rubyThread.callInit(argsblock);
         } else {
             // for Thread::start, which does not call the subclass's initialize
             rubyThread.initialize(recv.getRuntime().getCurrentContext(), argsblock);
         }
         
         return rubyThread;
     }
     
     public synchronized void cleanTerminate(IRubyObject result) {
          = result;
     }
 
     public synchronized void beDead() {
         .set(.);
     }
 
     public void pollThreadEvents() {
     }
     
     public void pollThreadEvents(ThreadContext context) {
         if ( != nullcheckMail(context);
     }
     
     private static void throwThreadKill() {
         throw new ThreadKill();
     }

    
Returns the status of the global ``abort on exception'' condition. The default is false. When set to true, will cause all threads to abort (the process will exit(0)) if an exception is raised in any thread. See also Thread.abort_on_exception= .
 
     @JRubyMethod(name = "abort_on_exception", meta = true)
     public static RubyBoolean abort_on_exception_x(IRubyObject recv) {
         Ruby runtime = recv.getRuntime();
         return runtime.isGlobalAbortOnExceptionEnabled() ? runtime.getTrue() : runtime.getFalse();
     }
 
     @JRubyMethod(name = "abort_on_exception=", required = 1, meta = true)
     public static IRubyObject abort_on_exception_set_x(IRubyObject recvIRubyObject value) {
         recv.getRuntime().setGlobalAbortOnExceptionEnabled(value.isTrue());
         return value;
     }
 
     @JRubyMethod(name = "current", meta = true)
     public static RubyThread current(IRubyObject recv) {
         return recv.getRuntime().getCurrentContext().getThread();
     }
 
     @JRubyMethod(name = "main", meta = true)
     public static RubyThread main(IRubyObject recv) {
         return recv.getRuntime().getThreadService().getMainThread();
     }
 
     @JRubyMethod(name = "pass", meta = true)
     public static IRubyObject pass(IRubyObject recv) {
         Ruby runtime = recv.getRuntime();
         ThreadService ts = runtime.getThreadService();
         boolean critical = ts.getCritical();
         
         ts.setCritical(false);
         
         Thread.yield();
         
         ts.setCritical(critical);
         
         return recv.getRuntime().getNil();
     }
 
     @JRubyMethod(name = "list", meta = true)
     public static RubyArray list(IRubyObject recv) {
         RubyThread[] activeThreads = recv.getRuntime().getThreadService().getActiveRubyThreads();
         
         return recv.getRuntime().newArrayNoCopy(activeThreads);
     }
 
     private void addToCorrectThreadGroup(ThreadContext context) {
         // JRUBY-3568, inherit threadgroup or use default
         IRubyObject group = context.getThread().group();
         if (!group.isNil()) {
             ((RubyThreadGroupgroup).addDirectly(this);
         } else {
             context.runtime.getDefaultThreadGroup().addDirectly(this);
         }
     }
     
     private IRubyObject getSymbolKey(IRubyObject originalKey) {
         if (originalKey instanceof RubySymbol) {
             return originalKey;
         } else if (originalKey instanceof RubyString) {
             return getRuntime().newSymbol(originalKey.asJavaString());
         } else if (originalKey instanceof RubyFixnum) {
             getRuntime().getWarnings().warn(."Do not use Fixnums as Symbols");
             throw getRuntime().newArgumentError(originalKey + " is not a symbol");
         } else {
             throw getRuntime().newTypeError(originalKey + " is not a symbol");
         }
     }
     
     private synchronized Map<IRubyObjectIRubyObjectgetThreadLocals() {
         if ( == null) {
              = new HashMap<IRubyObjectIRubyObject>();
         }
         return ;
     }
 
     private void clearThreadLocals() {
          = null;
     }
 
     public final Map<ObjectIRubyObjectgetContextVariables() {
         return ;
     }
 
     public boolean isAlive(){
         return .isAlive() && .get() != .;
     }
 
     @JRubyMethod(name = "[]", required = 1)
     public IRubyObject op_aref(IRubyObject key) {
         IRubyObject value;
         if ((value = getThreadLocals().get(getSymbolKey(key))) != null) {
             return value;
         }
         return getRuntime().getNil();
     }
 
     @JRubyMethod(name = "[]=", required = 2)
     public IRubyObject op_aset(IRubyObject keyIRubyObject value) {
         key = getSymbolKey(key);
         
         getThreadLocals().put(keyvalue);
         return value;
     }
 
     @JRubyMethod(name = "abort_on_exception")
     public RubyBoolean abort_on_exception() {
         return  ? getRuntime().getTrue() : getRuntime().getFalse();
     }
 
     @JRubyMethod(name = "abort_on_exception=", required = 1)
          = val.isTrue();
         return val;
     }
 
     @JRubyMethod(name = "alive?")
     public RubyBoolean alive_p() {
         return isAlive() ? getRuntime().getTrue() : getRuntime().getFalse();
     }
 
     @JRubyMethod(name = "join", optional = 1)
     public IRubyObject join(IRubyObject[] args) {
         Ruby runtime = getRuntime();
         long timeoutMillis = .;
 
         if (args.length > 0 && !args[0].isNil()) {
             if (args.length > 1) {
                 throw getRuntime().newArgumentError(args.length,1);
             }
             // MRI behavior: value given in seconds; converted to Float; less
             // than or equal to zero returns immediately; returns nil
             timeoutMillis = (long)(1000.0D * args[0].convertToFloat().getValue());
             if (timeoutMillis <= 0) {
             // TODO: not sure that we should skip calling join() altogether.
             // Thread.join() has some implications for Java Memory Model, etc.
                 if (.isAlive()) {
                     return getRuntime().getNil();
                 } else {   
                    return this;
                 }
             }
         }
 
         if (isCurrent()) {
             throw getRuntime().newThreadError("thread " + identityString() + " tried to join itself");
         }
 
         try {
             if (runtime.getThreadService().getCritical()) {
                 // If the target thread is sleeping or stopped, wake it
                 synchronized (this) {
                     notify();
                 }
                 
                 // interrupt the target thread in case it's blocking or waiting
                 // WARNING: We no longer interrupt the target thread, since this usually means
                 // interrupting IO and with NIO that means the channel is no longer usable.
                 // We either need a new way to handle waking a target thread that's waiting
                 // on IO, or we need to accept that we can't wake such threads and must wait
                 // for them to complete their operation.
                 //threadImpl.interrupt();
             }
 
             RubyThread currentThread = getRuntime().getCurrentContext().getThread();
             final long timeToWait = Math.min(timeoutMillis, 200);
 
             // We need this loop in order to be able to "unblock" the
             // join call without actually calling interrupt.
             long start = System.currentTimeMillis();
             while(true) {
                 currentThread.pollThreadEvents();
                 .join(timeToWait);
                 if (!.isAlive()) {
                     break;
                 }
                 if (System.currentTimeMillis() - start > timeoutMillis) {
                     break;
                 }
             }
         } catch (InterruptedException ie) {
             ie.printStackTrace();
             assert false : ie;
         } catch (ExecutionException ie) {
             ie.printStackTrace();
             assert false : ie;
         }
 
         if ( != null) {
             // Set $! in the current thread before exiting
             throw ;
         }
 
         if (.isAlive()) {
             return getRuntime().getNil();
         } else {
             return this;
         }
     }
 
     @JRubyMethod
     public IRubyObject value() {
         join(new IRubyObject[0]);
         synchronized (this) {
             return ;
         }
     }
 
     @JRubyMethod
     public IRubyObject group() {
         if ( == null) {
             return getRuntime().getNil();
         }
         
         return ;
     }
     
     void setThreadGroup(RubyThreadGroup rubyThreadGroup) {
          = rubyThreadGroup;
     }
     
     @JRubyMethod(name = "inspect")
     @Override
     public synchronized IRubyObject inspect() {
         // FIXME: There's some code duplication here with RubyObject#inspect
         StringBuilder part = new StringBuilder();
         String cname = getMetaClass().getRealClass().getName();
         part.append("#<").append(cname).append(":");
         part.append(identityString());
         part.append(' ');
         part.append(.toString().toLowerCase());
         part.append('>');
         return getRuntime().newString(part.toString());
     }
 
     @JRubyMethod(name = "key?", required = 1)
     public RubyBoolean key_p(IRubyObject key) {
         key = getSymbolKey(key);
         
         return getRuntime().newBoolean(getThreadLocals().containsKey(key));
     }
 
     @JRubyMethod(name = "keys")
     public RubyArray keys() {
         IRubyObject[] keys = new IRubyObject[getThreadLocals().size()];
         
         return RubyArray.newArrayNoCopy(getRuntime(), getThreadLocals().keySet().toArray(keys));
     }
     
     @JRubyMethod(name = "critical=", required = 1, meta = true, compat = .)
     public static IRubyObject critical_set(IRubyObject receiverIRubyObject value) {
         receiver.getRuntime().getThreadService().setCritical(value.isTrue());
 
         return value;
     }
 
     @JRubyMethod(name = "critical", meta = true, compat = .)
     public static IRubyObject critical(IRubyObject receiver) {
         return receiver.getRuntime().newBoolean(receiver.getRuntime().getThreadService().getCritical());
     }
     
     @JRubyMethod(name = "stop", meta = true)
     public static IRubyObject stop(ThreadContext contextIRubyObject receiver) {
         RubyThread rubyThread = context.getThread();
         
         synchronized (rubyThread) {
             rubyThread.checkMail(context);
             try {
                 // attempt to decriticalize all if we're the critical thread
                 receiver.getRuntime().getThreadService().setCritical(false);
 
                 rubyThread.status.set(.);
                 rubyThread.wait();
             } catch (InterruptedException ie) {
                 rubyThread.checkMail(context);
                 rubyThread.status.set(.);
             }
         }
         
         return receiver.getRuntime().getNil();
     }
     
     @JRubyMethod(required = 1, meta = true)
     public static IRubyObject kill(IRubyObject receiverIRubyObject rubyThreadBlock block) {
         if (!(rubyThread instanceof RubyThread)) throw receiver.getRuntime().newTypeError(rubyThreadreceiver.getRuntime().getThread());
         return ((RubyThread)rubyThread).kill();
     }
     
     @JRubyMethod(meta = true)
     public static IRubyObject exit(IRubyObject receiverBlock block) {
         RubyThread rubyThread = receiver.getRuntime().getThreadService().getCurrentContext().getThread();
 
         synchronized (rubyThread) {
             rubyThread.status.set(.);
             // FIXME: This was not checking for non-null before, but maybe it should
             rubyThread.mail.set(null);
             receiver.getRuntime().getThreadService().setCritical(false);
             throw new ThreadKill();
         }
     }
 
     @JRubyMethod(name = "stop?")
     public RubyBoolean stop_p() {
         // not valid for "dead" state
         return getRuntime().newBoolean(.get() == . || .get() == .);
     }
     
     @JRubyMethod(name = "wakeup")
     public synchronized RubyThread wakeup() {
         if(!.isAlive() && .get() == .) {
             throw getRuntime().newThreadError("killed thread");
         }
 
         .set(.);
         notifyAll();
 
         return this;
     }
     
     @JRubyMethod(name = "priority")
     public RubyFixnum priority() {
         return RubyFixnum.newFixnum(getRuntime(), javaPriorityToRubyPriority(.getPriority()));
     }
 
     @JRubyMethod(name = "priority=", required = 1)
     public IRubyObject priority_set(IRubyObject priority) {
         int iPriority = RubyNumeric.fix2int(priority);
         
         if (iPriority < ) {
             iPriority = ;
         } else if (iPriority > ) {
             iPriority = ;
         }
 
         if (.isAlive()) {
             int jPriority = rubyPriorityToJavaPriority(iPriority);
             if (jPriority < .) {
                 jPriority = .;
             } else if (jPriority > .) {
                 jPriority = .;
             }
             .setPriority(jPriority);
         }
 
         return RubyFixnum.newFixnum(getRuntime(), iPriority);
     }
      
     /* helper methods to translate java thread priority (1-10) to
      * Ruby thread priority (-3 to 3) using a quadratic polynoimal ant its
      * inverse
      * i.e., j = r^2/18 + 3*r/2 + 5
      *       r = 3/2*sqrt(8*j + 41) - 27/2
      */
     private int javaPriorityToRubyPriority(int javaPriority) {
         double d// intermediate value
         d = 1.5 * Math.sqrt(8.0*javaPriority + 41) - 13.5;
         return Math.round((floatd);
     }
     
     private int rubyPriorityToJavaPriority(int rubyPriority) {
         double d;
         if (rubyPriority < ) {
             rubyPriority = ;
         } else if (rubyPriority > ) {
             rubyPriority = ;
         }
         d = Math.pow(rubyPriority, 2.0)/18.0 + 1.5 * rubyPriority + 5;
         return Math.round((floatd);
     }
    
    
Simplified utility method for just raising an existing exception in this thread.

Parameters:
exception the exception to raise
Returns:
this thread
 
     public IRubyObject raise(IRubyObject exception) {
         return raise(new IRubyObject[]{exception}, .);
     }
 
     @JRubyMethod(optional = 3)
     public IRubyObject raise(IRubyObject[] argsBlock block) {
         Ruby runtime = getRuntime();
         ThreadContext context = runtime.getCurrentContext();
         if (this == context.getThread()) {
             return RubyKernel.raise(contextruntime.getKernel(), argsblock);
         }
         
         debug(this"before raising");
         RubyThread currentThread = getRuntime().getCurrentContext().getThread();
 
         debug(this"raising");
         IRubyObject exception = prepareRaiseException(runtimeargsblock);
 
         runtime.getThreadService().deliverEvent(new ThreadService.Event(currentThreadthis...exception));
 
         return this;
     }

    
This is intended to be used to raise exceptions in Ruby threads from non- Ruby threads like Timeout's thread.

Parameters:
args Same args as for Thread#raise
block Same as for Thread#raise
 
     public void internalRaise(IRubyObject[] args) {
         Ruby runtime = getRuntime();
 
         IRubyObject exception = prepareRaiseException(runtimeargs.);
 
         receiveMail(new ThreadService.Event(thisthis...exception));
     }
 
     private IRubyObject prepareRaiseException(Ruby runtimeIRubyObject[] argsBlock block) {
         if(args.length == 0) {
             IRubyObject lastException = ;
             if(lastException.isNil()) {
                 return new RaiseException(runtimeruntime.getRuntimeError(), ""false).getException();
             } 
             return lastException;
         }
 
         IRubyObject exception;
         ThreadContext context = getRuntime().getCurrentContext();
         
         if(args.length == 1) {
             if(args[0] instanceof RubyString) {
                 return runtime.getRuntimeError().newInstance(contextargsblock);
             } else if (args[0] instanceof ConcreteJavaProxy) {
                 return args[0];
             } else if(!args[0].respondsTo("exception")) {
                 return runtime.newTypeError("exception class/object expected").getException();
             }
             exception = args[0].callMethod(context"exception");
         } else {
             if (!args[0].respondsTo("exception")) {
                 return runtime.newTypeError("exception class/object expected").getException();
             }
             
             exception = args[0].callMethod(context"exception"args[1]);
         }
         
         if (!runtime.getException().isInstance(exception)) {
             return runtime.newTypeError("exception object expected").getException();
         }
         
         if (args.length == 3) {
             ((RubyExceptionexception).set_backtrace(args[2]);
         }
         
         return exception;
     }
     
     @JRubyMethod(name = "run")
     public synchronized IRubyObject run() {
         return wakeup();
     }

    
We can never be sure if a wait will finish because of a Java "spurious wakeup". So if we explicitly wakeup and we wait less than requested amount we will return false. We will return true if we sleep right amount or less than right amount via spurious wakeup.
 
     public synchronized boolean sleep(long millisthrows InterruptedException {
         assert this == getRuntime().getCurrentContext().getThread();
         boolean result = true;
 
         synchronized (this) {
             pollThreadEvents();
             try {
                 .set(.);
                 if (millis == -1) {
                     wait();
                } else {
                    wait(millis);
                }
            } finally {
                result = (.get() != .);
                pollThreadEvents();
                .set(.);
            }
        }
        return result;
    }
    public IRubyObject status() {
        return status(getRuntime());
    }
    @JRubyMethod(name = "status")
    public IRubyObject status(ThreadContext context) {
        return status(context.runtime);
    }
    
    private synchronized IRubyObject status(Ruby runtime) {
        if (.isAlive()) {
            return RubyString.newStringShared(runtime.get().);
        } else if ( != null) {
            return runtime.getNil();
        } else {
            return runtime.getFalse();
        }
    }
    public static interface BlockingTask {
        public void run() throws InterruptedException;
        public void wakeup();
    }
    public static final class SleepTask implements BlockingTask {
        private final Object object;
        private final long millis;
        private final int nanos;
        public SleepTask(Object objectlong millisint nanos) {
            this. = object;
            this. = millis;
            this. = nanos;
        }
        public void run() throws InterruptedException {
            synchronized () {
                .wait();
            }
        }
        public void wakeup() {
            synchronized () {
                .notify();
            }
        }
    }
    public void executeBlockingTask(BlockingTask taskthrows InterruptedException {
        enterSleep();
        try {
             = task;
            pollThreadEvents();
            task.run();
        } finally {
            exitSleep();
             = null;
            pollThreadEvents();
        }
    }
    public void enterSleep() {
        .set(.);
    }
    public void exitSleep() {
        .set(.);
    }
    @JRubyMethod(name = {"kill""exit""terminate"})
    public IRubyObject kill() {
        // need to reexamine this
        RubyThread currentThread = getRuntime().getCurrentContext().getThread();
        
        // If the killee thread is the same as the killer thread, just die
        if (currentThread == thisthrowThreadKill();
        debug(this"trying to kill");
        currentThread.pollThreadEvents();
        
        getRuntime().getThreadService().deliverEvent(new ThreadService.Event(currentThreadthis...));
        debug(this"succeeded with kill");
        
        return this;
    }
    
    
Used for finalizers that need to kill a Ruby thread. Finalizers run in a VM thread to which we do not want to attach a ThreadContext and within which we do not want to check for Ruby thread events. This mechanism goes directly to mail delivery, bypassing all Ruby Thread-related steps.
    public void dieFromFinalizer() {
        receiveMail(new ThreadService.Event(nullthis...));
    }