Beispiel #1
0
  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(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
    runtime.setThread(threadClass);

    threadClass.index = ClassIndex.THREAD;
    threadClass.setReifiedClass(RubyThread.class);

    threadClass.defineAnnotatedMethods(RubyThread.class);

    RubyThread rubyThread = new RubyThread(runtime, threadClass);
    // 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(ObjectMarshal.NOT_MARSHALABLE_MARSHAL);

    return threadClass;
  }
Beispiel #2
0
  @JRubyMethod(rest = true, visibility = PRIVATE)
  public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block block) {
    Ruby runtime = getRuntime();
    if (!block.isGiven()) throw runtime.newThreadError("must be called with a block");

    try {
      RubyRunnable runnable = new RubyRunnable(this, args, context.getFrames(0), block);
      if (RubyInstanceConfig.POOLING_ENABLED) {
        FutureThread futureThread = new FutureThread(this, runnable);
        threadImpl = futureThread;

        addToCorrectThreadGroup(context);

        threadImpl.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" + thread.getName() + ": " + context.getFile() + ":" + (context.getLine() + 1));
        threadImpl = new NativeThread(this, thread);

        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(thread, this);

        threadImpl.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());
    }
  }
Beispiel #3
0
 /**
  * Try to acquire the given lock, adding it to a list of held locks for cleanup on thread
  * termination if it is acquired. Return immediately if the lock cannot be acquired.
  *
  * @param lock the lock to acquire, released on thread termination
  */
 public boolean tryLock(Lock lock) {
   assert Thread.currentThread() == getNativeThread();
   boolean locked = lock.tryLock();
   if (locked) {
     heldLocks.add(lock);
   }
   return locked;
 }
  private IRubyObject startWith(ThreadedRunnable runnable) throws RaiseException, OutOfMemoryError {
    Ruby runtime = getRuntime();
    ThreadContext context = runtime.getCurrentContext();

    try {
      if (RubyInstanceConfig.POOLING_ENABLED) {
        FutureThread futureThread = new FutureThread(this, runnable);
        threadImpl = futureThread;

        addToCorrectThreadGroup(context);

        threadImpl.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" + thread.getName() + ": " + context.getFile() + ":" + (context.getLine() + 1));
        threadImpl = new NativeThread(this, thread);

        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(thread, this);

        threadImpl.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());
    }
  }
Beispiel #5
0
  @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();
  }
Beispiel #6
0
 private static void debug(RubyThread thread, String message) {
   if (DEBUG) LOG.debug(Thread.currentThread() + "(" + thread.status + "): " + message);
 }
Beispiel #7
0
 /** Release all locks held. */
 public void unlockAll() {
   assert Thread.currentThread() == getNativeThread();
   for (Lock lock : heldLocks) {
     lock.unlock();
   }
 }
Beispiel #8
0
 /**
  * Release the given lock and remove it from the list of locks to be released on thread
  * termination.
  *
  * @param lock the lock to release and dereferences
  */
 public void unlock(Lock lock) {
   assert Thread.currentThread() == getNativeThread();
   lock.unlock();
   heldLocks.remove(lock);
 }
Beispiel #9
0
 /**
  * Acquire the given lock interruptibly, holding a reference to it for cleanup on thread
  * termination.
  *
  * @param lock the lock to acquire, released on thread termination
  * @throws InterruptedException if the lock acquisition is interrupted
  */
 public void lockInterruptibly(Lock lock) throws InterruptedException {
   assert Thread.currentThread() == getNativeThread();
   lock.lockInterruptibly();
   heldLocks.add(lock);
 }
Beispiel #10
0
 /**
  * Acquire the given lock, holding a reference to it for cleanup on thread termination.
  *
  * @param lock the lock to acquire, released on thread termination
  */
 public void lock(Lock lock) {
   assert Thread.currentThread() == getNativeThread();
   lock.lock();
   heldLocks.add(lock);
 }
 /**
  * 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.initialPriority = Thread.currentThread().getPriority();
 }