001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.util.cleanup;
006
007import edu.wpi.first.util.ErrorMessages;
008import java.util.ArrayDeque;
009import java.util.Deque;
010
011/**
012 * An object containing a Stack of AutoCloseable objects that are closed when this object is closed.
013 */
014public class CleanupPool implements AutoCloseable {
015  // Use a Deque instead of a Stack, as Stack's iterators go the wrong way, and docs
016  // state ArrayDeque is faster anyway.
017  private final Deque<AutoCloseable> m_closers = new ArrayDeque<>();
018
019  /** Default constructor. */
020  public CleanupPool() {}
021
022  /**
023   * Registers an object in the object stack for cleanup.
024   *
025   * @param <T> The object type
026   * @param object The object to register
027   * @return The registered object
028   */
029  public <T extends AutoCloseable> T register(T object) {
030    ErrorMessages.requireNonNullParam(object, "object", "register");
031    m_closers.addFirst(object);
032    return object;
033  }
034
035  /**
036   * Removes an object from the cleanup stack.
037   *
038   * @param object the object to remove
039   */
040  public void remove(AutoCloseable object) {
041    m_closers.remove(object);
042  }
043
044  /** Closes all objects in the stack. */
045  @Override
046  @SuppressWarnings("PMD.AvoidCatchingGenericException")
047  public void close() {
048    for (AutoCloseable autoCloseable : m_closers) {
049      try {
050        autoCloseable.close();
051      } catch (Exception e) {
052        // Swallow any exceptions on close
053        e.printStackTrace();
054      }
055    }
056    m_closers.clear();
057  }
058}