Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 2 additions & 120 deletions ext/java/org/jruby/ext/io/wait/IOWaitLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,133 +29,15 @@
package org.jruby.ext.io.wait;

import org.jruby.Ruby;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyIO;
import org.jruby.RubyNumeric;
import org.jruby.RubySymbol;
import org.jruby.RubyTime;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import org.jruby.util.io.OpenFile;

import java.nio.channels.SelectionKey;

import static org.jruby.api.Warn.warnDeprecated;

/**
* IO wait methods are built in JRuby now, just for backward compatibility.
*
* @author Nick Sieger
*/
public class IOWaitLibrary implements Library {

public void load(Ruby runtime, boolean wrap) {
RubyClass ioClass = runtime.getIO();
ioClass.defineAnnotatedMethods(IOWaitLibrary.class);
}

@JRubyMethod(optional = 1)
public static IRubyObject wait_readable(ThreadContext context, IRubyObject _io, IRubyObject[] argv) {
RubyIO io = (RubyIO)_io;
OpenFile fptr = io.getOpenFileChecked();

fptr.checkReadable(context);

long tv = prepareTimeout(context, argv);

if (fptr.readPending() != 0) return context.tru;

return doWait(context, io, fptr, tv, SelectionKey.OP_READ | SelectionKey.OP_ACCEPT);
}

/**
* waits until input available or timed out and returns self, or nil when EOF reached.
*/
@JRubyMethod(optional = 1)
public static IRubyObject wait_writable(ThreadContext context, IRubyObject _io, IRubyObject[] argv) {
RubyIO io = (RubyIO)_io;

OpenFile fptr = io.getOpenFileChecked();

fptr.checkWritable(context);

long tv = prepareTimeout(context, argv);

return doWait(context, io, fptr, tv, SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE);
}

@JRubyMethod(optional = 2)
public static IRubyObject wait(ThreadContext context, IRubyObject _io, IRubyObject[] argv) {
RubyIO io = (RubyIO)_io;

OpenFile fptr = io.getOpenFileChecked();

int ops = 0;

if (argv.length == 2) {
if (argv[1] instanceof RubySymbol) {
RubySymbol sym = (RubySymbol) argv[1];
switch (sym.asJavaString()) { // 7 bit comparison
case "r":
case "read":
case "readable":
ops |= SelectionKey.OP_ACCEPT | SelectionKey.OP_READ;
break;
case "w":
case "write":
case "writable":
ops |= SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE;
break;
case "rw":
case "read_write":
case "readable_writable":
ops |= SelectionKey.OP_ACCEPT | SelectionKey.OP_READ | SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE;
break;
default:
throw context.runtime.newArgumentError("unsupported mode: " + sym);
}
} else {
throw context.runtime.newArgumentError("unsupported mode: " + argv[1].getType());
}
} else {
ops |= SelectionKey.OP_ACCEPT | SelectionKey.OP_READ;
}

if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ && fptr.readPending() != 0) return context.tru;

long tv = prepareTimeout(context, argv);

return doWait(context, io, fptr, tv, ops);
}

private static IRubyObject doWait(ThreadContext context, RubyIO io, OpenFile fptr, long tv, int ops) {
boolean ready = fptr.ready(context.runtime, context.getThread(), ops, tv);
fptr.checkClosed();
if (ready) return io;
return context.nil;
}

private static long prepareTimeout(ThreadContext context, IRubyObject[] argv) {
IRubyObject timeout;
long tv;
switch (argv.length) {
case 2:
case 1:
timeout = argv[0];
break;
default:
timeout = context.nil;
}

if (timeout.isNil()) {
tv = -1;
}
else {
tv = (long)(RubyTime.convertTimeInterval(context, timeout) * 1000);
if (tv < 0) throw context.runtime.newArgumentError("time interval must be positive");
}
return tv;
}
}
Loading