// natSelectorImplWin32.cc /* Copyright (C) 2003 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 #include #include #include jint gnu::java::nio::SelectorImpl::implSelect (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; }