private int writeInternal(ThreadContext context, IRubyObject arg) {
    checkWritable();
    checkFrozen();

    RubyString val = arg.asString();
    data.internal.modify();

    if (data.modes.isAppendable()) {
      data.internal.getByteList().append(val.getByteList());
      data.pos = data.internal.getByteList().length();
    } else {
      int left = data.internal.getByteList().length() - (int) data.pos;
      data.internal
          .getByteList()
          .replace((int) data.pos, Math.min(val.getByteList().length(), left), val.getByteList());
      data.pos += val.getByteList().length();
    }

    if (val.isTaint()) {
      data.internal.setTaint(true);
    }

    return val.getByteList().length();
  }
示例#2
0
  @JRubyMethod(name = "join", optional = 1)
  public IRubyObject join(IRubyObject[] args) {
    Ruby runtime = getRuntime();
    long timeoutMillis = Long.MAX_VALUE;

    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 (threadImpl.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();
        threadImpl.join(timeToWait);
        if (!threadImpl.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 (exitingException != null) {
      // Set $! in the current thread before exiting
      getRuntime().getGlobalVariables().set("$!", (IRubyObject) exitingException.getException());
      throw exitingException;
    }

    if (threadImpl.isAlive()) {
      return getRuntime().getNil();
    } else {
      return this;
    }
  }