| 1 | 756 | jeremybenn | // natVMSelectorImplWin32.cc
 | 
      
         | 2 |  |  |  
 | 
      
         | 3 |  |  | /* Copyright (C) 2003, 2004, 2007  Free Software Foundation
 | 
      
         | 4 |  |  |  
 | 
      
         | 5 |  |  |    This file is part of libgcj.
 | 
      
         | 6 |  |  |  
 | 
      
         | 7 |  |  | This software is copyrighted work licensed under the terms of the
 | 
      
         | 8 |  |  | Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
      
         | 9 |  |  | details.  */
 | 
      
         | 10 |  |  |  
 | 
      
         | 11 |  |  | #include <config.h>
 | 
      
         | 12 |  |  | #include <platform.h>
 | 
      
         | 13 |  |  |  
 | 
      
         | 14 |  |  | #include <gnu/java/nio/VMSelector.h>
 | 
      
         | 15 |  |  | #include <java/lang/Thread.h>
 | 
      
         | 16 |  |  |  
 | 
      
         | 17 |  |  | jint
 | 
      
         | 18 |  |  | gnu::java::nio::VMSelector::select (jintArray read, jintArray write,
 | 
      
         | 19 |  |  |                                     jintArray except, jlong timeout)
 | 
      
         | 20 |  |  | {
 | 
      
         | 21 |  |  |   // FIXME: The API for implSelect is biased towards POSIX implementations.
 | 
      
         | 22 |  |  |   jint* pReadFD = elements (read);
 | 
      
         | 23 |  |  |   int nNbReadFDs = JvGetArrayLength (read);
 | 
      
         | 24 |  |  |  
 | 
      
         | 25 |  |  |   jint* pWriteFD = elements (write);
 | 
      
         | 26 |  |  |   int nNbWriteFDs = JvGetArrayLength (write);
 | 
      
         | 27 |  |  |  
 | 
      
         | 28 |  |  |   int nNbEvents = nNbReadFDs + nNbWriteFDs;
 | 
      
         | 29 |  |  |  
 | 
      
         | 30 |  |  |   // Create and initialize our event wrapper array
 | 
      
         | 31 |  |  |  
 | 
      
         | 32 |  |  |   // FIXME: We're creating fresh WSAEVENTs for each call.
 | 
      
         | 33 |  |  |   // This is inefficient. It would probably be better to cache these
 | 
      
         | 34 |  |  |   // in the Win32 socket implementation class.
 | 
      
         | 35 |  |  |   WSAEventWrapper aArray[nNbEvents];
 | 
      
         | 36 |  |  |  
 | 
      
         | 37 |  |  |   int nCurIndex = 0;
 | 
      
         | 38 |  |  |   for (int i=0; i < nNbReadFDs; ++i)
 | 
      
         | 39 |  |  |     aArray[nCurIndex++].init(pReadFD[i], FD_ACCEPT | FD_READ);
 | 
      
         | 40 |  |  |  
 | 
      
         | 41 |  |  |   for (int i=0; i < nNbWriteFDs; ++i)
 | 
      
         | 42 |  |  |     aArray[nCurIndex++].init(pWriteFD[i], FD_WRITE);
 | 
      
         | 43 |  |  |  
 | 
      
         | 44 |  |  |   // Build our array of WSAEVENTs to wait on. Also throw in our thread's
 | 
      
         | 45 |  |  |   // interrupt event in order to detect thread interruption.
 | 
      
         | 46 |  |  |   HANDLE arh[nNbEvents + 1];
 | 
      
         | 47 |  |  |   for (int i=0; i < nNbEvents; ++i)
 | 
      
         | 48 |  |  |     arh[i] = aArray[i].getEventHandle();
 | 
      
         | 49 |  |  |   arh[nNbEvents] = _Jv_Win32GetInterruptEvent ();
 | 
      
         | 50 |  |  |  
 | 
      
         | 51 |  |  |   // A timeout value of 0 needs to be treated as infinite.
 | 
      
         | 52 |  |  |   if (timeout <= 0)
 | 
      
         | 53 |  |  |     timeout = WSA_INFINITE;
 | 
      
         | 54 |  |  |  
 | 
      
         | 55 |  |  |   // Do the select.
 | 
      
         | 56 |  |  |   DWORD dwRet = WSAWaitForMultipleEvents (nNbEvents+1, arh, 0, timeout, false);
 | 
      
         | 57 |  |  |  
 | 
      
         | 58 |  |  |   if (dwRet == WSA_WAIT_FAILED)
 | 
      
         | 59 |  |  |     _Jv_ThrowIOException ();
 | 
      
         | 60 |  |  |  
 | 
      
         | 61 |  |  |   // Before we do anything else, clear output file descriptor arrays.
 | 
      
         | 62 |  |  |   memset(pReadFD, 0, sizeof(jint) * nNbReadFDs);
 | 
      
         | 63 |  |  |   memset(pWriteFD, 0, sizeof(jint) * nNbWriteFDs);
 | 
      
         | 64 |  |  |   memset(elements (except), 0, sizeof(jint) * JvGetArrayLength (except));
 | 
      
         | 65 |  |  |  
 | 
      
         | 66 |  |  |   if (dwRet == DWORD(WSA_WAIT_EVENT_0 + nNbEvents))
 | 
      
         | 67 |  |  |     {
 | 
      
         | 68 |  |  |       // We were interrupted. Set the current thread's interrupt
 | 
      
         | 69 |  |  |       // status and get out of here, with nothing selected..
 | 
      
         | 70 |  |  |       ::java::lang::Thread::currentThread ()->interrupt ();
 | 
      
         | 71 |  |  |       return 0;
 | 
      
         | 72 |  |  |     }
 | 
      
         | 73 |  |  |   else if (dwRet < DWORD(WSA_WAIT_EVENT_0 + nNbEvents))
 | 
      
         | 74 |  |  |     {
 | 
      
         | 75 |  |  |       int nSelectedEventIndex = dwRet - WSA_WAIT_EVENT_0;
 | 
      
         | 76 |  |  |  
 | 
      
         | 77 |  |  |       // Record the selected file descriptor.
 | 
      
         | 78 |  |  |       // FIXME: This implementation only allows one file descriptor
 | 
      
         | 79 |  |  |       // to be selected at a time. Remedy this by looping on
 | 
      
         | 80 |  |  |       // WSAWaitForMultipleEvents 'til nothing more is selected.
 | 
      
         | 81 |  |  |       jint fd = aArray[nSelectedEventIndex].getFD();
 | 
      
         | 82 |  |  |       if (nSelectedEventIndex < nNbReadFDs)
 | 
      
         | 83 |  |  |         pReadFD[0] = fd;
 | 
      
         | 84 |  |  |       else
 | 
      
         | 85 |  |  |         pWriteFD[0] = fd;
 | 
      
         | 86 |  |  |  
 | 
      
         | 87 |  |  |       return 1;
 | 
      
         | 88 |  |  |     }
 | 
      
         | 89 |  |  |   else
 | 
      
         | 90 |  |  |     // None of the event objects was signalled, so nothing was
 | 
      
         | 91 |  |  |     // selected.
 | 
      
         | 92 |  |  |     return 0;
 | 
      
         | 93 |  |  | }
 |