package org.playorm.nio.impl.cm.basic.nioimpl; import java.io.IOException; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.playorm.nio.api.testutil.nioapi.ChannelRegistrationListener; import org.playorm.nio.api.testutil.nioapi.Select; import org.playorm.nio.api.testutil.nioapi.SelectorListener; import org.playorm.nio.api.testutil.nioapi.SelectorRunnable; import org.playorm.nio.impl.cm.basic.SelectorManager2; /** */ public class SelectorImpl implements Select { private static final Logger log = Logger.getLogger(SelectorImpl.class.getName()); private PollingThread thread; private AbstractSelector selector; private String id; private boolean running = false; private boolean wantToShutDown = false; private SelectorListener listener; private SelectorProvider provider; /** * Creates an instance of SelectorImpl. * @param selector */ public SelectorImpl(String id, AbstractSelector selector) { } /** * Creates an instance of SelectorImpl. * @param provider */ public SelectorImpl(String id, SelectorProvider provider) { this.id = id; this.provider = provider; } /** * @see org.playorm.nio.api.testutil.nioapi.Select#wakeup() */ public void wakeup() { if(selector != null) selector.wakeup(); } /** */ public Selector getSelector() { return selector; } /** * @throws IOException * @see org.playorm.nio.api.testutil.nioapi.Select#startPollingThread(org.playorm.nio.impl.cm.basic.SelectorManager2) */ public void startPollingThread(SelectorListener l) throws IOException { if(running) throw new IllegalStateException("Already running, can't start again"); this.listener = l; selector = provider.openSelector(); thread = new PollingThread(); thread.setName("SelMgr-"+id); thread.start(); } /** * @throws InterruptedException * @see org.playorm.nio.api.testutil.nioapi.Select#stopPollingThread() */ public void stopPollingThread() throws InterruptedException { if(!running) return; wantToShutDown = true; selector.wakeup(); synchronized(this) { if(running) this.wait(20000); if(running) log.severe(id+"Tried to shutdown channelmanager, but it took longer " + "than 20 seconds. It may be hung now"); } } //protect the Thread from being started or controlled by putting //the run in a private class. The rest of the methods are protected //so they are ok. private class PollingThread extends Thread { @Override public void run() { try { running = true; runLoop(); if(log.isLoggable(Level.FINE)) log.fine("shutting down the PollingThread"); selector.close(); selector = null; thread = null; synchronized(SelectorImpl.this) { running = false; SelectorImpl.this.notifyAll(); } } catch (Exception e) { log.log(Level.WARNING, id+"Exception on ConnectionManager thread", e); } } } protected void runLoop() { while (!wantToShutDown) { listener.selectorFired(); } } /** * @see org.playorm.nio.api.testutil.nioapi.Select#getThread() */ public Object getThread() { return thread; } /** * @see org.playorm.nio.api.testutil.nioapi.Select#selectedKeys() */ public Set<SelectionKey> selectedKeys() { return selector.selectedKeys(); } /** * @throws IOException * @see org.playorm.nio.api.testutil.nioapi.Select#select() */ public int select() throws IOException { return selector.select(); } /** * @see org.playorm.nio.api.testutil.nioapi.Select#isRunning() */ public boolean isRunning() { return running; } /** * @see org.playorm.nio.api.testutil.nioapi.Select#isWantShutdown() */ public boolean isWantShutdown() { return wantToShutDown; } /** * @see org.playorm.nio.api.testutil.nioapi.Select#setRunning(boolean) */ public void setRunning(boolean b) { running = b; } /** * @see org.playorm.nio.api.testutil.nioapi.Select#createRegistrationListener * (java.lang.Object, org.playorm.nio.api.testutil.nioapi.SelectorRunnable, org.playorm.nio.impl.cm.basic.SelectorManager2) */ public ChannelRegistrationListener createRegistrationListener(Object id, SelectorRunnable r, Object s) { return new RegistrationListenerImpl(id, r, (SelectorManager2)s); } /** * @see org.playorm.nio.api.testutil.nioapi.Select#getKeyFromChannel(java.nio.channels.SelectableChannel) */ public SelectionKey getKeyFromChannel(SelectableChannel realChannel) { return realChannel.keyFor(selector); } /** * @throws ClosedChannelException * @see org.playorm.nio.api.testutil.nioapi.Select#register(java.nio.channels.SelectableChannel, * int, org.playorm.nio.impl.cm.basic.WrapperAndListener) */ public SelectionKey register(SelectableChannel s, int allOps, Object struct) throws ClosedChannelException { if(struct == null) throw new IllegalArgumentException("struct cannot be null"); return s.register(selector, allOps, struct); } }