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  /**
020   * Registers an object in the object stack for cleanup.
021   *
022   * @param <T> The object type
023   * @param object The object to register
024   * @return The registered object
025   */
026  public <T extends AutoCloseable> T register(T object) {
027    ErrorMessages.requireNonNullParam(object, "object", "register");
028    m_closers.addFirst(object);
029    return object;
030  }
031
032  /**
033   * Removes an object from the cleanup stack.
034   *
035   * @param object the object to remove
036   */
037  public void remove(AutoCloseable object) {
038    m_closers.remove(object);
039  }
040
041  /** Closes all objects in the stack. */
042  @Override
043  @SuppressWarnings("PMD.AvoidCatchingGenericException")
044  public void close() {
045    for (AutoCloseable autoCloseable : m_closers) {
046      try {
047        autoCloseable.close();
048      } catch (Exception e) {
049        // Swallow any exceptions on close
050        e.printStackTrace();
051      }
052    }
053    m_closers.clear();
054  }
055}