1 // 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
select(jintArray read,jintArray write,jintArray except,jlong timeout)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 }
94