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;
+ }
+ }
+ }
+ }
}