changeset 350:59ef23ee73ad

SelectorSimulator is not thread safe now.
author kono
date Thu, 16 Oct 2008 10:19:18 +0900
parents ef4afcae0c92
children b8efd57faf78
files rep/channel/SelectorSimulator.java
diffstat 1 files changed, 71 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/rep/channel/SelectorSimulator.java	Thu Oct 16 01:12:34 2008 +0900
+++ b/rep/channel/SelectorSimulator.java	Thu Oct 16 10:19:18 2008 +0900
@@ -5,30 +5,34 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 public class SelectorSimulator<P> extends REPSelector<P>{
 
-	// access to these set have to be synchronized
-	private Set<SelectionKey> keyList;
-	private Set<SelectionKey> selectedKeys;
+	// This selector cannot be shared among threads.
+	
+	private Map<SelectableChannel, SelectionKeySimulator<P>> keyList;
+	private Set<SelectionKeySimulator<P>> selectedKeys;
 	private boolean isOpen=true;
 
 	public SelectorSimulator() {
 		super(null);
-		keyList = new HashSet<SelectionKey>();
+		keyList = new HashMap<SelectableChannel,SelectionKeySimulator<P>>();
 	}
 
-	public synchronized int select() throws IOException {
+	public int select() throws IOException {
 		while(true) {
 			getSelectedKeys();
 			if(selectedKeys.isEmpty()) {
 				try {
-					this.wait();
+					synchronized(this) {
+						wait();
+					}
 				} catch (InterruptedException e) {
-					throw new IOException("Error, Selector was interrupted!");
+					throw new IOException();
 				}
 			} else
 				break;
@@ -37,30 +41,32 @@
 	}
 
 	@Override
-	public synchronized int select(long timeout) throws IOException {
+	public int select(long timeout) throws IOException {
 		getSelectedKeys();
 		if(selectedKeys.isEmpty()) {
 			try {
-				wait(timeout);
+				synchronized(this) {
+					wait(timeout);
+				}
 				// we cannot know if we time outed or not
 				getSelectedKeys(); 
 			} catch (InterruptedException e) {
-				throw new IOException("Error, Selector was interrupted!");
+				throw new IOException();
 			}
 		} 
 		return selectedKeys.size();
 	}
 
 	private void getSelectedKeys() {
-		selectedKeys = new HashSet<SelectionKey>();
-		for(SelectionKey key : keyList){
-			if(((SelectionKeySimulator<?>) key).isAble())
-				selectedKeys.add(key);
+		selectedKeys = new HashSet<SelectionKeySimulator<P>>();
+		for(SelectionKeySimulator<P> key : keyList.values()){
+			if(key.isAble())
+				selectedKeys.add(new SelectionKeySimulator<P>(key));
 		}
 	}
 
 	@Override
-	public synchronized int selectNow() throws IOException {
+	public int selectNow() throws IOException {
 		getSelectedKeys();
 		return selectedKeys.size();
 	}
@@ -69,39 +75,26 @@
 		return register(cs, opt, null);
 	}
 	public SelectionKeySimulator<P> register(SelectableChannel cs, int opt, Object handler){
-		SelectionKeySimulator<P> key = new SelectionKeySimulator<P>(cs, opt, this);
+		SelectionKeySimulator<P> key = keyList.get(cs);
+		if (key!=null) {
+			key.attach(handler);
+			key.interestOps(opt);
+			return key;
+		}
+		key = new SelectionKeySimulator<P>(cs, opt, this);
 		key.attach(handler);
-		deregister(cs);
-		synchronized(this) {
-			keyList.add(key);
-		}
+		keyList.put(cs,key);
 		return key;
 	}
 
-	public synchronized void deregister(SelectableChannel channel) {
-		for(Iterator<SelectionKey> it = keyList.iterator();it.hasNext();) {
-			if(it.next().channel() == channel)
-				it.remove();
-		}
+	public SelectionKeySimulator<P> deregister(SelectableChannel channel) {
+		SelectionKeySimulator<P> key = keyList.remove(channel);
+		return key;
 	}
 
 
-	public synchronized Set<REPSelectionKey<P>> selectedKeys1() {
-		Set<SelectionKey> keys = keyList;
-		Set<REPSelectionKey<P>> newKeys = new HashSet<REPSelectionKey<P>>();
-		for(SelectionKey k: keys) {
-			// REPSelectionKeyを生成しないように注意
-			newKeys.add(new SelectionKeySimulator<P>(k));
-		}
-		return newKeys;
-	}
-
-	public synchronized <T> SelectionKey getKey(ChannelSimulator<T> channel){
-		for(SelectionKey key : keyList){
-			if(key.channel() == channel)
-				return key;
-		}
-		return null;
+	public SelectionKey getKey(SelectableChannel channel){
+		return keyList.get(channel);
 	}
 
 	@Override
@@ -116,7 +109,23 @@
 
 	@Override
 	public Set<SelectionKey> keys() {
-		return keyList;
+		Set<SelectionKey> newKeys = new HashSet<SelectionKey>();
+		for(SelectionKey k: keyList.values()) {
+			// REPSelectionKeyを生成しないように注意
+			newKeys.add(k);
+		}
+		return newKeys;
+	}
+	
+	public Set<REPSelectionKey<P>> keys1() {
+		// we cannot solve cast, we need the same method again with different
+		// types
+		Set<REPSelectionKey<P>> newKeys = new HashSet<REPSelectionKey<P>>();
+		for(SelectionKeySimulator<P> k: keyList.values()) {
+			// REPSelectionKeyを生成しないように注意
+			newKeys.add(k); //new SelectionKeySimulator<P>(k));
+		}
+		return newKeys;
 	}
 
 	@Override
@@ -132,9 +141,26 @@
 		return this;
 	}
 
+
+	public Set<REPSelectionKey<P>> selectedKeys1() {
+		Set<REPSelectionKey<P>> newKeys = new HashSet<REPSelectionKey<P>>();
+		for(SelectionKeySimulator<P> k: selectedKeys) {
+			// REPSelectionKeyを生成しないように注意
+			//newKeys.add(new SelectionKeySimulator<P>(k));
+			newKeys.add(k);
+		}
+		return newKeys;
+	}
+	
 	@Override
-	public synchronized Set<SelectionKey> selectedKeys() {
-		return (Set<SelectionKey>)selectedKeys;
+	public Set<SelectionKey> selectedKeys() {
+		Set<SelectionKeySimulator<P>> keys = selectedKeys;
+		Set<SelectionKey> newKeys = new HashSet<SelectionKey>();
+		for(SelectionKeySimulator<P> k: keys) {
+			// REPSelectionKeyを生成しないように注意
+			newKeys.add(k); // new SelectionKeySimulator<P>(k));
+		}
+		return newKeys;
 	}
 
 }