/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Windows implementation of AsynchronousChannelGroup encapsulating an I/O
* completion port.
*/
private static final boolean supportsThreadAgnosticIo;
// maps completion key to channel
private int nextCompletionKey;
// handle to completion port
private final long port;
// true if port has been closed
private boolean closed;
// the set of "stale" OVERLAPPED structures. These OVERLAPPED structures
// relate to I/O operations where the completion notification was not
// received in a timely manner after the channel is closed.
throws IOException
{
this.port =
this.nextCompletionKey = 1;
}
startThreads(new EventHandlerTask());
return this;
}
/*
* Channels implements this interface support overlapped I/O and can be
* associated with a completion port.
*/
/**
* Returns a reference to the pending I/O result.
*/
}
/**
* Indicates if this operating system supports thread agnostic I/O.
*/
static boolean supportsThreadAgnosticIo() {
return supportsThreadAgnosticIo;
}
// release all resources
void implClose() {
synchronized (this) {
if (closed)
return;
closed = true;
}
synchronized (staleIoSet) {
}
staleIoSet.clear();
}
}
boolean isEmpty() {
try {
return keyToChannel.isEmpty();
} finally {
}
}
throws IOException
{
return null;
}
public void close() throws IOException {
}
}, 0L);
}
}
void closeAllChannels() {
/**
* and then wait until all outstanding I/O operations have aborted.
* This is necessary as each channel's cache of OVERLAPPED structures
* can only be freed once all I/O operations have completed. As I/O
* completion requires a lookup of the keyToChannel then we must close
* the channels when not holding the write lock.
*/
final int MAX_BATCH_SIZE = 32;
int count;
do {
// grab a batch of up to 32 channels
count = 0;
try {
if (count >= MAX_BATCH_SIZE)
break;
}
} finally {
}
// close them
for (int i=0; i<count; i++) {
try {
} catch (IOException ignore) { }
}
} while (count > 0);
}
private void wakeup() {
try {
} catch (IOException e) {
// should not happen
throw new AssertionError(e);
}
}
synchronized (this) {
if (closed)
throw new RejectedExecutionException();
wakeup();
}
}
void shutdownHandlerTasks() {
// shutdown all handler threads
int nThreads = threadCount();
while (nThreads-- > 0) {
wakeup();
}
}
/**
* Associate the given handle with this group
*/
// generate a completion key (if not shutdown)
int key;
try {
if (isShutdown())
throw new ShutdownChannelGroupException();
// generate unique key
do {
key = nextCompletionKey++;
// associate with I/O completion port
if (handle != 0L) {
}
// setup mapping
} finally {
}
return key;
}
/**
* Disassociate channel from the group.
*/
boolean checkForShutdown = false;
try {
// last key to be removed so check if group is shutdown
if (keyToChannel.isEmpty())
checkForShutdown = true;
} finally {
}
// continue shutdown
if (checkForShutdown && isShutdown()) {
try {
shutdownNow();
} catch (IOException ignore) { }
}
}
/**
* Invoked when a channel associated with this port is closed before
* notifications for all outstanding I/O operations have been received.
*/
synchronized (staleIoSet) {
}
}
/**
* Checks if the given OVERLAPPED is stale and if so, releases it.
*/
synchronized (staleIoSet) {
if (removed) {
}
}
}
/**
* The handler for consuming the result of an asynchronous I/O operation.
*/
static interface ResultHandler {
/**
* Invoked if the I/O operation completes successfully.
*/
/**
* Invoked if the I/O operation fails.
*/
}
// Creates IOException for the given I/O error.
return new IOException(msg);
}
/**
* Long-running task servicing system-wide or per-file completion port
*/
public void run() {
boolean replaceMe = false;
try {
for (;;) {
// reset invoke count
if (myGroupAndInvokeCount != null)
// wait for I/O completion event
// A error here is fatal (thread will not be replaced)
replaceMe = false;
try {
} catch (IOException x) {
// should not happen
x.printStackTrace();
return;
}
// handle wakeup to execute task or shutdown
{
// shutdown request
return;
}
// run task
replaceMe = true;
continue;
}
// map key to channel
try {
continue;
}
} finally {
}
// lookup I/O request
// we get here if the OVERLAPPED structure is associated
// with an I/O operation on a channel that was closed
// but the I/O operation event wasn't read in a timely
// manner. Alternatively, it may be related to a
// tryLock operation as the OVERLAPPED structures for
// these operations are not in the I/O cache.
continue;
}
// synchronize on result in case I/O completed immediately
// and was handled by initiator
synchronized (result) {
continue;
}
// not handled by initiator
}
// invoke I/O result handler
if (error == 0) {
} else {
}
}
} finally {
// last thread to exit when shutdown releases resources
implClose();
}
}
}
}
/**
* Container for data returned by GetQueuedCompletionStatus
*/
private static class CompletionStatus {
private int error;
private int bytesTransferred;
private int completionKey;
private long overlapped;
private CompletionStatus() { }
}
// -- native methods --
private static native void initIDs();
int completionKey) throws IOException;
static {
initIDs();
// thread agnostic I/O on Vista/2008 or newer
new GetPropertyAction("os.version"));
}
}