/[classpath]/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c
ViewVC logotype

Diff of /classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.2.1 by gnu_andrew, Sat Jan 15 17:02:23 2005 UTC revision 1.1.2.2 by gnu_andrew, Wed Mar 23 21:00:04 2005 UTC
# Line 1  Line 1 
1  /* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class  /* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class
2     Copyright (C) 2004 Free Software Foundation, Inc.     Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 35  this exception to your version of the li Line 35  this exception to your version of the li
35  obligated to do so.  If you do not wish to do so, delete this  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */  exception statement from your version. */
37    
38    #include <sys/select.h>
39    #include <sys/time.h>
40    
41    #include <string.h>
42    
43  #include <config.h>  #include <config.h>
44  #include <errno.h>  #include <errno.h>
45    
# Line 43  exception statement from your version. * Line 48  exception statement from your version. *
48    
49  #include "gnu_java_nio_VMSelector.h"  #include "gnu_java_nio_VMSelector.h"
50    
51  #define IO_EXCEPTION "java/io/IOException"  /* Amount of characters in the error message buffer for strerror_r. */
52    #define BUF_SIZE 250
53    
54    void
55    helper_put_filedescriptors(JNIEnv *, jintArray, fd_set *, int *);
56    
57    void
58    helper_get_filedescriptors (JNIEnv *, jintArray*, fd_set *);
59    
60    void
61    helper_reset (JNIEnv *, jintArray*);
62    
63    int
64    helper_select (JNIEnv *, jclass, jmethodID,
65                    int, fd_set *, fd_set  *, fd_set *,
66                    struct timeval *);
67    
68    void
69    helper_put_filedescriptors(JNIEnv *env, jintArray fdArray, fd_set *fds, int *max_fd)
70    {
71            jint *tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0);
72            int size = (*env)->GetArrayLength(env, fdArray);
73            int index, fd;
74            
75            for( index = 0; index < size; index++)
76            {
77                    fd = tmpFDArray [index];
78            
79            if (fd > 0)
80            {
81              FD_SET (tmpFDArray [index], fds);
82    
83              if (tmpFDArray [index] > (*max_fd))
84                (*max_fd) = tmpFDArray [index];
85            }
86        }
87    }
88    
89    void
90    helper_get_filedescriptors (JNIEnv *env, jintArray* fdArray, fd_set *fds)
91    {
92            jint *tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0);
93            int size = (*env)->GetArrayLength(env, fdArray);
94            int index, fd;
95    
96            for (index = 0; index < size; index++)
97        {
98          fd = tmpFDArray [index];
99          if (fd < 0 || !FD_ISSET (fd, fds))
100            tmpFDArray [index] = 0;
101        }
102    }
103    
104    void
105    helper_reset (JNIEnv *env, jintArray* fdArray)
106    {
107            jint* tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0);
108            int size = (*env)->GetArrayLength(env, fdArray);
109            int index;
110    
111            for (index = 0; index < size; index++)
112                    tmpFDArray [index] = 0;
113    }
114    
115    /* A wrapper for select() which ignores EINTR.
116     * Taken from gclib's posix.cc
117     */
118    int
119    helper_select (JNIEnv *env, jclass thread_class, jmethodID thread_interrupted,
120                    int n, fd_set *readfds, fd_set  *writefds, fd_set *exceptfds,
121                    struct timeval *timeout)
122    {
123    #ifdef HAVE_SYS_SELECT_H
124            /* If we have a timeout, compute the absolute ending time. */
125            struct timeval end, delay, after;
126            int r;
127      
128            if (timeout)
129            {
130                    gettimeofday (&end, NULL);
131                    
132                    end.tv_usec += timeout->tv_usec;
133                    
134                    if (end.tv_usec >= 1000000)
135                    {
136                            ++end.tv_sec;
137                            end.tv_usec -= 1000000;
138                    }
139                    
140                    end.tv_sec += timeout->tv_sec;
141                    delay = *timeout;
142            }
143            else
144            {
145                    /* Placate compiler. */
146                    delay.tv_sec = delay.tv_usec = 0;
147            }
148    
149            while (1)
150            {
151                    r = select (n, readfds, writefds, exceptfds,
152                          timeout ? &delay : NULL);
153                          
154                    if (r != -1 || errno != EINTR)
155                            return r;
156    
157                    /* Here we know we got EINTR. */
158                    if ( (*env)->CallStaticBooleanMethod(env, thread_class, thread_interrupted) )
159                    {
160                            return EINTR;
161                    }
162    
163                    if (timeout)
164                    {
165                            gettimeofday (&after, NULL);
166                            
167                            /* Now compute new timeout argument. */
168                            delay.tv_usec = end.tv_usec - after.tv_usec;
169                            delay.tv_sec = end.tv_sec - after.tv_sec;
170                            
171                            if (delay.tv_usec < 0)
172                            {
173                                    --delay.tv_sec;
174                                    delay.tv_usec += 1000000;
175                            }
176    
177                            if (delay.tv_sec < 0)
178                            {
179                                    /* We assume that the user wants a valid select() call
180                                     * more than precise timing.  So if we get a series of
181                                     * EINTR we just keep trying with delay 0 until we get a
182                                     * valid result.
183                                     */
184                                    delay.tv_sec = 0;
185                            }
186                    }
187            }
188    #else /* HAVE_SYS_SELECT_H */
189      return 0;
190    #endif
191    
192    }
193    
194  JNIEXPORT jint JNICALL  JNIEXPORT jint JNICALL
195  Java_gnu_java_nio_VMSelector_select (JNIEnv *env,  Java_gnu_java_nio_VMSelector_select (JNIEnv *env,
196                                       jclass obj __attribute__ ((__unused__)),                                       jclass obj __attribute__ ((__unused__)),
197                                       jintArray read                                       jintArray read,
198                                       __attribute__ ((__unused__)),                                       jintArray write,
199                                       jintArray write                                       jintArray except,
200                                       __attribute__ ((__unused__)),                                       jlong timeout)
                                      jintArray except  
                                      __attribute__ ((__unused__)),  
                                      jlong timeout  
                                      __attribute__ ((__unused__)))  
201  {  {
202    JCL_ThrowException (env, IO_EXCEPTION, "gnu.java.nio.VMSelector.select(): not implemented");          jint result;
203    return 0;          jclass thread_class = (*env)->FindClass(env, "java/lang/Thread");
204            jmethodID thread_current_thread = (*env)->GetStaticMethodID(env, thread_class, "currentThread", "()Ljava/lang/Thread;");
205            jmethodID thread_interrupt = (*env)->GetMethodID(env, thread_class, "interrupt", "()V");
206            jmethodID thread_interrupted = (*env)->GetMethodID(env, thread_class, "interrupted", "()Z");
207            jobject current_thread;
208            int max_fd = 0;
209            fd_set read_fds;
210            fd_set write_fds;
211            fd_set except_fds;
212            struct timeval real_time_data;
213            struct timeval *time_data = NULL;
214            char message_buf[BUF_SIZE+1];
215            
216            /* If a legal timeout value isn't given, use NULL.
217             * This means an infinite timeout. The specification
218             * also says that a zero timeout should be treated
219             * as infinite. Otherwise (if the timeout value is legal),
220             * fill our timeval struct and use it for the select.
221             */
222            if (timeout > 0)
223            {
224                    real_time_data.tv_sec = timeout / 1000;
225                    real_time_data.tv_usec = (timeout % 1000) * 1000;
226                    time_data = &real_time_data;
227            }
228    
229            /* Reset all fd_set structures */
230            FD_ZERO (&read_fds);
231            FD_ZERO (&write_fds);
232            FD_ZERO (&except_fds);
233    
234            /* Fill the fd_set data structures for the _Jv_select() call. */
235            helper_put_filedescriptors (env, read, &read_fds, &max_fd);
236            helper_put_filedescriptors (env, write, &write_fds, &max_fd);
237            helper_put_filedescriptors (env, except, &except_fds, &max_fd);
238    
239            /* Actually do the select */
240            result = helper_select (env, thread_class, thread_interrupted, max_fd + 1, &read_fds, &write_fds,
241                                                                    &except_fds, time_data);
242    
243            if( result == EINTR ) {
244                    /* The behavior of JRE 1.4.1 is that no exception is thrown
245                     * when the thread is interrupted, but the thread's interrupt
246                     * status is set. Clear all of our select sets and return 0,
247                     * indicating that nothing was selected.
248                     */
249                    current_thread = (*env)->CallStaticObjectMethod(env, thread_class, thread_current_thread);
250                    (*env)->CallVoidMethod(env, current_thread, thread_interrupt);
251          
252                    helper_reset (env, read);
253                    helper_reset (env, write);
254                    helper_reset (env, except);
255                    
256                    return 0;
257            }
258            
259            if (result < 0)
260        {
261            if( strerror_r(errno, message_buf, BUF_SIZE) )
262            {
263                    /* This would mean that message_buf was to small
264                     * to hold the error message.
265                     */
266                    JCL_ThrowException(env, "java/lang/InternalError",
267                            "Not enough space in message buffer.");
268                    return 0;
269            }
270            
271                    JCL_ThrowException (env, "java/io/IOException", message_buf);
272                    return 0;
273        }
274    
275            /* Set the file descriptors according to the values returned from select(). */
276            helper_get_filedescriptors (env, read, &read_fds);
277            helper_get_filedescriptors (env, write, &write_fds);
278            helper_get_filedescriptors (env, except, &except_fds);
279    
280            return result;
281  }  }
282    

Legend:
Removed from v.1.1.2.1  
changed lines
  Added in v.1.1.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26