org.jruby.internal.runtime
Class ThreadService
java.lang.Object
org.jruby.internal.runtime.ThreadService
public class ThreadService
- extends java.lang.Object
ThreadService maintains lists ofall the JRuby-specific thread data structures
needed for Ruby's threading API and for JRuby's execution. The main
structures are:
- ThreadContext, which contains frames, scopes, etc needed for Ruby execution
- RubyThread, the Ruby object representation of a thread's state
- RubyThreadGroup, which represents a group of Ruby threads
- NativeThread, used to wrap native Java threads
- FutureThread, used to wrap java.util.concurrent.Future
In order to ensure these structures do not linger after the thread has terminated,
most of them are either weakly or softly referenced. The references associated
with these structures are:
- ThreadService has a hard reference to a ThreadLocal, which holds a soft reference
to a ThreadContext. So the thread's locals softly reference ThreadContext.
We use a soft reference to keep ThreadContext instances from going away too
quickly when a Java thread leaves Ruby space completely, which would otherwise
result in a lot of ThreadContext object churn.
- ThreadService maintains a weak map from the actual java.lang.Thread (or
java.util.concurrent.Future) instance to the associated RubyThread. The map
is weak-keyyed, so it will not prevent the collection of the associated
Thread or Future. The associated RubyThread will remain alive as long as the
Thread/Future and this ThreadService instance are both alive, maintaining
the external thread's identity in Ruby-land.
- RubyThread has a weak reference to its to ThreadContext.
- ThreadContext has a hard reference to its associated RubyThread. Ignoring other
references, this will usually mean RubyThread is softly reachable via the
soft threadlocal reference to ThreadContext in ThreadService.
- RubyThreadGroup has hard references to threads it owns. The thread removes
itself on termination (if it's a Ruby thread) or when the ThreadContext is
collected (as in the case of "adopted" Java threads.
These data structures can come to life in one of two ways:
- A Ruby thread is started. This constructs a new RubyThread object, which
calls to ThreadService to initialize a ThreadContext and appropriate mappings
in all ThreadService's structures. The body of the thread is wrapped with a
finally block that will forcibly unregister the thread and all related
structures from ThreadService.
- A Java thread enters Ruby by doing a call. The thread is "adopted", and
gains a RubyThread instance, a ThreadContext instance, and all associated
mappings in ThreadService. Since we don't know when the thread has "left"
Ruby permanently, no forcible unregistration is attempted for the various
structures and maps. However, they should not be hard-rooted; the
ThreadContext is only softly reachable at best if no calls are in-flight,
so it will collect. Its collection will release the reference to RubyThread,
and its finalizer will unregister that RubyThread from its RubyThreadGroup.
With the RubyThread gone, the Thread-to-RubyThread map will eventually clear,
releasing the hard reference to the Thread itself.
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
ThreadService
public ThreadService(Ruby runtime)
disposeCurrentThread
public void disposeCurrentThread()
initMainThread
public void initMainThread()
getCurrentContext
public ThreadContext getCurrentContext()
- In order to provide an appropriate execution context for a given thread,
we store ThreadContext instances in a threadlocal. This method is a utility
to get at that threadlocal context from anywhere in the program it may
not be immediately available. This method should be used sparingly, and
if it is possible to pass ThreadContext on the argument list, it is
preferable.
Description of behavior
The threadlocal does not actually contain the ThreadContext directly;
instead, it contains a SoftReference that holds the ThreadContext. This
is to allow new threads to enter the system and execute Ruby code with
a valid context, but still allow that context to garbage collect if the
thread stays alive much longer. We use SoftReference here because
WeakReference is collected too quickly, resulting in very expensive
ThreadContext churn (and this originally lead to JRUBY-2261's leak of
adopted RubyThread instances).
- Returns:
- The ThreadContext instance for the current thread, or a new one
if none has previously been created or the old ThreadContext has been
collected.
getMainThread
public RubyThread getMainThread()
setMainThread
public void setMainThread(java.lang.Thread thread,
RubyThread rubyThread)
getActiveRubyThreads
public RubyThread[] getActiveRubyThreads()
getRubyThreadGroup
public java.lang.ThreadGroup getRubyThreadGroup()
getThreadContextForThread
public ThreadContext getThreadContextForThread(RubyThread thread)
registerNewThread
public ThreadContext registerNewThread(RubyThread thread)
associateThread
public void associateThread(java.lang.Object threadOrFuture,
RubyThread rubyThread)
dissociateThread
public void dissociateThread(java.lang.Object threadOrFuture)
unregisterThread
public void unregisterThread(RubyThread thread)
setCritical
public void setCritical(boolean critical)
getCritical
public boolean getCritical()
deliverEvent
public void deliverEvent(ThreadService.Event event)
getRubyThreadMap
public java.util.Map<java.lang.Object,RubyThread> getRubyThreadMap()
- Get the map from threadlike objects to RubyThread instances. Used mainly
for testing purposes.
- Returns:
- The ruby thread map
Copyright © 2002-2009 JRuby Team. All Rights Reserved.