2024-08-23 10:05:53 -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.
|
|
|
|
|
|
|
|
|
|
#include "frc/Alert.h"
|
|
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
#include <set>
|
2024-09-20 17:43:39 -07:00
|
|
|
#include <string>
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
#include <utility>
|
2024-09-20 17:43:39 -07:00
|
|
|
#include <vector>
|
2024-08-23 10:05:53 -04:00
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
#include <fmt/format.h>
|
|
|
|
|
#include <networktables/NTSendable.h>
|
2024-08-23 10:05:53 -04:00
|
|
|
#include <networktables/NTSendableBuilder.h>
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
#include <wpi/StringMap.h>
|
|
|
|
|
#include <wpi/sendable/SendableHelper.h>
|
|
|
|
|
#include <wpi/sendable/SendableRegistry.h>
|
2024-08-23 10:05:53 -04:00
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
#include "frc/Errors.h"
|
|
|
|
|
#include "frc/RobotController.h"
|
2024-09-20 17:43:39 -07:00
|
|
|
#include "frc/smartdashboard/SmartDashboard.h"
|
|
|
|
|
|
2024-08-23 10:05:53 -04:00
|
|
|
using namespace frc;
|
|
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
class Alert::PublishedAlert {
|
|
|
|
|
public:
|
|
|
|
|
PublishedAlert(uint64_t timestamp, std::string_view text)
|
|
|
|
|
: timestamp{timestamp}, text{text} {}
|
|
|
|
|
uint64_t timestamp;
|
|
|
|
|
std::string text;
|
|
|
|
|
auto operator<=>(const PublishedAlert& other) const {
|
|
|
|
|
if (timestamp != other.timestamp) {
|
|
|
|
|
return other.timestamp <=> timestamp;
|
|
|
|
|
} else {
|
|
|
|
|
return text <=> other.text;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Alert::SendableAlerts : public nt::NTSendable,
|
|
|
|
|
public wpi::SendableHelper<SendableAlerts> {
|
|
|
|
|
public:
|
|
|
|
|
SendableAlerts() { m_alerts.fill({}); }
|
|
|
|
|
|
|
|
|
|
void InitSendable(nt::NTSendableBuilder& builder) override {
|
|
|
|
|
builder.SetSmartDashboardType("Alerts");
|
|
|
|
|
builder.AddStringArrayProperty(
|
|
|
|
|
"errors", [this]() { return GetStrings(AlertType::kError); }, nullptr);
|
|
|
|
|
builder.AddStringArrayProperty(
|
|
|
|
|
"warnings", [this]() { return GetStrings(AlertType::kWarning); },
|
|
|
|
|
nullptr);
|
|
|
|
|
builder.AddStringArrayProperty(
|
|
|
|
|
"infos", [this]() { return GetStrings(AlertType::kInfo); }, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a reference to the set of active alerts for the given type.
|
|
|
|
|
* @param type the type
|
|
|
|
|
* @return reference to the set of active alerts for the type
|
|
|
|
|
*/
|
|
|
|
|
std::set<PublishedAlert>& GetActiveAlertsStorage(AlertType type) {
|
|
|
|
|
return const_cast<std::set<Alert::PublishedAlert>&>(
|
|
|
|
|
std::as_const(*this).GetActiveAlertsStorage(type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::set<PublishedAlert>& GetActiveAlertsStorage(AlertType type) const {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case AlertType::kInfo:
|
|
|
|
|
case AlertType::kWarning:
|
|
|
|
|
case AlertType::kError:
|
|
|
|
|
return m_alerts[static_cast<int32_t>(type)];
|
|
|
|
|
default:
|
|
|
|
|
throw FRC_MakeError(frc::err::InvalidParameter,
|
|
|
|
|
"Invalid Alert Type: {}", type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the SendableAlerts for a given group, initializing and publishing
|
|
|
|
|
* if it does not already exist.
|
|
|
|
|
* @param group the group name
|
|
|
|
|
* @return the SendableAlerts for the group
|
|
|
|
|
*/
|
|
|
|
|
static SendableAlerts& ForGroup(std::string_view group) {
|
2025-02-12 01:05:22 -05:00
|
|
|
SendableAlerts* salert = nullptr;
|
|
|
|
|
try {
|
|
|
|
|
auto* sendable = frc::SmartDashboard::GetData(group);
|
|
|
|
|
salert = dynamic_cast<SendableAlerts*>(sendable);
|
|
|
|
|
} catch (frc::RuntimeError&) {
|
|
|
|
|
}
|
|
|
|
|
if (!salert) {
|
|
|
|
|
// this leaks if ResetSmartDashboardInstance is called, but that's fine
|
|
|
|
|
salert = new Alert::SendableAlerts;
|
|
|
|
|
frc::SmartDashboard::PutData(group, salert);
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
}
|
2025-02-12 01:05:22 -05:00
|
|
|
return *salert;
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::vector<std::string> GetStrings(AlertType type) const {
|
|
|
|
|
auto& set = GetActiveAlertsStorage(type);
|
|
|
|
|
std::vector<std::string> output;
|
|
|
|
|
output.reserve(set.size());
|
|
|
|
|
for (auto& alert : set) {
|
|
|
|
|
output.emplace_back(alert.text);
|
|
|
|
|
}
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::array<std::set<PublishedAlert>, 3> m_alerts;
|
|
|
|
|
};
|
|
|
|
|
|
2024-08-23 10:05:53 -04:00
|
|
|
Alert::Alert(std::string_view text, AlertType type)
|
|
|
|
|
: Alert("Alerts", text, type) {}
|
|
|
|
|
|
|
|
|
|
Alert::Alert(std::string_view group, std::string_view text, AlertType type)
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
: m_type(type),
|
|
|
|
|
m_text(text),
|
|
|
|
|
m_activeAlerts{
|
|
|
|
|
&SendableAlerts::ForGroup(group).GetActiveAlertsStorage(m_type)} {}
|
|
|
|
|
|
|
|
|
|
Alert::Alert(Alert&& other)
|
|
|
|
|
: m_type{other.m_type},
|
|
|
|
|
m_text{std::move(other.m_text)},
|
|
|
|
|
m_activeAlerts{std::exchange(other.m_activeAlerts, nullptr)},
|
|
|
|
|
m_active{std::exchange(other.m_active, false)},
|
|
|
|
|
m_activeStartTime{other.m_activeStartTime} {}
|
|
|
|
|
|
|
|
|
|
Alert& Alert::operator=(Alert&& other) {
|
|
|
|
|
if (&other != this) {
|
|
|
|
|
// We want to destroy current state after the move is done
|
|
|
|
|
Alert tmp{std::move(*this)};
|
|
|
|
|
// Now, swap moved-from state with other state
|
|
|
|
|
std::swap(m_type, other.m_type);
|
|
|
|
|
std::swap(m_text, other.m_text);
|
|
|
|
|
std::swap(m_activeAlerts, other.m_activeAlerts);
|
|
|
|
|
std::swap(m_active, other.m_active);
|
|
|
|
|
std::swap(m_activeStartTime, other.m_activeStartTime);
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Alert::~Alert() {
|
|
|
|
|
Set(false);
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Alert::Set(bool active) {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (active == m_active) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (active) {
|
2024-11-16 10:43:38 -05:00
|
|
|
m_activeStartTime = frc::RobotController::GetTime();
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
m_activeAlerts->emplace(m_activeStartTime, m_text);
|
|
|
|
|
} else {
|
|
|
|
|
m_activeAlerts->erase({m_activeStartTime, m_text});
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
m_active = active;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Alert::SetText(std::string_view text) {
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (text == m_text) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string oldText = std::move(m_text);
|
2024-08-23 10:05:53 -04:00
|
|
|
m_text = text;
|
|
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
if (m_active) {
|
|
|
|
|
auto iter = m_activeAlerts->find({m_activeStartTime, oldText});
|
|
|
|
|
auto hint = m_activeAlerts->erase(iter);
|
|
|
|
|
m_activeAlerts->emplace_hint(hint, m_activeStartTime, m_text);
|
|
|
|
|
}
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
|
[wpilib] Refactor Alert (#7279)
This refactors Alert in both c++ and java to fix the issues with the current c++ implementation and improve performance.
Currently, constructing an Alert adds it to a list of Alerts with the same group and type. Activating an alert sets a flag on the alert. When the SendableAlerts is polled (GetStrings), the entire list is iterated over, filtered, and the filtered list is sorted by timestamp. This leads to a worst case O(m + nlog(n)) time complexity for GetStrings, where m and n are the count of total constructed alerts active alerts respectively. It also allocates intermediate data structures to hold the active alert strings for sorting.
This changes the implementation to improve the performance of GetStrings, by shifting the sorting overhead to Alert.Set
Constructing the Alert only initializes the alert's initial state, and initializes the SendableAlerts for the group if it is not already initialized.
Activating or deactivating an alert sets an internal flag for state tracking, and inserts or removes a structure containing the timestamp and text into a self-sorting data structure (std::set, TreeSet) containing other active alerts with the same group and type. (worst case O(log(n))
Now, SendableAlerts.GetStrings only has to iterate over the structure and copy the strings to the returned array. (amortized O(n))
This also fixes the c++ implementation by removing the need for SendableAlerts to directly access the Alert.
This also adds a helper method to SendableRegistry to force initialization of the instance to prevent static initialization ordering issues.
2024-11-06 18:09:06 -05:00
|
|
|
std::string frc::format_as(Alert::AlertType type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case Alert::AlertType::kInfo:
|
|
|
|
|
return "kInfo";
|
|
|
|
|
case Alert::AlertType::kWarning:
|
|
|
|
|
return "kWarning";
|
|
|
|
|
case Alert::AlertType::kError:
|
|
|
|
|
return "kError";
|
|
|
|
|
default:
|
|
|
|
|
return std::to_string(static_cast<int>(type));
|
2024-08-23 10:05:53 -04:00
|
|
|
}
|
|
|
|
|
}
|