From 5cd4d463f974cced4d9819ace4583641ec0ad188 Mon Sep 17 00:00:00 2001 From: Mohan Embar Date: Tue, 16 Dec 2003 22:54:22 +0000 Subject: [PATCH] win32.cc (WSAEventWrapper): Implemented default constructor and init() methods. * win32.cc (WSAEventWrapper): Implemented default constructor and init() methods. (_Jv_select): Removed. * gnu/java/nio/natSelectorImplWin32.cc (helper_put_filedescriptors): Removed. (helper_get_filedescriptors): Removed. (implSelect): Implemented in terms of WSAEventWrapper and WSAWaitForMultipleEvents instead of _Jv_select(). Added support for thread interruption. * include/win32.h (WSAEventWrapper): Minor formatting changes; added default constructor declaration, init(), getFD() and getEventHandle() methods. (_Jv_select): Removed. From-SVN: r74715 --- libjava/ChangeLog | 16 +++ libjava/gnu/java/nio/natSelectorImplWin32.cc | 132 ++++++++++--------- libjava/include/win32.h | 38 ++++-- libjava/win32.cc | 30 ++--- 4 files changed, 122 insertions(+), 94 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 1b5cf7edaa1..2667bd2741e 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,19 @@ +2003-12-16 Mohan Embar + + * win32.cc (WSAEventWrapper): Implemented default + constructor and init() methods. + (_Jv_select): Removed. + * gnu/java/nio/natSelectorImplWin32.cc + (helper_put_filedescriptors): Removed. + (helper_get_filedescriptors): Removed. + (implSelect): Implemented in terms of WSAEventWrapper + and WSAWaitForMultipleEvents instead of _Jv_select(). + Added support for thread interruption. + * include/win32.h (WSAEventWrapper): Minor formatting + changes; added default constructor declaration, init(), + getFD() and getEventHandle() methods. + (_Jv_select): Removed. + 2003-12-16 Mohan Embar * gnu/java/net/natPlainDatagramSocketImplPosix.cc diff --git a/libjava/gnu/java/nio/natSelectorImplWin32.cc b/libjava/gnu/java/nio/natSelectorImplWin32.cc index c82c2aa6d0e..34c4deb0e96 100644 --- a/libjava/gnu/java/nio/natSelectorImplWin32.cc +++ b/libjava/gnu/java/nio/natSelectorImplWin32.cc @@ -11,81 +11,83 @@ details. */ #include #include -#include -#include - #include -#include - -void -helper_put_filedescriptors (jintArray fdArray, fd_set& fds, int& max_fd) -{ - jint* tmpFDArray = elements (fdArray); - - for (int index = 0; index < JvGetArrayLength (fdArray); index++) - { - FD_SET (tmpFDArray [index], &fds); - - if (tmpFDArray [index] > max_fd) - max_fd = tmpFDArray [index]; - } -} - -void -helper_get_filedescriptors (jintArray& fdArray, fd_set fds) -{ - jint* tmpFDArray = elements (fdArray); - - for (int index = 0; index < JvGetArrayLength (fdArray); index++) - if (!FD_ISSET (tmpFDArray [index], &fds)) - tmpFDArray [index] = 0; -} +#include jint gnu::java::nio::SelectorImpl::implSelect (jintArray read, jintArray write, jintArray except, jlong timeout) { - jint result; - int max_fd = 0; - fd_set read_fds; - fd_set write_fds; - fd_set except_fds; - struct timeval real_time_data; - struct timeval *time_data = NULL; + // FIXME: The API for implSelect is biased towards POSIX implementations. + jint* pReadFD = elements (read); + int nNbReadFDs = JvGetArrayLength (read); - real_time_data.tv_sec = 0; - real_time_data.tv_usec = timeout; + 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]; - // If not legal timeout value is given, use NULL. - // This means an infinite timeout. - if (timeout >= 0) + 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)) { - time_data = &real_time_data; + // 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; } - - // Reset all fd_set structures - FD_ZERO (&read_fds); - FD_ZERO (&write_fds); - FD_ZERO (&except_fds); - - // Fill the fd_set data structures for the _Jv_select() call. - helper_put_filedescriptors (read, read_fds, max_fd); - helper_put_filedescriptors (write, write_fds, max_fd); - helper_put_filedescriptors (except, except_fds, max_fd); - - // Actually do the select - result = _Jv_select (max_fd + 1, &read_fds, &write_fds, &except_fds, time_data); - - if (result < 0) + else if (dwRet < DWORD(WSA_WAIT_EVENT_0 + nNbEvents)) { - char* strerr = strerror (errno); - throw new ::java::io::IOException (JvNewStringUTF (strerr)); + 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; } - - // Set the file descriptors according to the values returned from select(). - helper_get_filedescriptors (read, read_fds); - helper_get_filedescriptors (write, write_fds); - helper_get_filedescriptors (except, except_fds); - - return result; + else + // None of the event objects was signalled, so nothing was + // selected. + return 0; } diff --git a/libjava/include/win32.h b/libjava/include/win32.h index 3de6f11b9ef..8dd2964e637 100644 --- a/libjava/include/win32.h +++ b/libjava/include/win32.h @@ -93,25 +93,36 @@ extern jstring _Jv_Win32NewString (LPCTSTR pcsz); /* Useful helper classes and methods. */ /* A C++ wrapper around a WSAEVENT which closes the event - in its destructor. If dwSelFlags is non-zero, we also - issue an WSAEventSelect on the socket descriptor with - the given flags; this is undone by a corresponding call - to WSAEventSelect(fd, 0, 0) in our destructor. */ + in its destructor. If dwSelFlags is non-zero, we also + issue an WSAEventSelect on the socket descriptor with + the given flags; this is undone by a corresponding call + to WSAEventSelect(fd, 0, 0) in our destructor. */ class WSAEventWrapper { public: - WSAEventWrapper(int fd, DWORD dwSelFlags); - ~WSAEventWrapper(); + // Default constructor. Call init() after this. + WSAEventWrapper(); + WSAEventWrapper(int fd, DWORD dwSelFlags); + ~WSAEventWrapper(); - WSAEVENT getEventHandle() - { - return m_hEvent; - } + // Used for two-step initialization after calling + // default constructor. + void init(int fd, DWORD dwSelFlags); + + int getFD() + { + return m_fd; + } + + WSAEVENT getEventHandle() + { + return m_hEvent; + } private: - WSAEVENT m_hEvent; - int m_fd; - DWORD m_dwSelFlags; + WSAEVENT m_hEvent; + int m_fd; + DWORD m_dwSelFlags; }; // Error string text. The int argument is compatible @@ -141,7 +152,6 @@ _Jv_ThrowSocketException (); extern void _Jv_platform_initialize (void); extern void _Jv_platform_initProperties (java::util::Properties*); extern jlong _Jv_platform_gettimeofday (); -extern int _Jv_select (int n, fd_set *, fd_set *, fd_set *, struct timeval *); extern int _Jv_pipe (int filedes[2]); extern void diff --git a/libjava/win32.cc b/libjava/win32.cc index ec089a52bd8..027333be738 100644 --- a/libjava/win32.cc +++ b/libjava/win32.cc @@ -143,11 +143,24 @@ _Jv_Win32TempString::~_Jv_Win32TempString() } // class WSAEventWrapper +WSAEventWrapper::WSAEventWrapper (): + m_hEvent(0), + m_fd(0), + m_dwSelFlags(0) +{} + WSAEventWrapper::WSAEventWrapper (int fd, DWORD dwSelFlags): m_hEvent(0), - m_fd(fd), - m_dwSelFlags(dwSelFlags) + m_fd(0), + m_dwSelFlags(0) { + init(fd, dwSelFlags); +} + +void WSAEventWrapper::init(int fd, DWORD dwSelFlags) +{ + m_fd = fd; + m_dwSelFlags = dwSelFlags; m_hEvent = WSACreateEvent (); if (dwSelFlags) WSAEventSelect(fd, m_hEvent, dwSelFlags); @@ -445,19 +458,6 @@ backtrace (void **__array, int __size) return i; } -int -_Jv_select (int n, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ - int r = ::select (n, readfds, writefds, exceptfds, timeout); - if (r == SOCKET_ERROR) - { - DWORD dwErrorCode = WSAGetLastError (); - throw new java::io::IOException (_Jv_WinStrError (dwErrorCode)); - } - return r; -} - int _Jv_pipe (int filedes[2]) {