/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the LICENSE file that accompanied
* this code.
*
* --
*/
package com.sun.sgs.nio.channels;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import com.sun.sgs.nio.channels.spi.AsynchronousChannelProvider;
/**
* An organization of asynchronous channels for the purpose of resource
* sharing.
* <p>
* An asynchronous channel group encapsulates the mechanics required to
* handle the completion of I/O operations initiated by
* {@link AsynchronousChannel asynchronous channels} that are bound to the
* group. A group is created with an {@link ExecutorService} to which tasks
* are submitted to handle I/O events and dispatch to
* {@link CompletionHandler completion handlers} that consume the result of
* asynchronous operations performed on channels in the group.
* <p>
* An asynchronous channel group is created by invoking the {@link #open}
* method. Channels are bound to a group by specifying the group when the
* channel is constructed. If a group is not specified then the channel is
* bound to a <em>default group</em> that is constructed automatically.
* The executor for the default group is created by invoking the
* {@link ThreadPoolFactory#newThreadPool() newThreadPool} method on a
* {@link ThreadPoolFactory} located as follows:
* <ul>
* <li> If the system property
* {@code java.nio.channels.DefaultThreadPoolFactory} is defined then it is
* taken to be the fully-qualified name of a concrete thread pool factory
* class. The class is loaded and instantiated.
* <li> If the system property is not defined, or the process to load and
* instantiate it fails, then a system-default factory class is
* instantiated.
* </ul>
* <h4>Shutdown and Termination</h4>
* The {@link #shutdown} method is used to initiate an
* <em>orderly shutdown</em> of the group. An orderly shutdown marks the
* group as shutdown; further attempts to construct a channel that binds to
* the group will throw {@link ShutdownChannelGroupException}. Whether or
* not a group is shutdown can be tested using the {@link #isShutdown}
* method. Once shutdown, a group <em>terminates</em> when all
* asynchronous channels that are bound to the group are closed and
* resources used by the group are released. Once a group is terminated then
* any actively executing completion handlers run to completion; no attempt
* is made to stop or interrupt threads that are executing completion
* handlers. The {@link #isTerminated} method is used to test if the group
* has terminated, and the {@link #awaitTermination} method can be used to
* block until the group has terminated.
* <p>
* The {@link #shutdownNow} method can be used to initiate a
* <em>forceful shutdown</em> of the group. In addition to the actions
* performed by an orderly shutdown, the {@code shutdownNow} method closes
* all open channels in the group as if by invoking the
* {@link AsynchronousChannel#close close} method. A group will typically
* terminate quickly after the {@code shutdownNow} method has been invoked.
*
* @see AsynchronousSocketChannel#open(AsynchronousChannelGroup)
* @see AsynchronousServerSocketChannel#open(AsynchronousChannelGroup)
* @see AsynchronousDatagramChannel#open(ProtocolFamily,
* AsynchronousChannelGroup)
*/
public abstract class AsynchronousChannelGroup {
/** The asynchronous channel provider for this group. */
private final AsynchronousChannelProvider provider;
/**
* Initialize a new instance of this class.
*
* @param provider the asynchronous channel provider for this group
*/
protected AsynchronousChannelGroup(AsynchronousChannelProvider provider) {
if (provider == null) {
throw new NullPointerException("null provider");
}
this.provider = provider;
}
/**
* Returns the provider that created this channel group.
*
* @return the provider that created this channel group
*/
public final AsynchronousChannelProvider provider() {
return provider;
}
/**
* Creates an asynchronous channel group.
* <p>
* The new group is created by invoking the
* {@link
* AsynchronousChannelProvider#openAsynchronousChannelGroup(ExecutorService)
* openAsynchronousChannelGroup} method of the system-wide default
* {@link AsynchronousChannelProvider} object.
* <p>
* The {@code executor} parameter is the {@link ExecutorService} to
* which tasks will be submitted to handle I/O events and dispatch
* completion results for operations initiated on asynchronous channels
* in the group.
* <p>
* The tasks and the usage of the executor are highly implementation
* specific. Consequently, care should be taken when configuring the
* thread pool and it should allow for unbounded queuing. Depending on
* the implementation, a number of tasks may be required to execute at
* the same time so as to wait on I/O events from multiple dictinct
* sources. A thread pool with a single worker, for example, may result
* in starvation and may be unsuitable for such implementations. It is
* recommended that the executor be used exclusively for the resulting
* asynchronous channel group.
*
* @param executor the executor service
* @return a new asynchronous channel group
* @throws IOException if an I/O error occurs
*/
public static AsynchronousChannelGroup open(ExecutorService executor)
throws IOException
{
return AsynchronousChannelProvider.provider().
openAsynchronousChannelGroup(executor);
}
/**
* Tells whether or not this asynchronous channel group is shutdown.
*
* @return {@code true} if this asynchronous channel group is shutdown
*/
public abstract boolean isShutdown();
/**
* Tells whether or not this asynchronous channel group is terminated.
*
* @return {@code true} if this asynchronous channel group is terminated
*/
public abstract boolean isTerminated();
/**
* Initiates an orderly shutdown of the group.
* <p>
* This method marks the group as shutdown. Further attempts to
* construct a channel that binds to this group will throw
* {@link ShutdownChannelGroupException}. The group terminates when all
* asynchronous channels in the group are closed and all resources have
* been released. This method has no effect if the group is already
* shutdown.
*
* @return this group
*/
public abstract AsynchronousChannelGroup shutdown();
/**
* Shuts down the group and closes all open channels in the group.
* <p>
* In addition to the actions performed by the {@link #shutdown} method,
* this method invokes the {@link AsynchronousChannel#close close}
* method on all open channels in the group. This method does not
* attempt to stop actively executing
* {@link CompletionHandler completion handlers}.
* <p>
* The group is likely to terminate <em>quickly</em> after invoking this
* method but there is no guarantee that the group has terminated on
* completion of this method.
*
* @return this group
* @throws IOException if an I/O error occurs
*/
public abstract AsynchronousChannelGroup shutdownNow()
throws IOException;
/**
* Awaits termination of the group.
* <p>
* This method blocks until all channels in the group have been closed
* and all resources associated with the group have been released.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return {@code true} if the group has terminated; {@code false} if
* the timeout elapsed before termination
* @throws InterruptedException if interrupted while waiting
*/
public abstract boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
/**
* Set the uncaught exception handler for the default group.
* <p>
* The uncaught exception handler is invoked when the execution of a
* {@link CompletionHandler}, consuming the result of an operation on a
* channel bound to the default group, terminates with an uncaught
* {@code Error} or {@code RuntimeException}.
* <p>
* [TBD - need to define interaction with normal uncaught exception
* handling mechanism]
*
* @param eh the object to use as the default uncaught exception
* handler, or {@code null} for no default handler
* @throws SecurityException [TBD]
*/
public static void
setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {
AsynchronousChannelProvider.provider().setUncaughtExceptionHandler(eh);
}
/**
* Returns the uncaught exception handler for the default group.
*
* @return the uncaught exception handler for the default group, or
* {@code null} if there is no default handler
*/
public static Thread.UncaughtExceptionHandler
getDefaultUncaughtExceptionHandler() {
return AsynchronousChannelProvider.provider()
.getUncaughtExceptionHandler();
}
}