From e5452e3f69c0e087b31558e005b6d5a96eb2fa85 Mon Sep 17 00:00:00 2001 From: Thad House Date: Mon, 10 Jul 2023 09:59:36 -0700 Subject: [PATCH] [wpiutil] Add WPICleaner and an example how to use it (#4850) --- .../first/net/MulticastServiceAnnouncer.java | 11 +++++++- .../first/net/MulticastServiceResolver.java | 11 +++++++- .../java/edu/wpi/first/util/WPICleaner.java | 28 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 wpiutil/src/main/java/edu/wpi/first/util/WPICleaner.java diff --git a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java index 6dff4541b2..9ccb322745 100644 --- a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java +++ b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceAnnouncer.java @@ -4,11 +4,18 @@ package edu.wpi.first.net; +import edu.wpi.first.util.WPICleaner; +import java.lang.ref.Cleaner.Cleanable; import java.util.Map; /** Class to announce over mDNS that a service is available. */ public class MulticastServiceAnnouncer implements AutoCloseable { private final int m_handle; + private final Cleanable m_cleanable; + + private static Runnable cleanupAction(int handle) { + return () -> WPINetJNI.freeMulticastServiceAnnouncer(handle); + } /** * Creates a MulticastServiceAnnouncer. @@ -24,6 +31,7 @@ public class MulticastServiceAnnouncer implements AutoCloseable { String[] values = txt.values().toArray(String[]::new); m_handle = WPINetJNI.createMulticastServiceAnnouncer(serviceName, serviceType, port, keys, values); + m_cleanable = WPICleaner.register(this, cleanupAction(m_handle)); } /** @@ -36,11 +44,12 @@ public class MulticastServiceAnnouncer implements AutoCloseable { public MulticastServiceAnnouncer(String serviceName, String serviceType, int port) { m_handle = WPINetJNI.createMulticastServiceAnnouncer(serviceName, serviceType, port, null, null); + m_cleanable = WPICleaner.register(this, cleanupAction(m_handle)); } @Override public void close() { - WPINetJNI.freeMulticastServiceAnnouncer(m_handle); + m_cleanable.clean(); } public void start() { diff --git a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java index 2426de29d6..b676f4c2dc 100644 --- a/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java +++ b/wpinet/src/main/java/edu/wpi/first/net/MulticastServiceResolver.java @@ -4,9 +4,17 @@ package edu.wpi.first.net; +import edu.wpi.first.util.WPICleaner; +import java.lang.ref.Cleaner.Cleanable; + /** Class to resolve a service over mDNS. */ public class MulticastServiceResolver implements AutoCloseable { private final int m_handle; + private final Cleanable m_cleanable; + + private static Runnable cleanupAction(int handle) { + return () -> WPINetJNI.freeMulticastServiceResolver(handle); + } /** * Creates a MulticastServiceResolver. @@ -15,11 +23,12 @@ public class MulticastServiceResolver implements AutoCloseable { */ public MulticastServiceResolver(String serviceType) { m_handle = WPINetJNI.createMulticastServiceResolver(serviceType); + m_cleanable = WPICleaner.register(this, cleanupAction(m_handle)); } @Override public void close() { - WPINetJNI.freeMulticastServiceResolver(m_handle); + m_cleanable.clean(); } public void start() { diff --git a/wpiutil/src/main/java/edu/wpi/first/util/WPICleaner.java b/wpiutil/src/main/java/edu/wpi/first/util/WPICleaner.java new file mode 100644 index 0000000000..0c497d4368 --- /dev/null +++ b/wpiutil/src/main/java/edu/wpi/first/util/WPICleaner.java @@ -0,0 +1,28 @@ +// 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; + +import java.lang.ref.Cleaner; +import java.lang.ref.Cleaner.Cleanable; + +/** Cleaner object for WPILib objects. */ +public final class WPICleaner { + private WPICleaner() { + throw new UnsupportedOperationException("This is a utility class!"); + } + + private static final Cleaner instance = Cleaner.create(); + + /** + * Register an object with the cleaner. + * + * @param object The object to register. + * @param runnable The runnable to call on cleanup. + * @return The registered Cleanable. + */ + public static Cleanable register(Object object, Runnable runnable) { + return instance.register(object, runnable); + } +}