Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/nio/ch/PendingIoCache.java
32288 views
/*1* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.nio.channels.*;28import java.util.*;29import sun.misc.Unsafe;3031/**32* Maintains a mapping of pending I/O requests (identified by the address of33* an OVERLAPPED structure) to Futures.34*/3536class PendingIoCache {37private static final Unsafe unsafe = Unsafe.getUnsafe();38private static final int addressSize = unsafe.addressSize();3940private static int dependsArch(int value32, int value64) {41return (addressSize == 4) ? value32 : value64;42}4344/*45* typedef struct _OVERLAPPED {46* DWORD Internal;47* DWORD InternalHigh;48* DWORD Offset;49* DWORD OffsetHigh;50* HANDLE hEvent;51* } OVERLAPPED;52*/53private static final int SIZEOF_OVERLAPPED = dependsArch(20, 32);5455// set to true when closed56private boolean closed;5758// set to true when thread is waiting for all I/O operations to complete59private boolean closePending;6061// maps OVERLAPPED to PendingFuture62@SuppressWarnings("rawtypes")63private final Map<Long,PendingFuture> pendingIoMap =64new HashMap<Long,PendingFuture>();6566// per-channel cache of OVERLAPPED structures67private long[] overlappedCache = new long[4];68private int overlappedCacheCount = 0;6970PendingIoCache() {71}7273long add(PendingFuture<?,?> result) {74synchronized (this) {75if (closed)76throw new AssertionError("Should not get here");77long ov;78if (overlappedCacheCount > 0) {79ov = overlappedCache[--overlappedCacheCount];80} else {81ov = unsafe.allocateMemory(SIZEOF_OVERLAPPED);82}83pendingIoMap.put(ov, result);84return ov;85}86}8788@SuppressWarnings("unchecked")89<V,A> PendingFuture<V,A> remove(long overlapped) {90synchronized (this) {91PendingFuture<V,A> res = pendingIoMap.remove(overlapped);92if (res != null) {93if (overlappedCacheCount < overlappedCache.length) {94overlappedCache[overlappedCacheCount++] = overlapped;95} else {96// cache full or channel closing97unsafe.freeMemory(overlapped);98}99// notify closing thread.100if (closePending) {101this.notifyAll();102}103}104return res;105}106}107108void close() {109synchronized (this) {110if (closed)111return;112113// handle case where I/O operations that have not completed.114if (!pendingIoMap.isEmpty())115clearPendingIoMap();116117// release memory for any cached OVERLAPPED structures118while (overlappedCacheCount > 0) {119unsafe.freeMemory( overlappedCache[--overlappedCacheCount] );120}121122// done123closed = true;124}125}126127private void clearPendingIoMap() {128assert Thread.holdsLock(this);129130// wait up to 50ms for the I/O operations to complete131closePending = true;132try {133this.wait(50);134} catch (InterruptedException x) {135Thread.currentThread().interrupt();136}137closePending = false;138if (pendingIoMap.isEmpty())139return;140141// cause all pending I/O operations to fail142// simulate the failure of all pending I/O operations.143for (Long ov: pendingIoMap.keySet()) {144PendingFuture<?,?> result = pendingIoMap.get(ov);145assert !result.isDone();146147// make I/O port aware of the stale OVERLAPPED structure148Iocp iocp = (Iocp)((Groupable)result.channel()).group();149iocp.makeStale(ov);150151// execute a task that invokes the result handler's failed method152final Iocp.ResultHandler rh = (Iocp.ResultHandler)result.getContext();153Runnable task = new Runnable() {154public void run() {155rh.failed(-1, new AsynchronousCloseException());156}157};158iocp.executeOnPooledThread(task);159}160pendingIoMap.clear();161}162}163164165