1 package org.openflow.example;
3 import java.io.IOException;
4 import java.nio.channels.CancelledKeyException;
5 import java.nio.channels.ClosedChannelException;
6 import java.nio.channels.SelectableChannel;
7 import java.nio.channels.SelectionKey;
8 import java.nio.channels.Selector;
9 import java.nio.channels.spi.SelectorProvider;
10 import java.util.Iterator;
11 import java.util.Queue;
12 import java.util.concurrent.ConcurrentLinkedQueue;
15 * Dirt simple SelectLoop for simple java controller
19 public class SelectLoop {
20 protected SelectListener callback;
21 protected boolean dontStop;
22 protected Object registrationLock;
23 protected int registrationRequests = 0;
24 protected Queue<Object[]> registrationQueue;
25 protected Selector selector;
26 protected long timeout;
28 public SelectLoop(SelectListener cb) throws IOException {
31 selector = SelectorProvider.provider().openSelector();
32 registrationLock = new Object();
33 registrationQueue = new ConcurrentLinkedQueue<Object[]>();
38 * Initializes this SelectLoop
39 * @param cb the callback to call when select returns
40 * @param timeout the timeout value in milliseconds that select will be
44 public SelectLoop(SelectListener cb, long timeout) throws IOException {
47 selector = SelectorProvider.provider().openSelector();
48 registrationLock = new Object();
49 registrationQueue = new ConcurrentLinkedQueue<Object[]>();
50 this.timeout = timeout;
53 public void register(SelectableChannel ch, int ops, Object arg)
54 throws ClosedChannelException {
55 registrationQueue.add(new Object[] {ch, ops, arg});
59 * Registers the supplied SelectableChannel with this SelectLoop. Note this
60 * method blocks until registration proceeds. It is advised that
61 * SelectLoop is intialized with a timeout value when using this method.
62 * @param ch the channel
63 * @param ops interest ops
64 * @param arg argument that will be returned with the SelectListener
66 * @throws ClosedChannelException
68 public synchronized SelectionKey registerBlocking(SelectableChannel ch, int ops, Object arg)
69 throws ClosedChannelException {
70 synchronized (registrationLock) {
71 registrationRequests++;
74 SelectionKey key = ch.register(selector, ops, arg);
75 synchronized (registrationLock) {
76 registrationRequests--;
77 registrationLock.notifyAll();
83 * Main top-level IO loop this dispatches all IO events and timer events
84 * together I believe this is fairly efficient
86 public void doLoop() throws IOException {
88 processRegistrationQueue();
91 nEvents = selector.select(timeout);
93 for (Iterator<SelectionKey> i = selector.selectedKeys()
94 .iterator(); i.hasNext();) {
95 SelectionKey sk = i.next();
101 Object arg = sk.attachment();
102 callback.handleEvent(sk, arg);
106 if (this.registrationQueue.size() > 0)
107 processRegistrationQueue();
109 if (registrationRequests > 0) {
110 synchronized (registrationLock) {
111 while (registrationRequests > 0) {
113 registrationLock.wait();
114 } catch (InterruptedException e) {
123 protected void processRegistrationQueue() {
124 // add any elements in queue
125 for (Iterator<Object[]> it = registrationQueue.iterator(); it.hasNext();) {
126 Object[] args = it.next();
127 SelectableChannel ch = (SelectableChannel) args[0];
129 ch.register(selector, (Integer) args[1], args[2]);
130 } catch (CancelledKeyException cke) {
132 } catch (ClosedChannelException e) {
139 * Force this select loop to return immediately and re-enter select, useful
140 * for example if a new item has been added to the select loop while it
141 * was already blocked.
143 public void wakeup() {
144 if (selector != null) {
150 * Shuts down this select loop, may return before it has fully shutdown
152 public void shutdown() {
153 this.dontStop = false;