Fix move handling of C++ Sendable in SmartDashboard and LiveWindow

This commit is contained in:
Peter Johnson
2019-10-17 22:01:31 -07:00
parent d726591ce4
commit 05c25deb7b
6 changed files with 244 additions and 134 deletions

View File

@@ -24,7 +24,6 @@ struct LiveWindow::Impl {
Impl();
struct Component {
SendableBuilderImpl builder;
bool firstTime = true;
bool telemetryEnabled = true;
};
@@ -85,13 +84,11 @@ void LiveWindow::DisableTelemetry(Sendable* sendable) {
void LiveWindow::DisableAllTelemetry() {
std::scoped_lock lock(m_impl->mutex);
m_impl->telemetryEnabled = false;
m_impl->registry.ForeachLiveWindow(
m_impl->dataHandle, [&](Sendable*, wpi::StringRef, wpi::StringRef,
Sendable*, std::shared_ptr<void>& data) {
if (!data) data = std::make_shared<Impl::Component>();
std::static_pointer_cast<Impl::Component>(data)->telemetryEnabled =
false;
});
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
if (!cbdata.data) cbdata.data = std::make_shared<Impl::Component>();
std::static_pointer_cast<Impl::Component>(cbdata.data)->telemetryEnabled =
false;
});
}
bool LiveWindow::IsEnabled() const {
@@ -111,13 +108,9 @@ void LiveWindow::SetEnabled(bool enabled) {
scheduler->SetEnabled(false);
scheduler->RemoveAll();
} else {
m_impl->registry.ForeachLiveWindow(
m_impl->dataHandle, [&](Sendable*, wpi::StringRef, wpi::StringRef,
Sendable*, std::shared_ptr<void>& data) {
if (data)
std::static_pointer_cast<Impl::Component>(data)
->builder.StopLiveWindowMode();
});
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
cbdata.builder.StopLiveWindowMode();
});
scheduler->SetEnabled(true);
}
m_impl->enabledEntry.SetBoolean(enabled);
@@ -132,42 +125,39 @@ void LiveWindow::UpdateValuesUnsafe() {
// Only do this if either LiveWindow mode or telemetry is enabled.
if (!m_impl->liveWindowEnabled && !m_impl->telemetryEnabled) return;
m_impl->registry.ForeachLiveWindow(
m_impl->dataHandle,
[&](Sendable* sendable, wpi::StringRef name, wpi::StringRef subsystem,
Sendable* parent, std::shared_ptr<void>& data) {
if (!sendable || parent) return;
m_impl->registry.ForeachLiveWindow(m_impl->dataHandle, [&](auto& cbdata) {
if (!cbdata.sendable || cbdata.parent) return;
if (!data) data = std::make_shared<Impl::Component>();
if (!cbdata.data) cbdata.data = std::make_shared<Impl::Component>();
auto& comp = *std::static_pointer_cast<Impl::Component>(data);
auto& comp = *std::static_pointer_cast<Impl::Component>(cbdata.data);
if (!m_impl->liveWindowEnabled && !comp.telemetryEnabled) return;
if (!m_impl->liveWindowEnabled && !comp.telemetryEnabled) return;
if (comp.firstTime) {
// By holding off creating the NetworkTable entries, it allows the
// components to be redefined. This allows default sensor and actuator
// values to be created that are replaced with the custom names from
// users calling setName.
if (name.empty()) return;
auto ssTable = m_impl->liveWindowTable->GetSubTable(subsystem);
std::shared_ptr<NetworkTable> table;
// Treat name==subsystem as top level of subsystem
if (name == subsystem)
table = ssTable;
else
table = ssTable->GetSubTable(name);
table->GetEntry(".name").SetString(name);
comp.builder.SetTable(table);
sendable->InitSendable(comp.builder);
ssTable->GetEntry(".type").SetString("LW Subsystem");
if (comp.firstTime) {
// By holding off creating the NetworkTable entries, it allows the
// components to be redefined. This allows default sensor and actuator
// values to be created that are replaced with the custom names from
// users calling setName.
if (cbdata.name.empty()) return;
auto ssTable = m_impl->liveWindowTable->GetSubTable(cbdata.subsystem);
std::shared_ptr<NetworkTable> table;
// Treat name==subsystem as top level of subsystem
if (cbdata.name == cbdata.subsystem)
table = ssTable;
else
table = ssTable->GetSubTable(cbdata.name);
table->GetEntry(".name").SetString(cbdata.name);
cbdata.builder.SetTable(table);
cbdata.sendable->InitSendable(cbdata.builder);
ssTable->GetEntry(".type").SetString("LW Subsystem");
comp.firstTime = false;
}
comp.firstTime = false;
}
if (m_impl->startLiveWindow) comp.builder.StartLiveWindowMode();
comp.builder.UpdateTable();
});
if (m_impl->startLiveWindow) cbdata.builder.StartLiveWindowMode();
cbdata.builder.UpdateTable();
});
m_impl->startLiveWindow = false;
}

View File

@@ -23,6 +23,8 @@ std::shared_ptr<nt::NetworkTable> SendableBuilderImpl::GetTable() {
return m_table;
}
bool SendableBuilderImpl::HasTable() const { return m_table != nullptr; }
bool SendableBuilderImpl::IsActuator() const { return m_actuator; }
void SendableBuilderImpl::UpdateTable() {
@@ -53,6 +55,8 @@ void SendableBuilderImpl::StopLiveWindowMode() {
if (m_safeState) m_safeState();
}
void SendableBuilderImpl::ClearProperties() { m_properties.clear(); }
void SendableBuilderImpl::SetSmartDashboardType(const wpi::Twine& type) {
m_table->GetEntry(".type").SetString(type);
}

View File

@@ -7,15 +7,22 @@
#include "frc/smartdashboard/SendableRegistry.h"
#include <memory>
#include <wpi/DenseMap.h>
#include <wpi/SmallVector.h>
#include <wpi/UidVector.h>
#include <wpi/mutex.h>
#include "frc/smartdashboard/Sendable.h"
#include "frc/smartdashboard/SendableBuilderImpl.h"
using namespace frc;
struct SendableRegistry::Impl {
struct Component {
Sendable* sendable = nullptr;
SendableBuilderImpl builder;
std::string name;
std::string subsystem = "Ungrouped";
Sendable* parent = nullptr;
@@ -37,17 +44,21 @@ struct SendableRegistry::Impl {
wpi::mutex mutex;
wpi::DenseMap<void*, Component> components;
wpi::UidVector<std::unique_ptr<Component>, 32> components;
wpi::DenseMap<void*, UID> componentMap;
int nextDataHandle = 0;
Component& GetOrAdd(Sendable* sendable);
Component& GetOrAdd(void* sendable, UID* uid = nullptr);
};
SendableRegistry::Impl::Component& SendableRegistry::Impl::GetOrAdd(
Sendable* sendable) {
auto& comp = components[sendable];
comp.sendable = sendable;
return comp;
void* sendable, UID* uid) {
UID& compUid = componentMap[sendable];
if (compUid == 0)
compUid = components.emplace_back(std::make_unique<Component>()) + 1;
if (uid) *uid = compUid;
return *components[compUid - 1];
}
SendableRegistry& SendableRegistry::GetInstance() {
@@ -58,6 +69,7 @@ SendableRegistry& SendableRegistry::GetInstance() {
void SendableRegistry::Add(Sendable* sendable, const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.name = name.str();
}
@@ -65,6 +77,7 @@ void SendableRegistry::Add(Sendable* sendable, const wpi::Twine& moduleType,
int channel) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.SetName(moduleType, channel);
}
@@ -72,6 +85,7 @@ void SendableRegistry::Add(Sendable* sendable, const wpi::Twine& moduleType,
int moduleNumber, int channel) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.SetName(moduleType, moduleNumber, channel);
}
@@ -79,6 +93,7 @@ void SendableRegistry::Add(Sendable* sendable, const wpi::Twine& subsystem,
const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.name = name.str();
comp.subsystem = subsystem.str();
}
@@ -86,6 +101,7 @@ void SendableRegistry::Add(Sendable* sendable, const wpi::Twine& subsystem,
void SendableRegistry::AddLW(Sendable* sendable, const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.liveWindow = true;
comp.name = name.str();
}
@@ -94,6 +110,7 @@ void SendableRegistry::AddLW(Sendable* sendable, const wpi::Twine& moduleType,
int channel) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.liveWindow = true;
comp.SetName(moduleType, channel);
}
@@ -102,6 +119,7 @@ void SendableRegistry::AddLW(Sendable* sendable, const wpi::Twine& moduleType,
int moduleNumber, int channel) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.liveWindow = true;
comp.SetName(moduleType, moduleNumber, channel);
}
@@ -110,6 +128,7 @@ void SendableRegistry::AddLW(Sendable* sendable, const wpi::Twine& subsystem,
const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->GetOrAdd(sendable);
comp.sendable = sendable;
comp.liveWindow = true;
comp.name = name.str();
comp.subsystem = subsystem.str();
@@ -117,82 +136,95 @@ void SendableRegistry::AddLW(Sendable* sendable, const wpi::Twine& subsystem,
void SendableRegistry::AddChild(Sendable* parent, void* child) {
std::scoped_lock lock(m_impl->mutex);
auto& comp = m_impl->components[child];
auto& comp = m_impl->GetOrAdd(child);
comp.parent = parent;
}
bool SendableRegistry::Remove(Sendable* sendable) {
std::scoped_lock lock(m_impl->mutex);
return m_impl->components.erase(sendable);
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return false;
UID compUid = it->getSecond();
m_impl->components.erase(compUid - 1);
m_impl->componentMap.erase(it);
return true;
}
void SendableRegistry::Move(Sendable* to, Sendable* from) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(from);
if (it == m_impl->components.end()) return;
Impl::Component old = std::move(it->getSecond());
m_impl->components.erase(it);
m_impl->components[to] = std::move(old);
m_impl->components[to].sendable = to;
auto it = m_impl->componentMap.find(from);
if (it == m_impl->componentMap.end()) return;
UID compUid = it->getSecond();
m_impl->componentMap.erase(it);
m_impl->componentMap[to] = compUid;
auto& comp = *m_impl->components[compUid - 1];
comp.sendable = to;
if (comp.builder.HasTable()) {
// rebuild builder, as lambda captures can point to "from"
comp.builder.ClearProperties();
to->InitSendable(comp.builder);
}
}
bool SendableRegistry::Contains(const Sendable* sendable) const {
std::scoped_lock lock(m_impl->mutex);
return m_impl->components.count(sendable) != 0;
return m_impl->componentMap.count(sendable) != 0;
}
std::string SendableRegistry::GetName(const Sendable* sendable) const {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return std::string{};
return it->getSecond().name;
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return std::string{};
return m_impl->components[it->getSecond() - 1]->name;
}
void SendableRegistry::SetName(Sendable* sendable, const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().name = name.str();
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->name = name.str();
}
void SendableRegistry::SetName(Sendable* sendable, const wpi::Twine& moduleType,
int channel) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().SetName(moduleType, channel);
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->SetName(moduleType, channel);
}
void SendableRegistry::SetName(Sendable* sendable, const wpi::Twine& moduleType,
int moduleNumber, int channel) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().SetName(moduleType, moduleNumber, channel);
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->SetName(moduleType, moduleNumber,
channel);
}
void SendableRegistry::SetName(Sendable* sendable, const wpi::Twine& subsystem,
const wpi::Twine& name) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().name = name.str();
it->getSecond().subsystem = subsystem.str();
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
auto& comp = *m_impl->components[it->getSecond() - 1];
comp.name = name.str();
comp.subsystem = subsystem.str();
}
std::string SendableRegistry::GetSubsystem(const Sendable* sendable) const {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return std::string{};
return it->getSecond().subsystem;
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return std::string{};
return m_impl->components[it->getSecond() - 1]->subsystem;
}
void SendableRegistry::SetSubsystem(Sendable* sendable,
const wpi::Twine& subsystem) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().subsystem = subsystem.str();
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->subsystem = subsystem.str();
}
int SendableRegistry::GetDataHandle() {
@@ -204,9 +236,9 @@ std::shared_ptr<void> SendableRegistry::SetData(Sendable* sendable, int handle,
std::shared_ptr<void> data) {
assert(handle >= 0);
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return nullptr;
auto& comp = it->getSecond();
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return nullptr;
auto& comp = *m_impl->components[it->getSecond() - 1];
std::shared_ptr<void> rv;
if (static_cast<size_t>(handle) < comp.data.size())
rv = std::move(comp.data[handle]);
@@ -220,42 +252,72 @@ std::shared_ptr<void> SendableRegistry::GetData(Sendable* sendable,
int handle) {
assert(handle >= 0);
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return nullptr;
auto& comp = it->getSecond();
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return nullptr;
auto& comp = *m_impl->components[it->getSecond() - 1];
if (static_cast<size_t>(handle) >= comp.data.size()) return nullptr;
return comp.data[handle];
}
void SendableRegistry::EnableLiveWindow(Sendable* sendable) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().liveWindow = true;
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->liveWindow = true;
}
void SendableRegistry::DisableLiveWindow(Sendable* sendable) {
std::scoped_lock lock(m_impl->mutex);
auto it = m_impl->components.find(sendable);
if (it == m_impl->components.end()) return;
it->getSecond().liveWindow = false;
auto it = m_impl->componentMap.find(sendable);
if (it == m_impl->componentMap.end()) return;
m_impl->components[it->getSecond() - 1]->liveWindow = false;
}
SendableRegistry::UID SendableRegistry::GetUniqueId(Sendable* sendable) {
std::scoped_lock lock(m_impl->mutex);
UID uid;
auto& comp = m_impl->GetOrAdd(sendable, &uid);
comp.sendable = sendable;
return uid;
}
Sendable* SendableRegistry::GetSendable(UID uid) {
if (uid == 0) return nullptr;
std::scoped_lock lock(m_impl->mutex);
return m_impl->components[uid - 1]->sendable;
}
void SendableRegistry::Publish(UID sendableUid,
std::shared_ptr<NetworkTable> table) {
std::scoped_lock lock(m_impl->mutex);
if (sendableUid == 0) return;
auto& comp = *m_impl->components[sendableUid - 1];
comp.builder = SendableBuilderImpl{}; // clear any current builder
comp.builder.SetTable(table);
comp.sendable->InitSendable(comp.builder);
comp.builder.UpdateTable();
comp.builder.StartListeners();
}
void SendableRegistry::Update(UID sendableUid) {
if (sendableUid == 0) return;
std::scoped_lock lock(m_impl->mutex);
m_impl->components[sendableUid - 1]->builder.UpdateTable();
}
void SendableRegistry::ForeachLiveWindow(
int dataHandle,
wpi::function_ref<void(Sendable* sendable, wpi::StringRef name,
wpi::StringRef subsystem, Sendable* parent,
std::shared_ptr<void>& data)>
callback) const {
wpi::function_ref<void(CallbackData& data)> callback) const {
assert(dataHandle >= 0);
std::scoped_lock lock(m_impl->mutex);
for (auto& i : m_impl->components) {
auto& comp = i.getSecond();
if (comp.sendable && comp.liveWindow) {
if (static_cast<size_t>(dataHandle) >= comp.data.size())
comp.data.resize(dataHandle + 1);
callback(comp.sendable, comp.name, comp.subsystem, comp.parent,
comp.data[dataHandle]);
for (auto&& comp : m_impl->components) {
if (comp->sendable && comp->liveWindow) {
if (static_cast<size_t>(dataHandle) >= comp->data.size())
comp->data.resize(dataHandle + 1);
CallbackData cbdata{comp->sendable, comp->name,
comp->subsystem, comp->parent,
comp->data[dataHandle], comp->builder};
callback(cbdata);
}
}
}

View File

@@ -14,27 +14,17 @@
#include <wpi/mutex.h>
#include "frc/WPIErrors.h"
#include "frc/smartdashboard/SendableBuilderImpl.h"
#include "frc/smartdashboard/SendableRegistry.h"
using namespace frc;
namespace {
class SmartDashboardData {
public:
SmartDashboardData() = default;
explicit SmartDashboardData(Sendable* sendable_) : sendable(sendable_) {}
Sendable* sendable = nullptr;
SendableBuilderImpl builder;
};
class Singleton {
public:
static Singleton& GetInstance();
std::shared_ptr<nt::NetworkTable> table;
wpi::StringMap<SmartDashboardData> tablesToData;
wpi::StringMap<SendableRegistry::UID> tablesToData;
wpi::mutex tablesToDataMutex;
private:
@@ -98,14 +88,13 @@ void SmartDashboard::PutData(wpi::StringRef key, Sendable* data) {
}
auto& inst = Singleton::GetInstance();
std::scoped_lock lock(inst.tablesToDataMutex);
auto& sddata = inst.tablesToData[key];
if (!sddata.sendable || sddata.sendable != data) {
sddata = SmartDashboardData(data);
auto& uid = inst.tablesToData[key];
auto& registry = SendableRegistry::GetInstance();
Sendable* sddata = registry.GetSendable(uid);
if (sddata != data) {
uid = registry.GetUniqueId(data);
auto dataTable = inst.table->GetSubTable(key);
sddata.builder.SetTable(dataTable);
data->InitSendable(sddata.builder);
sddata.builder.UpdateTable();
sddata.builder.StartListeners();
registry.Publish(uid, dataTable);
dataTable->GetEntry(".name").SetString(key);
}
}
@@ -122,12 +111,12 @@ void SmartDashboard::PutData(Sendable* value) {
Sendable* SmartDashboard::GetData(wpi::StringRef key) {
auto& inst = Singleton::GetInstance();
std::scoped_lock lock(inst.tablesToDataMutex);
auto data = inst.tablesToData.find(key);
if (data == inst.tablesToData.end()) {
auto it = inst.tablesToData.find(key);
if (it == inst.tablesToData.end()) {
wpi_setGlobalWPIErrorWithContext(SmartDashboardMissingKey, key);
return nullptr;
}
return data->getValue().sendable;
return SendableRegistry::GetInstance().GetSendable(it->getValue());
}
bool SmartDashboard::PutBoolean(wpi::StringRef keyName, bool value) {
@@ -262,10 +251,9 @@ void SmartDashboard::PostListenerTask(std::function<void()> task) {
}
void SmartDashboard::UpdateValues() {
auto& registry = SendableRegistry::GetInstance();
auto& inst = Singleton::GetInstance();
std::scoped_lock lock(inst.tablesToDataMutex);
for (auto& i : inst.tablesToData) {
i.getValue().builder.UpdateTable();
}
for (auto& i : inst.tablesToData) registry.Update(i.getValue());
listenerExecutor.RunListenerTasks();
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2017-2019 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. */
@@ -45,6 +45,12 @@ class SendableBuilderImpl : public SendableBuilder {
*/
std::shared_ptr<nt::NetworkTable> GetTable();
/**
* Return whether this sendable has an associated table.
* @return True if it has a table, false if not.
*/
bool HasTable() const;
/**
* Return whether this sendable should be treated as an actuator.
* @return True if actuator, false if not.
@@ -78,6 +84,11 @@ class SendableBuilderImpl : public SendableBuilder {
*/
void StopLiveWindowMode();
/**
* Clear properties.
*/
void ClearProperties();
void SetSmartDashboardType(const wpi::Twine& type) override;
void SetActuator(bool value) override;
void SetSafeState(std::function<void()> func) override;

View File

@@ -10,12 +10,14 @@
#include <memory>
#include <string>
#include <networktables/NetworkTable.h>
#include <wpi/STLExtras.h>
#include <wpi/Twine.h>
namespace frc {
class Sendable;
class SendableBuilderImpl;
/**
* The SendableRegistry class is the public interface for registering sensors
@@ -26,6 +28,8 @@ class SendableRegistry {
SendableRegistry(const SendableRegistry&) = delete;
SendableRegistry& operator=(const SendableRegistry&) = delete;
using UID = size_t;
/**
* Gets an instance of the SendableRegistry class.
*
@@ -252,6 +256,60 @@ class SendableRegistry {
*/
void DisableLiveWindow(Sendable* sendable);
/**
* Get unique id for an object. Since objects can move, use this instead
* of storing Sendable* directly if ownership is in question.
*
* @param sendable object
* @return unique id
*/
UID GetUniqueId(Sendable* sendable);
/**
* Get sendable object for a given unique id.
*
* @param uid unique id
* @return sendable object (may be null)
*/
Sendable* GetSendable(UID uid);
/**
* Publishes an object in the registry to a network table.
*
* @param sendableUid sendable unique id
* @param table network table
*/
void Publish(UID sendableUid, std::shared_ptr<NetworkTable> table);
/**
* Updates network table information from an object.
*
* @param sendableUid sendable unique id
*/
void Update(UID sendableUid);
/**
* Data passed to ForeachLiveWindow() callback function
*/
struct CallbackData {
CallbackData(Sendable* sendable_, wpi::StringRef name_,
wpi::StringRef subsystem_, Sendable* parent_,
std::shared_ptr<void>& data_, SendableBuilderImpl& builder_)
: sendable(sendable_),
name(name_),
subsystem(subsystem_),
parent(parent_),
data(data_),
builder(builder_) {}
Sendable* sendable;
wpi::StringRef name;
wpi::StringRef subsystem;
Sendable* parent;
std::shared_ptr<void>& data;
SendableBuilderImpl& builder;
};
/**
* Iterates over LiveWindow-enabled objects in the registry.
* It is *not* safe to call other SendableRegistry functions from the
@@ -262,10 +320,7 @@ class SendableRegistry {
*/
void ForeachLiveWindow(
int dataHandle,
wpi::function_ref<void(Sendable* sendable, wpi::StringRef name,
wpi::StringRef subsystem, Sendable* parent,
std::shared_ptr<void>& data)>
callback) const;
wpi::function_ref<void(CallbackData& cbdata)> callback) const;
private:
SendableRegistry();