1 |
/* SelectorImpl.java -- |
/* SelectorImpl.java -- |
2 |
Copyright (C) 2002 Free Software Foundation, Inc. |
Copyright (C) 2002, 2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
37 |
|
|
38 |
package gnu.java.nio; |
package gnu.java.nio; |
39 |
|
|
40 |
|
import java.io.IOException; |
41 |
import java.nio.channels.ClosedSelectorException; |
import java.nio.channels.ClosedSelectorException; |
42 |
import java.nio.channels.SelectableChannel; |
import java.nio.channels.SelectableChannel; |
43 |
import java.nio.channels.SelectionKey; |
import java.nio.channels.SelectionKey; |
45 |
import java.nio.channels.spi.AbstractSelectableChannel; |
import java.nio.channels.spi.AbstractSelectableChannel; |
46 |
import java.nio.channels.spi.AbstractSelector; |
import java.nio.channels.spi.AbstractSelector; |
47 |
import java.nio.channels.spi.SelectorProvider; |
import java.nio.channels.spi.SelectorProvider; |
48 |
|
import java.util.Collections; |
49 |
import java.util.HashSet; |
import java.util.HashSet; |
50 |
import java.util.Iterator; |
import java.util.Iterator; |
51 |
import java.util.Set; |
import java.util.Set; |
52 |
|
|
53 |
public class SelectorImpl extends AbstractSelector |
public class SelectorImpl extends AbstractSelector |
54 |
{ |
{ |
55 |
boolean closed = false; |
private Set keys; |
56 |
Set keys, selected, canceled; |
private Set selected; |
57 |
|
|
58 |
public SelectorImpl (SelectorProvider provider) |
public SelectorImpl (SelectorProvider provider) |
59 |
{ |
{ |
60 |
super (provider); |
super (provider); |
61 |
|
|
62 |
|
keys = new HashSet (); |
63 |
|
selected = new HashSet (); |
64 |
|
} |
65 |
|
|
66 |
|
protected void finalize() throws Throwable |
67 |
|
{ |
68 |
|
close(); |
69 |
|
} |
70 |
|
|
71 |
|
protected final void implCloseSelector() |
72 |
|
throws IOException |
73 |
|
{ |
74 |
|
// FIXME: We surely need to do more here. |
75 |
|
wakeup(); |
76 |
} |
} |
77 |
|
|
78 |
public Set keys () |
public final Set keys() |
79 |
{ |
{ |
80 |
return keys; |
return Collections.unmodifiableSet (keys); |
81 |
} |
} |
82 |
|
|
83 |
public int selectNow () |
public int selectNow () |
87 |
|
|
88 |
public int select () |
public int select () |
89 |
{ |
{ |
90 |
return select (Long.MAX_VALUE); |
return select (-1); |
91 |
} |
} |
92 |
|
|
93 |
// private static native int java_do_select(int[] read, int[] write, |
// A timeout value of -1 means block forever. |
94 |
// int[] except, long timeout); |
private static native int java_do_select (int[] read, int[] write, |
95 |
|
int[] except, long timeout); |
96 |
|
|
97 |
private static int java_do_select (int[] read, int[] write, |
private int[] getFDsAsArray (int ops) |
|
int[] except, long timeout) |
|
98 |
{ |
{ |
99 |
return 0; |
int[] result; |
100 |
|
int counter = 0; |
101 |
|
Iterator it = keys.iterator (); |
102 |
|
|
103 |
|
// Count the number of file descriptors needed |
104 |
|
while (it.hasNext ()) |
105 |
|
{ |
106 |
|
SelectionKeyImpl key = (SelectionKeyImpl) it.next (); |
107 |
|
|
108 |
|
if ((key.interestOps () & ops) != 0) |
109 |
|
{ |
110 |
|
counter++; |
111 |
|
} |
112 |
|
} |
113 |
|
|
114 |
|
result = new int[counter]; |
115 |
|
|
116 |
|
counter = 0; |
117 |
|
it = keys.iterator (); |
118 |
|
|
119 |
|
// Fill the array with the file descriptors |
120 |
|
while (it.hasNext ()) |
121 |
|
{ |
122 |
|
SelectionKeyImpl key = (SelectionKeyImpl) it.next (); |
123 |
|
|
124 |
|
if ((key.interestOps () & ops) != 0) |
125 |
|
{ |
126 |
|
result[counter] = key.fd; |
127 |
|
counter++; |
128 |
|
} |
129 |
|
} |
130 |
|
|
131 |
|
return result; |
132 |
} |
} |
133 |
|
|
134 |
public int select (long timeout) |
public int select (long timeout) |
135 |
{ |
{ |
136 |
if (closed) |
if (!isOpen()) |
137 |
{ |
throw new ClosedSelectorException (); |
|
throw new ClosedSelectorException (); |
|
|
} |
|
138 |
|
|
139 |
if (keys == null) |
if (keys == null) |
140 |
{ |
{ |
141 |
return 0; |
return 0; |
142 |
} |
} |
143 |
|
|
144 |
int[] read = new int[keys.size ()]; |
int ret = 0; |
145 |
int[] write = new int[keys.size ()]; |
|
146 |
int[] except = new int[keys.size ()]; |
deregisterCancelledKeys(); |
147 |
int i = 0; |
|
148 |
|
// Set only keys with the needed interest ops into the arrays. |
149 |
|
int[] read = getFDsAsArray (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT); |
150 |
|
int[] write = getFDsAsArray (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT); |
151 |
|
int[] except = new int [0]; // FIXME: We dont need to check this yet |
152 |
|
|
153 |
|
// Call the native select () on all file descriptors. |
154 |
|
int anzahl = read.length + write.length + except.length; |
155 |
|
ret = java_do_select (read, write, except, timeout); |
156 |
|
|
157 |
Iterator it = keys.iterator (); |
Iterator it = keys.iterator (); |
158 |
|
|
159 |
while (it.hasNext ()) |
while (it.hasNext ()) |
160 |
{ |
{ |
161 |
SelectionKeyImpl k = (SelectionKeyImpl) it.next (); |
int ops = 0; |
162 |
read[i] = k.fd; |
SelectionKeyImpl key = (SelectionKeyImpl) it.next (); |
|
write[i] = k.fd; |
|
|
except[i] = k.fd; |
|
|
i++; |
|
|
} |
|
163 |
|
|
164 |
int ret = java_do_select (read, write, except, timeout); |
// If key is already selected retrieve old ready ops. |
165 |
|
if (selected.contains (key)) |
166 |
|
{ |
167 |
|
ops = key.readyOps (); |
168 |
|
} |
169 |
|
|
170 |
i = 0; |
// Set new ready read/accept ops |
171 |
it = keys.iterator (); |
for (int i = 0; i < read.length; i++) |
172 |
|
{ |
173 |
|
if (key.fd == read[i]) |
174 |
|
{ |
175 |
|
if (key.channel () instanceof ServerSocketChannelImpl) |
176 |
|
{ |
177 |
|
ops = ops | SelectionKey.OP_ACCEPT; |
178 |
|
} |
179 |
|
else |
180 |
|
{ |
181 |
|
ops = ops | SelectionKey.OP_READ; |
182 |
|
} |
183 |
|
} |
184 |
|
} |
185 |
|
|
186 |
while (it.hasNext ()) |
// Set new ready write ops |
187 |
{ |
for (int i = 0; i < write.length; i++) |
188 |
SelectionKeyImpl k = (SelectionKeyImpl) it.next (); |
{ |
189 |
|
if (key.fd == write[i]) |
190 |
|
{ |
191 |
|
ops = ops | SelectionKey.OP_WRITE; |
192 |
|
|
193 |
|
// if (key.channel ().isConnected ()) |
194 |
|
// { |
195 |
|
// ops = ops | SelectionKey.OP_WRITE; |
196 |
|
// } |
197 |
|
// else |
198 |
|
// { |
199 |
|
// ops = ops | SelectionKey.OP_CONNECT; |
200 |
|
// } |
201 |
|
} |
202 |
|
} |
203 |
|
|
204 |
|
// FIXME: We dont handle exceptional file descriptors yet. |
205 |
|
|
206 |
if (read[i] != -1 || |
// If key is not yet selected add it. |
207 |
write[i] != -1 || |
if (!selected.contains (key)) |
|
except[i] != -1) |
|
208 |
{ |
{ |
209 |
add_selected (k); |
add_selected (key); |
210 |
} |
} |
211 |
|
|
212 |
i++; |
// Set new ready ops |
213 |
} |
key.readyOps (key.interestOps () & ops); |
214 |
|
} |
215 |
|
|
216 |
|
deregisterCancelledKeys(); |
217 |
return ret; |
return ret; |
218 |
} |
} |
219 |
|
|
229 |
|
|
230 |
public void add (SelectionKeyImpl k) |
public void add (SelectionKeyImpl k) |
231 |
{ |
{ |
|
if (keys == null) |
|
|
keys = new HashSet (); |
|
|
|
|
232 |
keys.add (k); |
keys.add (k); |
233 |
} |
} |
234 |
|
|
235 |
void add_selected (SelectionKeyImpl k) |
void add_selected (SelectionKeyImpl k) |
236 |
{ |
{ |
237 |
if (selected == null) |
selected.add (k); |
|
selected = new HashSet (); |
|
|
|
|
|
selected.add(k); |
|
238 |
} |
} |
239 |
|
|
240 |
protected void implCloseSelector () |
private void deregisterCancelledKeys () |
241 |
{ |
{ |
242 |
closed = true; |
Iterator it = cancelledKeys().iterator(); |
243 |
|
|
244 |
|
while (it.hasNext ()) |
245 |
|
{ |
246 |
|
keys.remove ((SelectionKeyImpl) it.next ()); |
247 |
|
it.remove (); |
248 |
|
} |
249 |
} |
} |
250 |
|
|
251 |
protected SelectionKey register (SelectableChannel ch, int ops, Object att) |
protected SelectionKey register (SelectableChannel ch, int ops, Object att) |
252 |
{ |
{ |
253 |
return register ((AbstractSelectableChannel) ch, ops, att); |
return register ((AbstractSelectableChannel) ch, ops, att); |