2025-10-10 16:47:22 -04: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.command3;
|
2025-10-10 16:47:22 -04:00
|
|
|
|
|
|
|
|
import static java.util.Objects.requireNonNull;
|
|
|
|
|
|
|
|
|
|
/** Represents the state of a command as it is executed by the scheduler. */
|
|
|
|
|
final class CommandState {
|
|
|
|
|
// Two billion unique IDs should be enough for anybody.
|
|
|
|
|
private static int s_lastId = 0;
|
|
|
|
|
|
|
|
|
|
private final Command m_command;
|
|
|
|
|
private final Command m_parent;
|
|
|
|
|
private final Coroutine m_coroutine;
|
|
|
|
|
private final Binding m_binding;
|
|
|
|
|
private double m_lastRuntimeMs = -1;
|
|
|
|
|
private double m_totalRuntimeMs;
|
|
|
|
|
private final int m_id;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new command state object.
|
|
|
|
|
*
|
|
|
|
|
* @param command The command being tracked.
|
|
|
|
|
* @param parent The parent command composition that scheduled the tracked command. Null if the
|
|
|
|
|
* command was scheduled by a top level construct like trigger bindings or manually scheduled
|
|
|
|
|
* by a user. For deeply nested compositions, this tracks the <i>direct parent command</i>
|
|
|
|
|
* that invoked the schedule() call; in this manner, an ancestry tree can be built, where each
|
|
|
|
|
* {@code CommandState} object references a parent node in the tree.
|
|
|
|
|
* @param coroutine The coroutine to which the command is bound.
|
|
|
|
|
* @param binding The binding that caused the command to be scheduled.
|
|
|
|
|
*/
|
|
|
|
|
CommandState(Command command, Command parent, Coroutine coroutine, Binding binding) {
|
|
|
|
|
m_command = requireNonNull(command, "WPILib bug: command state given null command");
|
|
|
|
|
m_parent = parent; // allowed to be null
|
|
|
|
|
m_coroutine = requireNonNull(coroutine, "WPILib bug: command state given null coroutine");
|
|
|
|
|
m_binding = requireNonNull(binding, "WPILib bug: command state given null binding");
|
|
|
|
|
|
|
|
|
|
// This is incredibly non-thread safe, but nobody should be using the command framework across
|
|
|
|
|
// multiple threads anyway. Worst case scenario, we'll get duplicate IDs for commands scheduled
|
|
|
|
|
// by different threads and cause bad telemetry data without affecting program correctness.
|
|
|
|
|
m_id = ++s_lastId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Command command() {
|
|
|
|
|
return m_command;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Command parent() {
|
|
|
|
|
return m_parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Coroutine coroutine() {
|
|
|
|
|
return m_coroutine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Binding binding() {
|
|
|
|
|
return m_binding;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* How long the command took to run the last time it executed. Defaults to -1 if the command has
|
|
|
|
|
* not run at least once.
|
|
|
|
|
*
|
|
|
|
|
* @return The runtime, in milliseconds.
|
|
|
|
|
*/
|
|
|
|
|
public double lastRuntimeMs() {
|
|
|
|
|
return m_lastRuntimeMs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setLastRuntimeMs(double lastRuntimeMs) {
|
|
|
|
|
m_lastRuntimeMs = lastRuntimeMs;
|
|
|
|
|
m_totalRuntimeMs += lastRuntimeMs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public double totalRuntimeMs() {
|
|
|
|
|
return m_totalRuntimeMs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int id() {
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean equals(Object obj) {
|
|
|
|
|
return obj instanceof CommandState that && m_id == that.m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public int hashCode() {
|
|
|
|
|
return m_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String toString() {
|
|
|
|
|
return "CommandState[command=%s, parent=%s, coroutine=%s, id=%d]"
|
|
|
|
|
.formatted(m_command, m_parent, m_coroutine, m_id);
|
|
|
|
|
}
|
|
|
|
|
}
|