2022-06-09 08:16:51 +03:00
|
|
|
// 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.
|
|
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
package org.wpilib.event;
|
2022-06-09 08:16:51 +03:00
|
|
|
|
|
|
|
|
import java.util.Collection;
|
2023-12-31 22:45:10 -08:00
|
|
|
import java.util.ConcurrentModificationException;
|
2022-06-09 08:16:51 +03:00
|
|
|
import java.util.LinkedHashSet;
|
|
|
|
|
|
2023-07-23 17:22:04 -04:00
|
|
|
/**
|
|
|
|
|
* A declarative way to bind a set of actions to a loop and execute them when the loop is polled.
|
|
|
|
|
*/
|
2022-06-09 08:16:51 +03:00
|
|
|
public final class EventLoop {
|
2022-11-28 23:48:48 +02:00
|
|
|
private final Collection<Runnable> m_bindings = new LinkedHashSet<>();
|
2023-12-31 22:45:10 -08:00
|
|
|
private boolean m_running;
|
2022-06-09 08:16:51 +03:00
|
|
|
|
2024-01-04 13:57:21 -08:00
|
|
|
/** Default constructor. */
|
|
|
|
|
public EventLoop() {}
|
|
|
|
|
|
2022-06-09 08:16:51 +03:00
|
|
|
/**
|
2023-07-23 17:22:04 -04:00
|
|
|
* Bind a new action to run when the loop is polled.
|
2022-06-09 08:16:51 +03:00
|
|
|
*
|
|
|
|
|
* @param action the action to run.
|
|
|
|
|
*/
|
2022-11-28 23:48:48 +02:00
|
|
|
public void bind(Runnable action) {
|
2023-12-31 22:45:10 -08:00
|
|
|
if (m_running) {
|
|
|
|
|
throw new ConcurrentModificationException("Cannot bind EventLoop while it is running");
|
|
|
|
|
}
|
2022-11-28 23:48:48 +02:00
|
|
|
m_bindings.add(action);
|
2022-06-09 08:16:51 +03:00
|
|
|
}
|
|
|
|
|
|
2026-05-07 19:32:34 -04:00
|
|
|
/**
|
|
|
|
|
* Unbind an action from running when the loop is polled. Has no effect if the given action is not
|
|
|
|
|
* already bound.
|
|
|
|
|
*
|
|
|
|
|
* @param action the action to unbind.
|
|
|
|
|
*/
|
|
|
|
|
public void unbind(Runnable action) {
|
|
|
|
|
if (m_running) {
|
|
|
|
|
throw new ConcurrentModificationException("Cannot unbind EventLoop while it is running");
|
|
|
|
|
}
|
|
|
|
|
m_bindings.remove(action);
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-09 08:16:51 +03:00
|
|
|
/** Poll all bindings. */
|
2024-06-09 01:08:23 -04:00
|
|
|
@SuppressWarnings("PMD.UnusedAssignment")
|
2022-06-09 08:16:51 +03:00
|
|
|
public void poll() {
|
2023-12-31 22:45:10 -08:00
|
|
|
try {
|
|
|
|
|
m_running = true;
|
|
|
|
|
m_bindings.forEach(Runnable::run);
|
|
|
|
|
} finally {
|
|
|
|
|
m_running = false;
|
|
|
|
|
}
|
2022-06-09 08:16:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Clear all bindings. */
|
|
|
|
|
public void clear() {
|
2023-12-31 22:45:10 -08:00
|
|
|
if (m_running) {
|
|
|
|
|
throw new ConcurrentModificationException("Cannot clear EventLoop while it is running");
|
|
|
|
|
}
|
2022-06-09 08:16:51 +03:00
|
|
|
m_bindings.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|