From bf7012fa2d27a3f8a528cea01926405da95777e7 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 10 Jan 2020 16:10:16 -0800 Subject: [PATCH] Fix new CommandScheduler.cancelAll() (#2251) When called outside the run loop, it would result in a CME in Java. --- .../wpilibj2/command/CommandScheduler.java | 4 ++-- .../cpp/frc2/command/CommandScheduler.cpp | 5 ++++- .../wpilibj2/command/ScheduleCommandTest.java | 2 +- .../first/wpilibj2/command/SchedulerTest.java | 20 ++++++++++++++++++- .../native/cpp/frc2/command/SchedulerTest.cpp | 20 ++++++++++++++++++- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java index d82e77fefe..b2110df708 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/CommandScheduler.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2008-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2008-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -375,7 +375,7 @@ public final class CommandScheduler implements Sendable { * Cancels all commands that are currently scheduled. */ public void cancelAll() { - for (Command command : m_scheduledCommands.keySet()) { + for (Command command : m_scheduledCommands.keySet().toArray(new Command[0])) { cancel(command); } } diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp index 842facbdbf..fbfabfb069 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandScheduler.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include "frc2/command/CommandGroupBase.h" #include "frc2/command/CommandState.h" @@ -310,9 +311,11 @@ void CommandScheduler::Cancel(std::initializer_list commands) { } void CommandScheduler::CancelAll() { + wpi::SmallVector commands; for (auto&& command : m_impl->scheduledCommands) { - Cancel(command.first); + commands.emplace_back(command.first); } + Cancel(commands); } double CommandScheduler::TimeSinceScheduled(const Command* command) const { diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java index 9041627a03..3e371fe391 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SchedulerTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SchedulerTest.java index 1f110b68ed..37ab0afc31 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SchedulerTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/SchedulerTest.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -54,4 +54,22 @@ class SchedulerTest extends CommandTestBase { scheduler.registerSubsystem(system); assertDoesNotThrow(() -> scheduler.unregisterSubsystem(system)); } + + @Test + void schedulerCancelAllTest() { + CommandScheduler scheduler = new CommandScheduler(); + + Counter counter = new Counter(); + + scheduler.onCommandInterrupt(command -> counter.increment()); + + Command command = new WaitCommand(10); + Command command2 = new WaitCommand(10); + + scheduler.schedule(command); + scheduler.schedule(command2); + scheduler.cancelAll(); + + assertEquals(counter.m_counter, 2); + } } diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/SchedulerTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/SchedulerTest.cpp index f0198c9187..2582ad9df1 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/SchedulerTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/SchedulerTest.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -54,3 +54,21 @@ TEST_F(SchedulerTest, UnregisterSubsystemTest) { EXPECT_NO_FATAL_FAILURE(scheduler.UnregisterSubsystem(&system)); } + +TEST_F(SchedulerTest, SchedulerCancelAllTest) { + CommandScheduler scheduler = GetScheduler(); + + RunCommand command([] {}, {}); + RunCommand command2([] {}, {}); + + int counter = 0; + + scheduler.OnCommandInterrupt([&counter](const Command&) { counter++; }); + + scheduler.Schedule(&command); + scheduler.Schedule(&command2); + scheduler.Run(); + scheduler.CancelAll(); + + EXPECT_EQ(counter, 2); +}