src/solaris/classes/java/io/FileDescriptor.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -23,11 +23,11 @@
  * questions.
  */
 
 package java.io;
 
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.ArrayList;
 
 /**
  * Instances of the file descriptor class serve as an opaque handle
  * to the underlying machine-specific structure representing an open
  * file, an open socket, or another source or sink of bytes. The

@@ -44,29 +44,24 @@
  */
 public final class FileDescriptor {
 
     private int fd;
 
-    /**
-     * A counter for tracking the FIS/FOS/RAF instances that
-     * use this FileDescriptor. The FIS/FOS.finalize() will not release
-     * the FileDescriptor if it is still under user by a stream.
-     */
-    private AtomicInteger useCount;
+    private Closeable parent;
+    private ArrayList<Closeable> otherParents;
+    boolean closed = false;
 
     /**
      * Constructs an (invalid) FileDescriptor
      * object.
      */
     public /**/ FileDescriptor() {
         fd = -1;
-        useCount = new AtomicInteger();
     }
 
     private /* */ FileDescriptor(int fd) {
         this.fd = fd;
-        useCount = new AtomicInteger();
     }
 
     /**
      * A handle to the standard input stream. Usually, this file
      * descriptor is not used directly, but rather via the input stream

@@ -162,15 +157,67 @@
                 }
             }
         );
     }
 
-    // package private methods used by FIS, FOS and RAF
+    /*
+     * Package private methods to track referents.
+     * If multiple streams point to the same FileDescriptor, we cycle
+     * through the list of all referents and call close()
+     */
 
-    int incrementAndGetUseCount() {
-        return useCount.incrementAndGet();
+    /*
+     * attach a Closeable to this FD for tracking
+     */
+    synchronized void attach(Closeable c) {
+        if (parent == null) {
+            // constructor gets to do this
+            parent = c;
+        } else if (otherParents == null) {
+            otherParents = new ArrayList<>();
+            otherParents.add(parent);
+            otherParents.add(c);
+        } else {
+            otherParents.add(c);
     }
+    }
 
-    int decrementAndGetUseCount() {
-        return useCount.decrementAndGet();
+    /*
+     * Cycle through all Closeables sharing this FD and call
+     * close() on each one.
+     *
+     * The caller closeable gets to call close0().
+     */
+    @SuppressWarnings("try")
+    synchronized void closeAll(Closeable releaser) throws IOException {
+        if (!closed) { 
+            closed = true;
+            IOException ioe = null;
+            try (Closeable c = releaser) {
+                if (otherParents != null) {
+                    for (Closeable referent : otherParents) {
+                        try {
+                            referent.close();
+                        } catch(IOException x) {
+                            if (ioe == null) {
+                                ioe = x;
+                            } else {
+                                ioe.addSuppressed(x);
     }
+                        }
+                    }
+                }
+            } catch(IOException ex) {
+                // if releaser close() throws IOException
+                // add other exceptions as suppressed
+                if (ioe != null) {
+                    ex.addSuppressed(ioe);
+                }
+                ioe = ex;
+            } finally {
+                if (ioe != null) {
+                    throw ioe;
+                }
+            }
+        }
+    }
 }