cvs commit: spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl DefaultSelectorManager.java NullSelectorEventHandler.java NullSelectorMonitor.java SelectorEntry.java SelectorMonitor.java
Peter Donald <[email protected]>
| Newsgroups | gmane.comp.java.spice.cvs |
|---|---|
| Message-ID | <[email protected]> |
donaldp 03/10/29 18:46:32
Added: sandbox/sca/src/java/org/realityforge/sca/selector/impl
DefaultSelectorManager.java
NullSelectorEventHandler.java
NullSelectorMonitor.java SelectorEntry.java
SelectorMonitor.java
Log:
Initial cut of selector code based on that previously in netserve
Revision Changes Path
1.1 spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl/DefaultSelectorManager.java
Index: DefaultSelectorManager.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.sca.selector.impl;
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.Set;
import org.realityforge.sca.selector.SelectorEventHandler;
import org.realityforge.sca.selector.SelectorManager;
/**
* The SelectorManager makes it easy to start a selector
* in a thread and receive events on selection.
*/
public class DefaultSelectorManager
implements SelectorManager, Runnable
{
/**
* The monitor that receives notifications of Connection events
*/
private SelectorMonitor m_monitor = NullSelectorMonitor.MONITOR;
/**
* Selector used to monitor for accepts.
*/
private Selector m_selector;
/**
* Flag indicating whether manager is running.
*/
private boolean m_active;
/**
* Timeout on selector.
*/
private int m_timeout = 500;
/**
* Set the SelectorMonitor that receives events when changes occur.
*
* @param monitor the SelectorMonitor.
*/
public void setMonitor( final SelectorMonitor monitor )
{
if( null == monitor )
{
throw new NullPointerException( "monitor" );
}
m_monitor = monitor;
}
/**
* Set the timeout on the selector.
*
* @param timeout the timeout.
*/
public void setTimeout( final int timeout )
{
m_timeout = timeout;
}
/**
* Initialize the selector to monitor accept attempts.
*
* @throws java.io.IOException if unable to initialize selector
*/
public void startup()
throws IOException
{
getMonitor().selectorStartup();
setSelector( Selector.open() );
startThread();
}
/**
* Method to shutdown the SelectorManager.
*/
public void shutdown()
{
setInactive();
shutdownSelector();
waitForThreadToComplete();
}
/**
* Start the thread to accept connections.
*/
protected void startThread()
{
final Thread thread = new Thread( this, getThreadName() );
thread.start();
while( !isRunning() )
{
Thread.yield();
}
}
/**
* Shutdown the selector and any associated acceptors.
*/
protected void shutdownSelector()
{
synchronized( getSelectorLock() )
{
if( null != m_selector )
{
getMonitor().selectorShutdown();
try
{
m_selector.wakeup();
m_selector.close();
}
catch( final IOException ioe )
{
getMonitor().errorClosingSelector( ioe );
}
}
}
}
/**
* Wait for selector thread to complete.
*/
protected void waitForThreadToComplete()
{
while( null != m_selector )
{
synchronized( getSelectorLock() )
{
try
{
wait( 100 );
}
catch( InterruptedException e )
{
//Ignore
}
}
}
}
/**
* Set a flag to indicate reactor is inactive.
* Will eventually cause the selector thread to
* close. Note that shutdownSelector() should be
* called after this method to make sure all
* resources are deallocated.
*/
public void setInactive()
{
setRunning( false );
}
/**
* Return true if the selector is manager is running.
*
* @return true if the selector is manager is running.
*/
public boolean isRunning()
{
synchronized( getSelectorLock() )
{
return m_active;
}
}
/**
* @see org.realityforge.sca.selector.SelectorManager#registerChannel
*/
public SelectionKey registerChannel( final SelectableChannel channel,
final int ops,
final SelectorEventHandler handler,
final Object userData )
throws IOException
{
if( null == channel )
{
throw new NullPointerException( "channel" );
}
//Handler will be checked for null in entry.
final SelectorEntry entry = new SelectorEntry( handler, userData );
channel.configureBlocking( false );
synchronized( getSelectorLock() )
{
final Selector selector = getSelector();
selector.wakeup();
return channel.register( selector, ops, entry );
}
}
/**
* This is the main connection accepting loop.
*/
public void run()
{
setRunning( true );
getMonitor().enteringSelectorLoop();
// Here's where everything happens. The select method will
// return when any operations registered above have occurred, the
// thread has been interrupted, etc.
while( isRunning() )
{
if( !performSelect() ||
!isRunning() )
{
synchronized( getSelectorLock() )
{
continue;
}
}
final Set keys = getSelector().selectedKeys();
final Iterator iterator = keys.iterator();
// Walk through the ready keys collection and process date requests.
while( iterator.hasNext() )
{
final SelectionKey key = (SelectionKey)iterator.next();
iterator.remove();
final Object value = key.attachment();
if( null == value || !( value instanceof SelectorEntry ) )
{
//Cancel keys that have had their
//attachments messed with
getMonitor().invalidAttachment( key );
key.cancel();
continue;
}
// The key indexes into the selector so you
// can retrieve the socket that's ready for I/O
final SelectorEntry entry = (SelectorEntry)value;
entry.getHandler().
handleSelectorEvent( key, entry.getUserData() );
}
}
getMonitor().exitingSelectorLoop();
setSelector( null );
}
/**
* Perform select operation and return true if
* successful and connections present.
*
* @return true if select resulted in keys being present
*/
private boolean performSelect()
{
try
{
getMonitor().enteringSelect();
final int count = getSelector().select( m_timeout );
getMonitor().selectCompleted( count );
if( 0 != count )
{
return true;
}
}
catch( final Exception e )
{
//Ignore
}
return false;
}
/**
* Return the lock used to synchronize access to selector.
*
* @return the lock used to synchronize access to selector.
*/
protected Object getSelectorLock()
{
return this;
}
/**
* Set the selector associated with reactor.
*
* @param selector the selector associated with reactor.
*/
protected void setSelector( final Selector selector )
{
synchronized( getSelectorLock() )
{
m_selector = selector;
notifyAll();
}
}
/**
* Return the selector associated with reactor.
*
* @return the selector associated with reactor.
*/
protected Selector getSelector()
{
synchronized( getSelectorLock() )
{
if( null == m_selector )
{
throw new NullPointerException( "selector" );
}
return m_selector;
}
}
/**
* Return the monitor associated with manager.
*
* @return the monitor associated with manager.
*/
protected SelectorMonitor getMonitor()
{
return m_monitor;
}
/**
* Set the flag to specify whether th Reactor is running.
*
* @param running the flag to specify whether th Reactor is running
*/
protected void setRunning( final boolean running )
{
synchronized( getSelectorLock() )
{
m_active = running;
}
}
/**
* Return the name of thread that Selector will run in.
*
* @return the name of thread that Selector will run in.
*/
protected String getThreadName()
{
return "SelectorManager";
}
}
1.1 spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl/NullSelectorEventHandler.java
Index: NullSelectorEventHandler.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.sca.selector.impl;
import java.nio.channels.SelectionKey;
import org.realityforge.sca.selector.SelectorEventHandler;
/**
* Basic implementation of
* SelectorEventHandler that does nothing.
*/
public class NullSelectorEventHandler
implements SelectorEventHandler
{
/**
* Constant containing instance of NullSelectorEventHandler.
*/
public static final NullSelectorEventHandler HANDLER = new NullSelectorEventHandler();
/**
* @see SelectorEventHandler#handleSelectorEvent
*/
public void handleSelectorEvent( final SelectionKey key,
final Object userData )
{
}
}
1.1 spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl/NullSelectorMonitor.java
Index: NullSelectorMonitor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.sca.selector.impl;
import java.io.IOException;
import java.nio.channels.SelectionKey;
/**
* A Null SelectorMonitor.
*/
public class NullSelectorMonitor
implements SelectorMonitor
{
/**
* Constant containing instance of NullSelectorMonitor.
*/
public static final NullSelectorMonitor MONITOR = new NullSelectorMonitor();
/**
* @see SelectorMonitor#selectorStartup
*/
public void selectorStartup()
{
}
/**
* @see SelectorMonitor#enteringSelectorLoop
*/
public void enteringSelectorLoop()
{
}
/**
* @see SelectorMonitor#enteringSelect
*/
public void enteringSelect()
{
}
/**
* @see SelectorMonitor#selectCompleted
*/
public void selectCompleted( final int count )
{
}
/**
* @see SelectorMonitor#handlingSelectEvent
*/
public void handlingSelectEvent( final SelectionKey key )
{
}
/**
* @see SelectorMonitor#exitingSelectorLoop
*/
public void exitingSelectorLoop()
{
}
/**
* @see SelectorMonitor#selectorShutdown
*/
public void selectorShutdown()
{
}
/**
* @see SelectorMonitor#errorClosingSelector
*/
public void errorClosingSelector( final IOException ioe )
{
}
/**
* @see SelectorMonitor#invalidAttachment
*/
public void invalidAttachment( final SelectionKey key )
{
}
}
1.1 spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl/SelectorEntry.java
Index: SelectorEntry.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.sca.selector.impl;
import org.realityforge.sca.selector.SelectorEventHandler;
/**
* A simple class that contains data relating
* to a specific Selector registration.
*/
class SelectorEntry
{
/**
* The associated handler that is passed
* events about channel.
*/
private final SelectorEventHandler _handler;
/**
* The user specified data that is passed to the handler.
*/
private final Object _userData;
/**
* Create an Entry for Selector registration.
*
* @param handler the handler
* @param userData the user specified data
*/
SelectorEntry( final SelectorEventHandler handler,
final Object userData )
{
if( null == handler )
{
throw new NullPointerException( "handler" );
}
_handler = handler;
_userData = userData;
}
/**
* Return the handler for channel.
*
* @return the handler for channel.
*/
SelectorEventHandler getHandler()
{
return _handler;
}
/**
* Return the userData passed to handler.
*
* @return the userData passed to handler.
*/
Object getUserData()
{
return _userData;
}
}
1.1 spice/sandbox/sca/src/java/org/realityforge/sca/selector/impl/SelectorMonitor.java
Index: SelectorMonitor.java
===================================================================
/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.sca.selector.impl;
import java.io.IOException;
import java.nio.channels.SelectionKey;
/**
* Monitor used to monitor events in the AcceptorManager.
*
* @author <a href="mailto:peter at realityforge.org">Peter Donald</a>
* @version $Revision: 1.1 $ $Date: 2003/10/30 02:46:32 $
*/
public interface SelectorMonitor
{
/**
* Selector being started up.
*/
void selectorStartup();
/**
* Entering the main loop that
* accepts connections.
*/
void enteringSelectorLoop();
/**
* Entering select call.
*/
void enteringSelect();
/**
* Aselect has completed.
*
* @param count the number of accepts that are ready
*/
void selectCompleted( int count );
/**
* About to handle a selection event.
*
* @param key the selection key
*/
void handlingSelectEvent( SelectionKey key );
/**
* Exiting the main loop that
* accepts connections.
*/
void exitingSelectorLoop();
/**
* Selector being shutdown.
*/
void selectorShutdown();
/**
* There was an error closing selector.
*
* @param ioe the exception
*/
void errorClosingSelector( IOException ioe );
/**
* The specified key has an invalid attachment.
*
* @param key the key
*/
void invalidAttachment( SelectionKey key );
}
-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive? Does it
help you create better code? SHARE THE LOVE, and help us help
YOU! Click Here: http://sourceforge.net/donate/