WindowsAsynchronousSocketChannelImpl(Iocp iocp, boolean failIfGroupShutdown) throws IOException { super(iocp); // associate socket with default completion port long h = IOUtil.fdVal(fd); int key = 0; try { key = iocp.associate(this, h); } catch (ShutdownChannelGroupException x) { if (failIfGroupShutdown) { closesocket0(h); throw x; } } catch (IOException x) { closesocket0(h); throw x; } this.handle = h; this.iocp = iocp; this.completionKey = key; this.ioCache = new PendingIoCache(); // allocate WSABUF arrays this.readBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY); this.writeBufferArray = unsafe.allocateMemory(SIZEOF_WSABUFARRAY); }
@Override <V extends Number, A> Future<V> implWrite( boolean gatheringWrite, ByteBuffer src, ByteBuffer[] srcs, long timeout, TimeUnit unit, A attachment, CompletionHandler<V, ? super A> handler) { // setup task PendingFuture<V, A> result = new PendingFuture<V, A>(this, handler, attachment); ByteBuffer[] bufs; if (gatheringWrite) { bufs = srcs; } else { bufs = new ByteBuffer[1]; bufs[0] = src; } final WriteTask writeTask = new WriteTask<V, A>(bufs, gatheringWrite, result); result.setContext(writeTask); // schedule timeout if (timeout > 0L) { Future<?> timeoutTask = iocp.schedule( new Runnable() { public void run() { writeTask.timeout(); } }, timeout, unit); result.setTimeoutTask(timeoutTask); } // initiate I/O (can only be done from thread in thread pool) // initiate I/O if (Iocp.supportsThreadAgnosticIo()) { writeTask.run(); } else { Invoker.invokeOnThreadInThreadPool(this, writeTask); } return result; }
@Override <A> Future<Void> implConnect( SocketAddress remote, A attachment, CompletionHandler<Void, ? super A> handler) { if (!isOpen()) { Throwable exc = new ClosedChannelException(); if (handler == null) return CompletedFuture.withFailure(exc); Invoker.invoke(this, handler, attachment, null, exc); return null; } InetSocketAddress isa = Net.checkAddress(remote); // permission check SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); // check and update state // ConnectEx requires the socket to be bound to a local address IOException bindException = null; synchronized (stateLock) { if (state == ST_CONNECTED) throw new AlreadyConnectedException(); if (state == ST_PENDING) throw new ConnectionPendingException(); if (localAddress == null) { try { bind(new InetSocketAddress(0)); } catch (IOException x) { bindException = x; } } if (bindException == null) state = ST_PENDING; } // handle bind failure if (bindException != null) { try { close(); } catch (IOException ignore) { } if (handler == null) return CompletedFuture.withFailure(bindException); Invoker.invoke(this, handler, attachment, null, bindException); return null; } // setup task PendingFuture<Void, A> result = new PendingFuture<Void, A>(this, handler, attachment); ConnectTask task = new ConnectTask<A>(isa, result); result.setContext(task); // initiate I/O if (Iocp.supportsThreadAgnosticIo()) { task.run(); } else { Invoker.invokeOnThreadInThreadPool(this, task); } return result; }
@Override <V extends Number, A> Future<V> implRead( boolean isScatteringRead, ByteBuffer dst, ByteBuffer[] dsts, long timeout, TimeUnit unit, A attachment, CompletionHandler<V, ? super A> handler) { // setup task PendingFuture<V, A> result = new PendingFuture<V, A>(this, handler, attachment); ByteBuffer[] bufs; if (isScatteringRead) { bufs = dsts; } else { bufs = new ByteBuffer[1]; bufs[0] = dst; } final ReadTask readTask = new ReadTask<V, A>(bufs, isScatteringRead, result); result.setContext(readTask); // schedule timeout if (timeout > 0L) { Future<?> timeoutTask = iocp.schedule( new Runnable() { public void run() { readTask.timeout(); } }, timeout, unit); result.setTimeoutTask(timeoutTask); } // initiate I/O if (Iocp.supportsThreadAgnosticIo()) { readTask.run(); } else { Invoker.invokeOnThreadInThreadPool(this, readTask); } return result; }
@Override void implClose() throws IOException { // close socket (may cause outstanding async I/O operations to fail). closesocket0(handle); // waits until all I/O operations have completed ioCache.close(); // release arrays of WSABUF structures unsafe.freeMemory(readBufferArray); unsafe.freeMemory(writeBufferArray); // finally disassociate from the completion port (key can be 0 if // channel created when group is shutdown) if (completionKey != 0) iocp.disassociate(completionKey); }