google / guava

Google core libraries for Java
Apache License 2.0
50.25k stars 10.91k forks source link

Feature Request: Closer-like utility for AutoCloseable #3450

Open ryanhaining opened 5 years ago

ryanhaining commented 5 years ago

The existing Closer utility is great for Closeable but not AutoCloseable. I have encountered the need for a utility that can safely close a dynamic number of resources in try with resources. Python has contextlib.ExitStack to handle this exact issue with context managers, its use speaks to its usefulness. I'm using the name ClosingStack as a placeholder here, which would of course implement AutoCloseable

The usefulness can be demonstrated in two ways. First, when the number of resources is not known until runtime (a List of filenames where all files must be opened at the same time).

static void processFiles(List<Path> paths) {
  try (ClosingStack closingStack = new ClosingStack()) {
    List<BufferedReader> brs = new ArrayList<>();
    for (Path p : paths) {
      brs.add(closingStack.register(new BufferedReader(new FileReader(p))))
    }
    // use brs
  }
}

Second, less necessarily, when the number of resources is known at compile-time, but it is unwieldy to nest try-with-resources blocks

try (ClosingStack closingStack = new ClosingStack()) {
  A a = closingStack.register(new A());
  B b = closingStack.register(new B(A));
  C c = closingStack.register(new C(B));
  // use a, b, and c
}

ClosingStack#close would close registered objects in reverse order of registration. Like Closer, ClosingStack#close would create an exception object and suppress every exception thrown by its registered objects, and only throw if it encountered an exception when closing its registered resources.

Sample implementation on stackoverflow.

Given than many AutoCloseable types don't actually throw, I see the utility around a companion class with a non-throwing close

I'd be happy to implement this myself, modelling it after the existing Closer's code and tests.

cpovirk commented 5 years ago

This might help with internal bug 80534298, which is the bug that's supposed to be referenced in: https://github.com/google/guava/blob/89138e916d8c1445fafb40adb7c858a9a8e920ab/guava/src/com/google/common/collect/Streams.java#L142

That assumes that this would live in a package usable from common.collect, though (i.e., "not common.io").

castioussupreme commented 4 years ago

I wanted to agree here, but seeing as the defacto usage of AutoClosable is try with resources; it stands to reason the implementors here want to explicitly call out the need to register resources with a closer.