diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index dfea44d947..130b47daa9 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -15,9 +15,6 @@ # include # include # include - -# undef JNIEXPORT -# define JNIEXPORT __attribute__ ((visibility("default"))) #endif #define java_nio_channels_SelectionKey_OP_READ 1L @@ -492,19 +489,6 @@ Java_java_nio_channels_SocketSelector_natWakeup(JNIEnv *e, jclass, jlong state) } } -extern "C" JNIEXPORT void JNICALL -Java_java_nio_channels_SocketSelector_natClearWoken(JNIEnv *e, jclass, jlong state) -{ - SelectorState* s = reinterpret_cast(state); - if (s->control.connected() and s->control.reader() >= 0) { - char c; - int r = ::doRead(s->control.reader(), &c, 1); - if (r != 1) { - throwIOException(e); - } - } -} - extern "C" JNIEXPORT void JNICALL Java_java_nio_channels_SocketSelector_natClose(JNIEnv *, jclass, jlong state) { @@ -562,8 +546,68 @@ Java_java_nio_channels_SocketSelector_natDoSocketSelect(JNIEnv *e, jclass, FD_SET(static_cast(socket), &(s->read)); if (max < socket) max = socket; } + +#ifdef WIN32 + if (s->control.listener() >= 0) { + int socket = s->control.listener(); + FD_SET(static_cast(socket), &(s->read)); + if (max < socket) max = socket; + } + + if (not s->control.connected()) { + int socket = s->control.writer(); + FD_SET(static_cast(socket), &(s->write)); + FD_SET(static_cast(socket), &(s->except)); + if (max < socket) max = socket; + } +#endif + timeval time = { interval / 1000, (interval % 1000) * 1000 }; int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time); + +#ifdef WIN32 + if (FD_ISSET(s->control.writer(), &(s->write)) or + FD_ISSET(s->control.writer(), &(s->except))) + { + unsigned socket = s->control.writer(); + FD_CLR(socket, &(s->write)); + FD_CLR(socket, &(s->except)); + + int error; + socklen_t size = sizeof(int); + int r = getsockopt(socket, SOL_SOCKET, SO_ERROR, + reinterpret_cast(&error), &size); + if (r != 0 or size != sizeof(int) or error != 0) { + throwIOException(e); + } + s->control.setConnected(true); + } + + if (s->control.listener() >= 0 and + FD_ISSET(s->control.listener(), &(s->read))) + { + FD_CLR(static_cast(s->control.listener()), &(s->read)); + + s->control.setReader(::doAccept(e, s->control.listener())); + s->control.setListener(-1); + } +#endif + + if (s->control.reader() >= 0 and + FD_ISSET(s->control.reader(), &(s->read))) + { + FD_CLR(static_cast(s->control.reader()), &(s->read)); + + char c; + int r = 1; + while (r == 1) { + r = ::doRead(s->control.reader(), &c, 1); + } + if (r < 0 and not eagain()) { + throwIOException(e); + } + } + if (r < 0) { if (errno != EINTR) { throwIOException(e); diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index c0863488c0..595a832f7f 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -4,13 +4,13 @@ import java.io.IOException; import java.util.Iterator; class SocketSelector extends Selector { - private static final boolean isWin32; + private static final boolean IsWin32; protected long state; protected final Object lock = new Object(); protected boolean woken = false; static { - isWin32 = false; + IsWin32 = false; } public SocketSelector() { @@ -35,7 +35,6 @@ class SocketSelector extends Selector { synchronized (lock) { if (woken) { woken = false; - natClearWoken(state); return true; } else { return false; @@ -44,93 +43,33 @@ class SocketSelector extends Selector { } public synchronized void select(long interval) throws IOException { - if (isWin32) { - win32Select(interval); - } else { - posixSelect(interval); - } - } - - private void win32Select(long interval) { } - - private void posixSelect(long interval) throws IOException { selectedKeys.clear(); if (clearWoken()) return; int max=0; for (Iterator it = keys.iterator(); - it.hasNext();) { + it.hasNext();) + { SelectionKey key = it.next(); SocketChannel c = (SocketChannel)key.channel(); int socket = c.socketFD(); if (! c.isOpen()) { natSelectClearAll(socket, state); - // Equivalent to: - // - // FD_CLR(socket, &(s->read)); - // FD_CLR(socket, &(s->write)); - // FD_CLR(socket, &(s->except)); it.remove(); continue; } key.readyOps(0); max = natSelectUpdateInterestSet(socket, key.interestOps(), state, max); - // Equivalent to: - // - // if (interest & (SelectionKey::OP_READ | SelectionKey::OP_ACCEPT)) { - // FD_SET(socket, &(s->read)); - // if (max < socket) max = socket; - // } else { - // FD_CLR(socket, &(s->read)); - // } - // - // if (interest & SelectionKey::OP_WRITE) { - // FD_SET(socket, &(s->write)); - // if (max < socket) max = socket; - // } else { - // FD_CLR(socket, &(s->write)); - // } } int r = natDoSocketSelect(state, max, interval); - // Equivalent to: - // - // if (s->control.reader() >= 0) { - // unsigned socket = s->control.reader(); - // FD_SET(socket, &(s->read)); - // if (max < socket) max = socket; - // } - // timeval time = { interval / 1000, (interval % 1000) * 1000 }; - // int r = ::select(max + 1, &(s->read), &(s->write), &(s->except), &time); - // if (r < 0) { - // if (errno != EINTR) { - // throw new IOException(errorString()); - // } - // } + if (r > 0) { for (SelectionKey key : keys) { SocketChannel c = (SocketChannel)key.channel(); int socket = c.socketFD(); int ready = natUpdateReadySet(socket, key.interestOps(), state); - // Equivalent to: - // - // jint ready = 0; - // - // if (FD_ISSET(c->socket, &(s->read))) { - // if (interest & SelectionKey::OP_READ) { - // ready |= SelectionKey::OP_READ; - // } - // - // if (interest & SelectionKey::OP_ACCEPT) { - // ready |= SelectionKey::OP_ACCEPT; - // } - // } - // - // if ((interest & SelectionKey::OP_WRITE) - // and FD_ISSET(c->socket, &(s->write))) { - // ready |= SelectionKey::OP_WRITE; - // } key.readyOps(ready); if (ready != 0) { selectedKeys.add(key); @@ -146,7 +85,6 @@ class SocketSelector extends Selector { private static native long natInit(); private static native void natWakeup(long state); - private static native void natClearWoken(long state); private static native void natClose(long state); private static native void natSelectClearAll(int socket, long state); private static native int natSelectUpdateInterestSet(int socket,