summaryrefslogtreecommitdiffstats
path: root/simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java
diff options
context:
space:
mode:
Diffstat (limited to 'simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java')
-rw-r--r--simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java193
1 files changed, 193 insertions, 0 deletions
diff --git a/simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java b/simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java
new file mode 100644
index 0000000..a9e78e9
--- /dev/null
+++ b/simple/simple-transport/src/main/java/org/simpleframework/transport/reactor/ActionSelector.java
@@ -0,0 +1,193 @@
+/*
+ * ActionSelector.java February 2013
+ *
+ * Copyright (C) 2013, Niall Gallagher <niallg@users.sf.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.simpleframework.transport.reactor;
+
+import java.io.IOException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * The <code>ActionSelector</code> object is used to perform socket
+ * based selection with the help of the <code>ActionSet</code> object.
+ * All registered channels have an associated action set. The action
+ * set contains a set of actions that should be executed when the
+ * selector selects the channel.
+ *
+ * @author Niall Gallagher
+ */
+class ActionSelector {
+
+ /**
+ * This is the selector used to perform the select operations.
+ */
+ private final Selector selector;
+
+ /**
+ * Constructor for the <code>ActionSelector</code> object. This is
+ * used to create a selector that can register socket channels
+ * with an associated <code>ActionSet</code>. The set can then be
+ * used to store actions to be executed upon selection.
+ */
+ public ActionSelector() throws IOException {
+ this.selector = Selector.open();
+ }
+
+ /**
+ * This is used to perform a select on the selector. This returns
+ * the number of channels that have been selected. If this returns
+ * a number greater than zero the <code>ready</code> method can
+ * be used to acquire the actions that are ready for execution.
+ *
+ * @param timeout this is the timeout associated with the select
+ *
+ * @return this returns the number of channels that are ready
+ */
+ public int select(long timeout) throws IOException {
+ return selector.select(timeout);
+ }
+
+ /**
+ * This performs the actual registration of the channel for selection
+ * based on the provided interest bitmask. When the channel has been
+ * registered for selection this returns an <code>ActionSet</code>
+ * for the selection key. The set can then be used to register the
+ * actions that should be executed when selection succeeds.
+ *
+ * @param channel this is the channel to register for selection
+ * @param interest this is the interested operations bitmask
+ *
+ * @return this is the action set associated with the registration
+ */
+ public ActionSet register(SelectableChannel channel, int interest) throws IOException {
+ SelectionKey key = channel.register(selector, interest);
+ Object value = key.attachment();
+
+ if(value == null) {
+ value = new ActionSet(key);
+ key.attach(value);
+ }
+ return (ActionSet)value;
+ }
+
+ /**
+ * This is used to acquire all the action sets that are associated
+ * with this selector. Only action sets that have a valid selection
+ * key are returned. Modification of the list will not affect the
+ * associated selector instance.
+ *
+ * @return this returns all the associated action sets for this
+ */
+ public List<ActionSet> registeredSets() {
+ Set<SelectionKey> keys = selector.keys();
+ Iterator<SelectionKey> ready = keys.iterator();
+
+ return registeredSets(ready);
+ }
+
+ /**
+ * This is used to acquire all the action sets that are associated
+ * with this selector. Only action sets that have a valid selection
+ * key are returned. Modification of the list will not affect the
+ * associated selector instance.
+ *
+ * @param keys the selection keys to get the associated sets from
+ *
+ * @return this returns all the associated action sets for this
+ */
+ private List<ActionSet> registeredSets(Iterator<SelectionKey> keys) {
+ List<ActionSet> sets = new LinkedList<ActionSet>();
+
+ while(keys.hasNext()) {
+ SelectionKey key = keys.next();
+ ActionSet actions = (ActionSet)key.attachment();
+
+ if(!key.isValid()) {
+ key.cancel();
+ } else {
+ sets.add(actions);
+ }
+ }
+ return sets;
+ }
+
+ /**
+ * This is used to acquire all the action sets that are selected
+ * by this selector. All action sets returned are unregistered from
+ * the selector and must be registered again to hear about further
+ * I/O events that occur on the associated channel.
+ *
+ * @return this returns all the selected action sets for this
+ */
+ public List<ActionSet> selectedSets() throws IOException {
+ Set<SelectionKey> keys = selector.selectedKeys();
+ Iterator<SelectionKey> ready = keys.iterator();
+
+ return selectedSets(ready);
+ }
+
+ /**
+ * This is used to acquire all the action sets that are selected
+ * by this selector. All action sets returned are unregistered from
+ * the selector and must be registered again to hear about further
+ * I/O events that occur on the associated channel.
+ *
+ * @param keys the selection keys to get the associated sets from
+ *
+ * @return this returns all the selected action sets for this
+ */
+ private List<ActionSet> selectedSets(Iterator<SelectionKey> keys) {
+ List<ActionSet> ready = new LinkedList<ActionSet>();
+
+ while(keys.hasNext()) {
+ SelectionKey key = keys.next();
+ ActionSet actions = (ActionSet)key.attachment();
+
+ if(key != null) {
+ keys.remove();
+ }
+ if(key != null) {
+ ready.add(actions);
+ }
+ }
+ return ready;
+ }
+
+ /**
+ * This is used to wake the selector if it is in the middle of a
+ * select operation. Waking up the selector in this manner is
+ * useful if further actions are to be registered with it.
+ */
+ public void wake() throws IOException {
+ selector.wakeup();
+ }
+
+ /**
+ * This is used to close the associated selector. Further attempts
+ * to register a channel with the selector will fail. All actions
+ * should be cancelled before closing the selector in this way.
+ */
+ public void close() throws IOException {
+ selector.close();
+ }
+}