mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-21 01:01:43 +00:00
[wpiutil] Add reflection based cleanup helper (#4919)
Co-authored-by: Starlight220 <53231611+Starlight220@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.cleanup;
|
||||
|
||||
import edu.wpi.first.util.ErrorMessages;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
/**
|
||||
* An object containing a Stack of AutoCloseable objects that are closed when this object is closed.
|
||||
*/
|
||||
public class CleanupPool implements AutoCloseable {
|
||||
// Use a Deque instead of a Stack, as Stack's iterators go the wrong way, and docs
|
||||
// state ArrayDeque is faster anyway.
|
||||
private final Deque<AutoCloseable> m_closers = new ArrayDeque<AutoCloseable>();
|
||||
|
||||
/**
|
||||
* Registers an object in the object stack for cleanup.
|
||||
*
|
||||
* @param <T> The object type
|
||||
* @param object The object to register
|
||||
* @return The registered object
|
||||
*/
|
||||
public <T extends AutoCloseable> T register(T object) {
|
||||
ErrorMessages.requireNonNullParam(object, "object", "register");
|
||||
m_closers.addFirst(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an object from the cleanup stack.
|
||||
*
|
||||
* @param object the object to remove
|
||||
*/
|
||||
public void remove(AutoCloseable object) {
|
||||
m_closers.remove(object);
|
||||
}
|
||||
|
||||
/** Closes all objects in the stack. */
|
||||
@Override
|
||||
@SuppressWarnings("PMD.AvoidCatchingGenericException")
|
||||
public void close() {
|
||||
for (AutoCloseable autoCloseable : m_closers) {
|
||||
try {
|
||||
autoCloseable.close();
|
||||
} catch (Exception e) {
|
||||
// Swallow any exceptions on close
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
m_closers.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.cleanup;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Implement this interface to have access to a `reflectionCleanup` method that can be called from
|
||||
* your `close` method, that will use reflection to find all `AutoCloseable` instance members and
|
||||
* close them.
|
||||
*/
|
||||
public interface ReflectionCleanup extends AutoCloseable {
|
||||
/**
|
||||
* Default implementation that uses reflection to find all AutoCloseable fields not marked
|
||||
* SkipCleanup and call close() on them. Call this from your `close()` method with the class level
|
||||
* you want to close.
|
||||
*
|
||||
* @param cls the class level to clean up
|
||||
*/
|
||||
@SuppressWarnings("PMD.AvoidCatchingGenericException")
|
||||
default void reflectionCleanup(Class<? extends ReflectionCleanup> cls) {
|
||||
if (!cls.isAssignableFrom(getClass())) {
|
||||
System.out.println("Passed in class is not assignable from \"this\"");
|
||||
System.out.println("Expected something in the hierarchy of" + cls.getName());
|
||||
System.out.println("This is " + getClass().getName());
|
||||
return;
|
||||
}
|
||||
for (Field field : cls.getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(SkipCleanup.class)) {
|
||||
continue;
|
||||
}
|
||||
if (!AutoCloseable.class.isAssignableFrom(field.getType())) {
|
||||
continue;
|
||||
}
|
||||
if (field.trySetAccessible()) {
|
||||
try {
|
||||
AutoCloseable c = (AutoCloseable) field.get(this);
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore any exceptions
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.util.cleanup;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SkipCleanup {}
|
||||
Reference in New Issue
Block a user