| // natSelectorImplWin32.cc | |
| /* Copyright (C) 2003, 2004 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; | |
| } |