| 1 | /* SelectorImpl.java --
|
|---|
| 2 | Copyright (C) 2002 Free Software Foundation, Inc.
|
|---|
| 3 |
|
|---|
| 4 | This file is part of GNU Classpath.
|
|---|
| 5 |
|
|---|
| 6 | GNU Classpath is free software; you can redistribute it and/or modify
|
|---|
| 7 | it under the terms of the GNU General Public License as published by
|
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 9 | any later version.
|
|---|
| 10 |
|
|---|
| 11 | GNU Classpath is distributed in the hope that it will be useful, but
|
|---|
| 12 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU General Public License
|
|---|
| 17 | along with GNU Classpath; see the file COPYING. If not, write to the
|
|---|
| 18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|---|
| 19 | 02111-1307 USA.
|
|---|
| 20 |
|
|---|
| 21 | Linking this library statically or dynamically with other modules is
|
|---|
| 22 | making a combined work based on this library. Thus, the terms and
|
|---|
| 23 | conditions of the GNU General Public License cover the whole
|
|---|
| 24 | combination.
|
|---|
| 25 |
|
|---|
| 26 | As a special exception, the copyright holders of this library give you
|
|---|
| 27 | permission to link this library with independent modules to produce an
|
|---|
| 28 | executable, regardless of the license terms of these independent
|
|---|
| 29 | modules, and to copy and distribute the resulting executable under
|
|---|
| 30 | terms of your choice, provided that you also meet, for each linked
|
|---|
| 31 | independent module, the terms and conditions of the license of that
|
|---|
| 32 | module. An independent module is a module which is not derived from
|
|---|
| 33 | or based on this library. If you modify this library, you may extend
|
|---|
| 34 | this exception to your version of the library, but you are not
|
|---|
| 35 | obligated to do so. If you do not wish to do so, delete this
|
|---|
| 36 | exception statement from your version. */
|
|---|
| 37 |
|
|---|
| 38 | package gnu.java.nio;
|
|---|
| 39 |
|
|---|
| 40 | import java.nio.channels.ClosedSelectorException;
|
|---|
| 41 | import java.nio.channels.SelectableChannel;
|
|---|
| 42 | import java.nio.channels.SelectionKey;
|
|---|
| 43 | import java.nio.channels.Selector;
|
|---|
| 44 | import java.nio.channels.spi.AbstractSelectableChannel;
|
|---|
| 45 | import java.nio.channels.spi.AbstractSelector;
|
|---|
| 46 | import java.nio.channels.spi.SelectorProvider;
|
|---|
| 47 | import java.util.HashSet;
|
|---|
| 48 | import java.util.Iterator;
|
|---|
| 49 | import java.util.Set;
|
|---|
| 50 |
|
|---|
| 51 | public class SelectorImpl extends AbstractSelector
|
|---|
| 52 | {
|
|---|
| 53 | boolean closed = false;
|
|---|
| 54 | Set keys, selected, canceled;
|
|---|
| 55 |
|
|---|
| 56 | public SelectorImpl (SelectorProvider provider)
|
|---|
| 57 | {
|
|---|
| 58 | super (provider);
|
|---|
| 59 |
|
|---|
| 60 | keys = new HashSet ();
|
|---|
| 61 | selected = new HashSet ();
|
|---|
| 62 | canceled = new HashSet ();
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | public Set keys ()
|
|---|
| 66 | {
|
|---|
| 67 | return keys;
|
|---|
| 68 | }
|
|---|
| 69 |
|
|---|
| 70 | public int selectNow ()
|
|---|
| 71 | {
|
|---|
| 72 | return select (1);
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | public int select ()
|
|---|
| 76 | {
|
|---|
| 77 | return select (-1);
|
|---|
| 78 | }
|
|---|
| 79 |
|
|---|
| 80 | // A timeout value of -1 means block forever.
|
|---|
| 81 | private static native int java_do_select (int[] read, int[] write,
|
|---|
| 82 | int[] except, long timeout);
|
|---|
| 83 |
|
|---|
| 84 | private int[] getFDsAsArray (int ops)
|
|---|
| 85 | {
|
|---|
| 86 | int[] result;
|
|---|
| 87 | int counter = 0;
|
|---|
| 88 | Iterator it = keys.iterator ();
|
|---|
| 89 |
|
|---|
| 90 | // Count the number of file descriptors needed
|
|---|
| 91 | while (it.hasNext ())
|
|---|
| 92 | {
|
|---|
| 93 | SelectionKeyImpl key = (SelectionKeyImpl) it.next ();
|
|---|
| 94 |
|
|---|
| 95 | if ((key.interestOps () & ops) != 0)
|
|---|
| 96 | {
|
|---|
| 97 | counter++;
|
|---|
| 98 | }
|
|---|
| 99 | }
|
|---|
| 100 |
|
|---|
| 101 | result = new int[counter];
|
|---|
| 102 |
|
|---|
| 103 | counter = 0;
|
|---|
| 104 | it = keys.iterator ();
|
|---|
| 105 |
|
|---|
| 106 | // Fill the array with the file descriptors
|
|---|
| 107 | while (it.hasNext ())
|
|---|
| 108 | {
|
|---|
| 109 | SelectionKeyImpl key = (SelectionKeyImpl) it.next ();
|
|---|
| 110 |
|
|---|
| 111 | if ((key.interestOps () & ops) != 0)
|
|---|
| 112 | {
|
|---|
| 113 | result[counter] = key.fd;
|
|---|
| 114 | counter++;
|
|---|
| 115 | }
|
|---|
| 116 | }
|
|---|
| 117 |
|
|---|
| 118 | return result;
|
|---|
| 119 | }
|
|---|
| 120 |
|
|---|
| 121 | public int select (long timeout)
|
|---|
| 122 | {
|
|---|
| 123 | if (closed)
|
|---|
| 124 | {
|
|---|
| 125 | throw new ClosedSelectorException ();
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | if (keys == null)
|
|---|
| 129 | {
|
|---|
| 130 | return 0;
|
|---|
| 131 | }
|
|---|
| 132 |
|
|---|
| 133 | int ret = 0;
|
|---|
| 134 |
|
|---|
| 135 | deregisterCanceledKeys ();
|
|---|
| 136 |
|
|---|
| 137 | // Set only keys with the needed interest ops into the arrays.
|
|---|
| 138 | int[] read = getFDsAsArray (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT);
|
|---|
| 139 | int[] write = getFDsAsArray (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
|
|---|
| 140 | int[] except = new int [0]; // FIXME: We dont need to check this yet
|
|---|
| 141 |
|
|---|
| 142 | // Call the native select () on all file descriptors.
|
|---|
| 143 | int anzahl = read.length + write.length + except.length;
|
|---|
| 144 | ret = java_do_select (read, write, except, timeout);
|
|---|
| 145 |
|
|---|
| 146 | Iterator it = keys.iterator ();
|
|---|
| 147 |
|
|---|
| 148 | while (it.hasNext ())
|
|---|
| 149 | {
|
|---|
| 150 | int ops = 0;
|
|---|
| 151 | SelectionKeyImpl key = (SelectionKeyImpl) it.next ();
|
|---|
| 152 |
|
|---|
| 153 | // If key is already selected retrieve old ready ops.
|
|---|
| 154 | if (selected.contains (key))
|
|---|
| 155 | {
|
|---|
| 156 | ops = key.readyOps ();
|
|---|
| 157 | }
|
|---|
| 158 |
|
|---|
| 159 | // Set new ready read/accept ops
|
|---|
| 160 | for (int i = 0; i < read.length; i++)
|
|---|
| 161 | {
|
|---|
| 162 | if (key.fd == read[i])
|
|---|
| 163 | {
|
|---|
| 164 | if (key.channel () instanceof ServerSocketChannelImpl)
|
|---|
| 165 | {
|
|---|
| 166 | ops = ops | SelectionKey.OP_ACCEPT;
|
|---|
| 167 | }
|
|---|
| 168 | else
|
|---|
| 169 | {
|
|---|
| 170 | ops = ops | SelectionKey.OP_READ;
|
|---|
| 171 | }
|
|---|
| 172 | }
|
|---|
| 173 | }
|
|---|
| 174 |
|
|---|
| 175 | // Set new ready write ops
|
|---|
| 176 | for (int i = 0; i < write.length; i++)
|
|---|
| 177 | {
|
|---|
| 178 | if (key.fd == write[i])
|
|---|
| 179 | {
|
|---|
| 180 | ops = ops | SelectionKey.OP_WRITE;
|
|---|
| 181 |
|
|---|
| 182 | // if (key.channel ().isConnected ())
|
|---|
| 183 | // {
|
|---|
| 184 | // ops = ops | SelectionKey.OP_WRITE;
|
|---|
| 185 | // }
|
|---|
| 186 | // else
|
|---|
| 187 | // {
|
|---|
| 188 | // ops = ops | SelectionKey.OP_CONNECT;
|
|---|
| 189 | // }
|
|---|
| 190 | }
|
|---|
| 191 | }
|
|---|
| 192 |
|
|---|
| 193 | // FIXME: We dont handle exceptional file descriptors yet.
|
|---|
| 194 |
|
|---|
| 195 | // If key is not yet selected add it.
|
|---|
| 196 | if (!selected.contains (key))
|
|---|
| 197 | {
|
|---|
| 198 | add_selected (key);
|
|---|
| 199 | }
|
|---|
| 200 |
|
|---|
| 201 | // Set new ready ops
|
|---|
| 202 | key.readyOps (key.interestOps () & ops);
|
|---|
| 203 | }
|
|---|
| 204 |
|
|---|
| 205 | deregisterCanceledKeys ();
|
|---|
| 206 | return ret;
|
|---|
| 207 | }
|
|---|
| 208 |
|
|---|
| 209 | public Set selectedKeys ()
|
|---|
| 210 | {
|
|---|
| 211 | return selected;
|
|---|
| 212 | }
|
|---|
| 213 |
|
|---|
| 214 | public Selector wakeup ()
|
|---|
| 215 | {
|
|---|
| 216 | return null;
|
|---|
| 217 | }
|
|---|
| 218 |
|
|---|
| 219 | public void add (SelectionKeyImpl k)
|
|---|
| 220 | {
|
|---|
| 221 | keys.add (k);
|
|---|
| 222 | }
|
|---|
| 223 |
|
|---|
| 224 | void add_selected (SelectionKeyImpl k)
|
|---|
| 225 | {
|
|---|
| 226 | selected.add (k);
|
|---|
| 227 | }
|
|---|
| 228 |
|
|---|
| 229 | protected void implCloseSelector ()
|
|---|
| 230 | {
|
|---|
| 231 | closed = true;
|
|---|
| 232 | }
|
|---|
| 233 |
|
|---|
| 234 | private void deregisterCanceledKeys ()
|
|---|
| 235 | {
|
|---|
| 236 | Iterator it = canceled.iterator ();
|
|---|
| 237 |
|
|---|
| 238 | while (it.hasNext ())
|
|---|
| 239 | {
|
|---|
| 240 | keys.remove ((SelectionKeyImpl) it.next ());
|
|---|
| 241 | it.remove ();
|
|---|
| 242 | }
|
|---|
| 243 | }
|
|---|
| 244 |
|
|---|
| 245 | protected SelectionKey register (SelectableChannel ch, int ops, Object att)
|
|---|
| 246 | {
|
|---|
| 247 | return register ((AbstractSelectableChannel) ch, ops, att);
|
|---|
| 248 | }
|
|---|
| 249 |
|
|---|
| 250 | protected SelectionKey register (AbstractSelectableChannel ch, int ops,
|
|---|
| 251 | Object att)
|
|---|
| 252 | {
|
|---|
| 253 | // // filechannel is not selectable ?
|
|---|
| 254 | // if (ch instanceof FileChannelImpl)
|
|---|
| 255 | // {
|
|---|
| 256 | // FileChannelImpl fc = (FileChannelImpl) ch;
|
|---|
| 257 | // SelectionKeyImpl impl = new SelectionKeyImpl (ch, this, fc.fd);
|
|---|
| 258 | // keys.add (impl);
|
|---|
| 259 | // impl.interestOps (ops);
|
|---|
| 260 | // impl.attach (att);
|
|---|
| 261 | // return impl;
|
|---|
| 262 | // }
|
|---|
| 263 | // else
|
|---|
| 264 |
|
|---|
| 265 | if (ch instanceof SocketChannelImpl)
|
|---|
| 266 | {
|
|---|
| 267 | SocketChannelImpl sc = (SocketChannelImpl) ch;
|
|---|
| 268 | SelectionKeyImpl impl = new SelectionKeyImpl (ch, this, sc.fd);
|
|---|
| 269 | add (impl);
|
|---|
| 270 | impl.interestOps (ops);
|
|---|
| 271 | impl.attach (att);
|
|---|
| 272 | return impl;
|
|---|
| 273 | }
|
|---|
| 274 | else if (ch instanceof DatagramChannelImpl)
|
|---|
| 275 | {
|
|---|
| 276 | DatagramChannelImpl dc = (DatagramChannelImpl) ch;
|
|---|
| 277 | SelectionKeyImpl impl = new SelectionKeyImpl (ch, this, dc.fd);
|
|---|
| 278 | add (impl);
|
|---|
| 279 | impl.interestOps (ops);
|
|---|
| 280 | impl.attach (att);
|
|---|
| 281 | return impl;
|
|---|
| 282 | }
|
|---|
| 283 | else if (ch instanceof ServerSocketChannelImpl)
|
|---|
| 284 | {
|
|---|
| 285 | ServerSocketChannelImpl ssc = (ServerSocketChannelImpl) ch;
|
|---|
| 286 | SelectionKeyImpl impl = new SelectionKeyImpl (ch, this, ssc.fd);
|
|---|
| 287 | add (impl);
|
|---|
| 288 | impl.interestOps (ops);
|
|---|
| 289 | impl.attach (att);
|
|---|
| 290 | return impl;
|
|---|
| 291 | }
|
|---|
| 292 | else
|
|---|
| 293 | {
|
|---|
| 294 | System.err.println ("INTERNAL ERROR, no known channel type");
|
|---|
| 295 | }
|
|---|
| 296 |
|
|---|
| 297 | return null;
|
|---|
| 298 | }
|
|---|
| 299 | }
|
|---|