diff options
Diffstat (limited to 'libjava/gnu/java/nio/natVMSelectorWin32.cc')
-rw-r--r-- | libjava/gnu/java/nio/natVMSelectorWin32.cc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/libjava/gnu/java/nio/natVMSelectorWin32.cc b/libjava/gnu/java/nio/natVMSelectorWin32.cc new file mode 100644 index 000000000..790de22e4 --- /dev/null +++ b/libjava/gnu/java/nio/natVMSelectorWin32.cc @@ -0,0 +1,93 @@ +// natVMSelectorImplWin32.cc + +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include <config.h> +#include <platform.h> + +#include <gnu/java/nio/VMSelector.h> +#include <java/lang/Thread.h> + +jint +gnu::java::nio::VMSelector::select (jintArray read, jintArray write, + jintArray except, jlong timeout) +{ + // FIXME: The API for implSelect is biased towards POSIX implementations. + jint* pReadFD = elements (read); + int nNbReadFDs = JvGetArrayLength (read); + + jint* pWriteFD = elements (write); + int nNbWriteFDs = JvGetArrayLength (write); + + int nNbEvents = nNbReadFDs + nNbWriteFDs; + + // Create and initialize our event wrapper array + + // FIXME: We're creating fresh WSAEVENTs for each call. + // This is inefficient. It would probably be better to cache these + // in the Win32 socket implementation class. + WSAEventWrapper aArray[nNbEvents]; + + int nCurIndex = 0; + for (int i=0; i < nNbReadFDs; ++i) + aArray[nCurIndex++].init(pReadFD[i], FD_ACCEPT | FD_READ); + + for (int i=0; i < nNbWriteFDs; ++i) + aArray[nCurIndex++].init(pWriteFD[i], FD_WRITE); + + // Build our array of WSAEVENTs to wait on. Also throw in our thread's + // interrupt event in order to detect thread interruption. + HANDLE arh[nNbEvents + 1]; + for (int i=0; i < nNbEvents; ++i) + arh[i] = aArray[i].getEventHandle(); + arh[nNbEvents] = _Jv_Win32GetInterruptEvent (); + + // A timeout value of 0 needs to be treated as infinite. + if (timeout <= 0) + timeout = WSA_INFINITE; + + // Do the select. + DWORD dwRet = WSAWaitForMultipleEvents (nNbEvents+1, arh, 0, timeout, false); + + if (dwRet == WSA_WAIT_FAILED) + _Jv_ThrowIOException (); + + // Before we do anything else, clear output file descriptor arrays. + memset(pReadFD, 0, sizeof(jint) * nNbReadFDs); + memset(pWriteFD, 0, sizeof(jint) * nNbWriteFDs); + memset(elements (except), 0, sizeof(jint) * JvGetArrayLength (except)); + + if (dwRet == DWORD(WSA_WAIT_EVENT_0 + nNbEvents)) + { + // We were interrupted. Set the current thread's interrupt + // status and get out of here, with nothing selected.. + ::java::lang::Thread::currentThread ()->interrupt (); + return 0; + } + else if (dwRet < DWORD(WSA_WAIT_EVENT_0 + nNbEvents)) + { + int nSelectedEventIndex = dwRet - WSA_WAIT_EVENT_0; + + // Record the selected file descriptor. + // FIXME: This implementation only allows one file descriptor + // to be selected at a time. Remedy this by looping on + // WSAWaitForMultipleEvents 'til nothing more is selected. + jint fd = aArray[nSelectedEventIndex].getFD(); + if (nSelectedEventIndex < nNbReadFDs) + pReadFD[0] = fd; + else + pWriteFD[0] = fd; + + return 1; + } + else + // None of the event objects was signalled, so nothing was + // selected. + return 0; +} |