static { String tmpDir; if (Platform.IS_WINDOWS) { tmpDir = System.getProperty("java.io.tmpdir"); if (tmpDir == null) tmpDir = System.getenv("TEMP"); if (tmpDir == null) tmpDir = System.getenv("TMP"); if (tmpDir == null) tmpDir = "C:\\Windows\\Temp"; } else { tmpDir = "/tmp"; } DEFAULT_TMP_DIR = tmpDir; }
public boolean wait_timeout(IRubyObject o, Double timeout) throws InterruptedException { if (timeout != null) { long delay_ns = (long) (timeout.doubleValue() * 1000000000.0); long start_ns = System.nanoTime(); if (delay_ns > 0) { long delay_ms = delay_ns / 1000000; int delay_ns_remainder = (int) (delay_ns % 1000000); executeBlockingTask(new SleepTask(o, delay_ms, delay_ns_remainder)); } long end_ns = System.nanoTime(); return (end_ns - start_ns) <= delay_ns; } else { executeBlockingTask(new SleepTask(o, 0, 0)); return true; } }
@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; } }
private String identityString() { return "0x" + Integer.toHexString(System.identityHashCode(this)); }
@SuppressWarnings("fallthrough") @JRubyMethod(name = "read", optional = 2) @Override public IRubyObject read(IRubyObject[] args) { checkReadable(); ByteList buf = null; int length = 0; int oldLength = 0; RubyString originalString = null; switch (args.length) { case 2: originalString = args[1].convertToString(); // must let original string know we're modifying, so shared buffers aren't damaged originalString.modify(); buf = originalString.getByteList(); case 1: if (!args[0].isNil()) { length = RubyNumeric.fix2int(args[0]); oldLength = length; if (length < 0) { throw getRuntime().newArgumentError("negative length " + length + " given"); } if (length > 0 && isEndOfString()) { data.eof = true; if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } else if (data.eof) { if (buf != null) buf.setRealSize(0); return getRuntime().getNil(); } break; } case 0: oldLength = -1; length = data.internal.getByteList().length(); if (length <= data.pos) { data.eof = true; if (buf == null) { buf = new ByteList(); } else { buf.setRealSize(0); } return makeString(getRuntime(), buf); } else { length -= data.pos; } break; default: getRuntime().newArgumentError(args.length, 0); } if (buf == null) { int internalLength = data.internal.getByteList().length(); if (internalLength > 0) { if (internalLength >= data.pos + length) { buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; buf = new ByteList(data.internal.getByteList(), (int) data.pos, length); } } } else { int rest = (int) (data.internal.getByteList().length() - data.pos); if (length > rest) length = rest; // Yow...this is still ugly byte[] target = buf.getUnsafeBytes(); if (target.length > length) { System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); } else { target = new byte[length]; System.arraycopy( data.internal.getByteList().getUnsafeBytes(), (int) data.pos, target, 0, length); buf.setBegin(0); buf.setRealSize(length); buf.setUnsafeBytes(target); } } if (buf == null) { if (!data.eof) buf = new ByteList(); length = 0; } else { length = buf.length(); data.pos += length; } if (oldLength < 0 || oldLength > length) data.eof = true; return originalString != null ? originalString : makeString(getRuntime(), buf); }