Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]
    1   /*
    2    * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package sun.nio.ch;
   27   
   28   import java.nio.channels;
   29   import java.util;
   30   import sun.misc.Unsafe;
   31   
   32   /**
   33    * Maintains a mapping of pending I/O requests (identified by the address of
   34    * an OVERLAPPED structure) to Futures.
   35    */
   36   
   37   class PendingIoCache {
   38       private static final Unsafe unsafe = Unsafe.getUnsafe();
   39       private static final int addressSize = unsafe.addressSize();
   40   
   41       private static int dependsArch(int value32, int value64) {
   42           return (addressSize == 4) ? value32 : value64;
   43       }
   44   
   45       /*
   46        * typedef struct _OVERLAPPED {
   47        *     DWORD  Internal;
   48        *     DWORD  InternalHigh;
   49        *     DWORD  Offset;
   50        *     DWORD  OffsetHigh;
   51        *     HANDLE hEvent;
   52        * } OVERLAPPED;
   53        */
   54       private static final int SIZEOF_OVERLAPPED = dependsArch(20, 32);
   55   
   56       // set to true when closed
   57       private boolean closed;
   58   
   59       // set to true when thread is waiting for all I/O operations to complete
   60       private boolean closePending;
   61   
   62       // maps OVERLAPPED to PendingFuture
   63       private final Map<Long,PendingFuture> pendingIoMap =
   64           new HashMap<Long,PendingFuture>();
   65   
   66       // per-channel cache of OVERLAPPED structures
   67       private long[] overlappedCache = new long[4];
   68       private int overlappedCacheCount = 0;
   69   
   70       PendingIoCache() {
   71       }
   72   
   73       long add(PendingFuture<?,?> result) {
   74           synchronized (this) {
   75               if (closed)
   76                   throw new AssertionError("Should not get here");
   77               long ov;
   78               if (overlappedCacheCount > 0) {
   79                   ov = overlappedCache[--overlappedCacheCount];
   80               } else {
   81                   ov = unsafe.allocateMemory(SIZEOF_OVERLAPPED);
   82               }
   83               pendingIoMap.put(ov, result);
   84               return ov;
   85           }
   86       }
   87   
   88       @SuppressWarnings("unchecked")
   89       <V,A> PendingFuture<V,A> remove(long overlapped) {
   90           synchronized (this) {
   91               PendingFuture<V,A> res = pendingIoMap.remove(overlapped);
   92               if (res != null) {
   93                   if (overlappedCacheCount < overlappedCache.length) {
   94                       overlappedCache[overlappedCacheCount++] = overlapped;
   95                   } else {
   96                       // cache full or channel closing
   97                       unsafe.freeMemory(overlapped);
   98                   }
   99                   // notify closing thread.
  100                   if (closePending) {
  101                       this.notifyAll();
  102                   }
  103               }
  104               return res;
  105           }
  106       }
  107   
  108       void close() {
  109           synchronized (this) {
  110               if (closed)
  111                   return;
  112   
  113               // handle case where I/O operations that have not completed.
  114               if (!pendingIoMap.isEmpty())
  115                   clearPendingIoMap();
  116   
  117               // release memory for any cached OVERLAPPED structures
  118               while (overlappedCacheCount > 0) {
  119                   unsafe.freeMemory( overlappedCache[--overlappedCacheCount] );
  120               }
  121   
  122               // done
  123               closed = true;
  124           }
  125       }
  126   
  127       private void clearPendingIoMap() {
  128           assert Thread.holdsLock(this);
  129   
  130           // wait up to 50ms for the I/O operations to complete
  131           closePending = true;
  132           try {
  133               this.wait(50);
  134           } catch (InterruptedException x) {
  135               Thread.currentThread().interrupt();
  136           }
  137           closePending = false;
  138           if (pendingIoMap.isEmpty())
  139               return;
  140   
  141           // cause all pending I/O operations to fail
  142           // simulate the failure of all pending I/O operations.
  143           for (Long ov: pendingIoMap.keySet()) {
  144               PendingFuture<?,?> result = pendingIoMap.get(ov);
  145               assert !result.isDone();
  146   
  147               // make I/O port aware of the stale OVERLAPPED structure
  148               Iocp iocp = (Iocp)((Groupable)result.channel()).group();
  149               iocp.makeStale(ov);
  150   
  151               // execute a task that invokes the result handler's failed method
  152               final Iocp.ResultHandler rh = (Iocp.ResultHandler)result.getContext();
  153               Runnable task = new Runnable() {
  154                   public void run() {
  155                       rh.failed(-1, new AsynchronousCloseException());
  156                   }
  157               };
  158               iocp.executeOnPooledThread(task);
  159           }
  160           pendingIoMap.clear();
  161       }
  162   }

Save This Page
Home » openjdk-7 » sun » nio » ch » [javadoc | source]