/*
 * Copyright (c) 2002-2016, the original author or authors.
 *
 * This software is distributable under the BSD license. See the terms of the
 * BSD license in the documentation provided with this software.
 *
 * https://opensource.org/licenses/BSD-3-Clause
 */
package jdk.internal.org.jline.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Manages the JLine shutdown-hook thread and tasks to execute on shutdown.
Author:Jason Dillon
Since:2.7
/** * Manages the JLine shutdown-hook thread and tasks to execute on shutdown. * * @author <a href="mailto:jason@planet57.com">Jason Dillon</a> * @since 2.7 */
public final class ShutdownHooks { private static final List<Task> tasks = new ArrayList<>(); private static Thread hook; public static synchronized <T extends Task> T add(final T task) { Objects.requireNonNull(task); // Install the hook thread if needed if (hook == null) { hook = addHook(new Thread("JLine Shutdown Hook") { @Override public void run() { runTasks(); } }); } // Track the task Log.debug("Adding shutdown-hook task: ", task); tasks.add(task); return task; } private static synchronized void runTasks() { Log.debug("Running all shutdown-hook tasks"); // Iterate through copy of tasks list for (Task task : tasks.toArray(new Task[tasks.size()])) { Log.debug("Running task: ", task); try { task.run(); } catch (Throwable e) { Log.warn("Task failed", e); } } tasks.clear(); } private static Thread addHook(final Thread thread) { Log.debug("Registering shutdown-hook: ", thread); Runtime.getRuntime().addShutdownHook(thread); return thread; } public static synchronized void remove(final Task task) { Objects.requireNonNull(task); // ignore if hook never installed if (hook == null) { return; } // Drop the task tasks.remove(task); // If there are no more tasks, then remove the hook thread if (tasks.isEmpty()) { removeHook(hook); hook = null; } } private static void removeHook(final Thread thread) { Log.debug("Removing shutdown-hook: ", thread); try { Runtime.getRuntime().removeShutdownHook(thread); } catch (IllegalStateException e) { // The VM is shutting down, not a big deal; ignore } }
Essentially a Runnable which allows running to throw an exception.
/** * Essentially a {@link Runnable} which allows running to throw an exception. */
public interface Task { void run() throws Exception; } }