Skip to content

Commit

Permalink
Throw early when EventLoop is modified while running
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Dec 30, 2023
1 parent 0718376 commit 28144dc
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
18 changes: 18 additions & 0 deletions wpilibc/src/main/native/cpp/event/EventLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,39 @@
// the WPILib BSD license file in the root directory of this project.

#include "frc/event/EventLoop.h"
#include "frc/Errors.h"

using namespace frc;

namespace {
struct RunningSetter {
bool& m_running;
explicit RunningSetter(bool& running) noexcept : m_running{running} {
m_running = true;
}
~RunningSetter() noexcept { m_running = false; }
};
} // namespace

EventLoop::EventLoop() {}

void EventLoop::Bind(wpi::unique_function<void()> action) {
if (m_running) {
throw FRC_MakeError(err::Error, "Cannot bind EventLoop while it is running");
}
m_bindings.emplace_back(std::move(action));
}

void EventLoop::Poll() {
RunningSetter runSetter{m_running};
for (wpi::unique_function<void()>& action : m_bindings) {
action();
}
}

void EventLoop::Clear() {
if (m_running) {
throw FRC_MakeError(err::Error, "Cannot clear EventLoop while it is running");
}
m_bindings.clear();
}
1 change: 1 addition & 0 deletions wpilibc/src/main/native/include/frc/event/EventLoop.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ class EventLoop {

private:
std::vector<wpi::unique_function<void()>> m_bindings;
bool m_running;
};
} // namespace frc
15 changes: 14 additions & 1 deletion wpilibj/src/main/java/edu/wpi/first/wpilibj/event/EventLoop.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,43 @@
package edu.wpi.first.wpilibj.event;

import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.LinkedHashSet;

/**
* A declarative way to bind a set of actions to a loop and execute them when the loop is polled.
*/
public final class EventLoop {
private final Collection<Runnable> m_bindings = new LinkedHashSet<>();
private boolean m_running;

/**
* Bind a new action to run when the loop is polled.
*
* @param action the action to run.
*/
public void bind(Runnable action) {
if (m_running) {
throw new ConcurrentModificationException("Cannot bind EventLoop while it is running");
}
m_bindings.add(action);
}

/** Poll all bindings. */
public void poll() {
m_bindings.forEach(Runnable::run);
try {
m_running = true;
m_bindings.forEach(Runnable::run);
} finally {
m_running = false;
}
}

/** Clear all bindings. */
public void clear() {
if (m_running) {
throw new ConcurrentModificationException("Cannot clear EventLoop while it is running");
}
m_bindings.clear();
}
}

0 comments on commit 28144dc

Please sign in to comment.