/*
* 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 AsynchronousSocketChannel using overlapped I/O.
*/
{
}
/*
* typedef struct _WSABUF {
* u_long len;
* char FAR * buf;
* } WSABUF;
*/
// socket handle. Use begin()/end() around each usage of this handle.
final long handle;
// I/O completion port that the socket is associated with
// completion key to identify channel when I/O completes
private final int completionKey;
// Pending I/O operations are tied to an OVERLAPPED structure that can only
// be released when the I/O completion event is posted to the completion
// port. Where I/O operations complete immediately then it is possible
// there may be more than two OVERLAPPED structures in use.
// per-channel arrays of WSABUF structures
private final long readBufferArray;
private final long writeBufferArray;
throws IOException
{
super(iocp);
// associate socket with default completion port
int key = 0;
try {
} catch (ShutdownChannelGroupException x) {
if (failIfGroupShutdown) {
closesocket0(h);
throw x;
}
} catch (IOException x) {
closesocket0(h);
throw x;
}
this.handle = h;
this.completionKey = key;
this.ioCache = new PendingIoCache();
// allocate WSABUF arrays
}
this(iocp, true);
}
return iocp;
}
/**
* Invoked by Iocp when an I/O operation competes.
*/
}
// invoked by WindowsAsynchronousServerSocketChannelImpl
long handle() {
return handle;
}
// invoked by WindowsAsynchronousServerSocketChannelImpl when new connection
// accept
{
synchronized (stateLock) {
this.localAddress = localAddress;
this.remoteAddress = remoteAddress;
}
}
// close socket (may cause outstanding async I/O operations to fail).
// waits until all I/O operations have completed
// release arrays of WSABUF structures
// finally disassociate from the completion port (key can be 0 if
// channel created when group is shutdown)
if (completionKey != 0)
}
killConnect();
killReading();
killWriting();
}
/**
* Implements the task to initiate a connection and the handler to
* consume the result when the connection is established (or fails).
*/
}
private void closeChannel() {
try {
close();
} catch (IOException ignore) { }
}
if (x instanceof IOException) {
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
return (IOException)x;
}
return new IOException(x);
}
/**
* Invoke after a connection is successfully established.
*/
synchronized (stateLock) {
}
}
/**
* Task to initiate a connection.
*/
public void run() {
long overlapped = 0L;
try {
begin();
// synchronize on result to allow this thread handle the case
// where the connection is established immediately.
synchronized (result) {
// initiate the connection
if (n == IOStatus.UNAVAILABLE) {
// connection is pending
return;
}
// connection established immediately
afterConnect();
}
} catch (Throwable x) {
if (overlapped != 0L)
exc = x;
} finally {
end();
}
closeChannel();
}
}
/**
* Invoked by handler thread when connection established.
*/
try {
begin();
afterConnect();
} catch (Throwable x) {
// channel is closed or unable to finish connect
exc = x;
} finally {
end();
}
closeChannel();
}
if (canInvokeDirect) {
} else {
}
}
/**
* Invoked by handler thread when failed to establish connection.
*/
if (isOpen()) {
closeChannel();
result.setFailure(x);
} else {
}
}
}
A attachment,
{
if (!isOpen()) {
return null;
}
// permission check
// check and update state
// ConnectEx requires the socket to be bound to a local address
synchronized (stateLock) {
if (state == ST_CONNECTED)
throw new AlreadyConnectedException();
if (state == ST_PENDING)
throw new ConnectionPendingException();
if (localAddress == null) {
try {
} catch (IOException x) {
bindException = x;
}
}
if (bindException == null)
state = ST_PENDING;
}
// handle bind failure
if (bindException != null) {
try {
close();
} catch (IOException ignore) { }
return null;
}
// setup task
// initiate I/O
if (Iocp.supportsThreadAgnosticIo()) {
} else {
}
return result;
}
/**
* Implements the task to initiate a read and the handler to consume the
* result when the read completes.
*/
private final int numBufs;
private final boolean scatteringRead;
// set by run method
boolean scatteringRead,
PendingFuture<V,A> result)
{
this.scatteringRead = scatteringRead;
}
/**
* Invoked prior to read to prepare the WSABUF array. Where necessary,
* it substitutes non-direct buffers with direct buffers.
*/
void prepareBuffers() {
long address = readBufferArray;
for (int i=0; i<numBufs; i++) {
long a;
if (!(dst instanceof DirectBuffer)) {
// substitute with direct buffer
} else {
}
address += SIZEOF_WSABUF;
}
}
/**
* Invoked after a read has completed to update the buffer positions
* and release any substituted buffers.
*/
for (int i=0; i<numBufs; i++) {
try {
} catch (IllegalArgumentException x) {
// position changed by another
}
} else { // Buffers not completely filled
if (bytesRead > 0) {
try {
} catch (IllegalArgumentException x) {
// position changed by another
}
}
break;
}
}
// Put results from shadow into the slow buffers
for (int i=0; i<numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
try {
} catch (BufferOverflowException x) {
// position changed by another
}
}
}
}
void releaseBuffers() {
for (int i=0; i<numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
}
}
}
@SuppressWarnings("unchecked")
public void run() {
long overlapped = 0L;
boolean prepared = false;
boolean pending = false;
try {
begin();
// substitute non-direct buffers
prepared = true;
// get an OVERLAPPED structure (from the cache or allocate)
// initiate read
if (n == IOStatus.UNAVAILABLE) {
// I/O is pending
pending = true;
return;
}
// input shutdown
if (scatteringRead) {
} else {
}
} else {
throw new InternalError("Read completed immediately");
}
} catch (Throwable x) {
// failed to initiate read
// reset read flag before releasing waiters
if (x instanceof ClosedChannelException)
x = new AsynchronousCloseException();
if (!(x instanceof IOException))
x = new IOException(x);
result.setFailure(x);
} finally {
// release resources if I/O not pending
if (!pending) {
if (overlapped != 0L)
if (prepared)
}
end();
}
// invoke completion handler
}
/**
* Executed when the I/O has completed
*/
@SuppressWarnings("unchecked")
if (bytesTransferred == 0) {
} else {
}
// return direct buffer to cache if substituted
// release waiters if not already released by timeout
synchronized (result) {
return;
if (scatteringRead) {
} else {
}
}
if (canInvokeDirect) {
} else {
}
}
// return direct buffer to cache if substituted
// release waiters if not already released by timeout
if (!isOpen())
x = new AsynchronousCloseException();
synchronized (result) {
return;
result.setFailure(x);
}
}
/**
* Invoked if timeout expires before it is cancelled
*/
void timeout() {
synchronized (result) {
return;
// kill further reading before releasing waiters
enableReading(true);
}
// invoke handler without any locks
}
}
ByteBuffer[] dsts,
long timeout,
A attachment,
CompletionHandler<V,? super A> handler)
{
// setup task
PendingFuture<V,A> result =
ByteBuffer[] bufs;
if (isScatteringRead) {
} else {
}
// schedule timeout
if (timeout > 0L) {
public void run() {
}
}
// initiate I/O
if (Iocp.supportsThreadAgnosticIo()) {
} else {
}
return result;
}
/**
* Implements the task to initiate a write and the handler to consume the
* result when the write completes.
*/
private final int numBufs;
private final boolean gatheringWrite;
// set by run method
boolean gatheringWrite,
PendingFuture<V,A> result)
{
this.gatheringWrite = gatheringWrite;
}
/**
* Invoked prior to write to prepare the WSABUF array. Where necessary,
* it substitutes non-direct buffers with direct buffers.
*/
void prepareBuffers() {
long address = writeBufferArray;
for (int i=0; i<numBufs; i++) {
long a;
if (!(src instanceof DirectBuffer)) {
// substitute with direct buffer
} else {
}
address += SIZEOF_WSABUF;
}
}
/**
* Invoked after a write has completed to update the buffer positions
* and release any substituted buffers.
*/
// Notify the buffers how many bytes were taken
for (int i=0; i<numBufs; i++) {
if (bytesWritten >= len) {
bytesWritten -= len;
try {
} catch (IllegalArgumentException x) {
// position changed by someone else
}
} else { // Buffers not completely filled
if (bytesWritten > 0) {
try {
} catch (IllegalArgumentException x) {
// position changed by someone else
}
}
break;
}
}
}
void releaseBuffers() {
for (int i=0; i<numBufs; i++) {
if (!(bufs[i] instanceof DirectBuffer)) {
}
}
}
//@SuppressWarnings("unchecked")
public void run() {
long overlapped = 0L;
boolean prepared = false;
boolean pending = false;
boolean shutdown = false;
try {
begin();
// substitute non-direct buffers
prepared = true;
// get an OVERLAPPED structure (from the cache or allocate)
if (n == IOStatus.UNAVAILABLE) {
// I/O is pending
pending = true;
return;
}
// special case for shutdown output
shutdown = true;
throw new ClosedChannelException();
}
// write completed immediately
throw new InternalError("Write completed immediately");
} catch (Throwable x) {
// write failed. Enable writing before releasing waiters.
if (!shutdown && (x instanceof ClosedChannelException))
x = new AsynchronousCloseException();
if (!(x instanceof IOException))
x = new IOException(x);
result.setFailure(x);
} finally {
// release resources if I/O not pending
if (!pending) {
if (overlapped != 0L)
if (prepared)
}
end();
}
// invoke completion handler
}
/**
* Executed when the I/O has completed
*/
@SuppressWarnings("unchecked")
// return direct buffer to cache if substituted
// release waiters if not already released by timeout
synchronized (result) {
return;
if (gatheringWrite) {
} else {
}
}
if (canInvokeDirect) {
} else {
}
}
// return direct buffer to cache if substituted
// release waiters if not already released by timeout
if (!isOpen())
x = new AsynchronousCloseException();
synchronized (result) {
return;
result.setFailure(x);
}
}
/**
* Invoked if timeout expires before it is cancelled
*/
void timeout() {
synchronized (result) {
return;
// kill further writing before releasing waiters
enableWriting(true);
}
// invoke handler without any locks
}
}
ByteBuffer[] srcs,
long timeout,
A attachment,
CompletionHandler<V,? super A> handler)
{
// setup task
PendingFuture<V,A> result =
ByteBuffer[] bufs;
if (gatheringWrite) {
} else {
}
// schedule timeout
if (timeout > 0L) {
public void run() {
}
}
// initiate I/O (can only be done from thread in thread pool)
// initiate I/O
if (Iocp.supportsThreadAgnosticIo()) {
} else {
}
return result;
}
// -- Native methods --
private static native void initIDs();
throws IOException;
long overlapped) throws IOException;
static {
initIDs();
}
}