src/windows/classes/java/io/FileDescriptor.java
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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,12 @@
* questions.
*/
package java.io;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.ArrayList;
+import java.util.List;
/**
* 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.
@@ -43,26 +44,21 @@
private int fd;
private long handle;
- /**
- * A use 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 use by any stream.
- */
- private AtomicInteger useCount;
+ private Closeable parent;
+ private List<Closeable> otherParents;
+ private boolean closed;
-
/**
* Constructs an (invalid) FileDescriptor
* object.
*/
public /**/ FileDescriptor() {
fd = -1;
handle = -1;
- useCount = new AtomicInteger();
}
static {
initIDs();
}
@@ -166,15 +162,69 @@
FileDescriptor desc = new FileDescriptor();
desc.handle = set(fd);
return desc;
}
- // 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.
+ * parent reference is added to otherParents when
+ * needed to make closeAll simpler.
+ */
+ synchronized void attach(Closeable c) {
+ if (parent == null) {
+ // first caller 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;
+ }
+ }
+ }
}