diff --git a/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp b/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp index c495c7a662..23c22e90ab 100644 --- a/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp +++ b/glass/src/libnt/native/cpp/NetworkTablesSettings.cpp @@ -17,14 +17,78 @@ using namespace glass; +void NetworkTablesSettings::Thread::Main() { + while (m_active) { + // wait to be woken up + std::unique_lock lock(m_mutex); + m_cond.wait(lock, [&] { return !m_active || m_restart; }); + if (!m_active) { + break; + } + + // clear restart flag + m_restart = false; + + int mode; + bool dsClient; + + do { + mode = m_mode; + dsClient = m_dsClient; + + // release lock while stopping to avoid blocking GUI + lock.unlock(); + + // if just changing servers in client mode, no need to stop and restart + unsigned int curMode = nt::GetNetworkMode(m_inst); + if (mode != 1 || (curMode & NT_NET_MODE_SERVER) != 0) { + nt::StopClient(m_inst); + nt::StopServer(m_inst); + nt::StopLocal(m_inst); + } + + if (m_mode != 1 || !dsClient) { + nt::StopDSClient(m_inst); + } + + lock.lock(); + } while (mode != m_mode || dsClient != m_dsClient); + + if (m_mode == 1) { + wpi::StringRef serverTeam{m_serverTeam}; + unsigned int team; + if (!serverTeam.contains('.') && !serverTeam.getAsInteger(10, team)) { + nt::StartClientTeam(m_inst, team, NT_DEFAULT_PORT); + } else { + wpi::SmallVector serverNames; + wpi::SmallVector, 4> servers; + serverTeam.split(serverNames, ',', -1, false); + for (auto&& serverName : serverNames) { + servers.emplace_back(serverName, NT_DEFAULT_PORT); + } + nt::StartClient(m_inst, servers); + } + + if (m_dsClient) { + nt::StartDSClient(m_inst, NT_DEFAULT_PORT); + } + } else if (m_mode == 2) { + nt::StartServer(m_inst, m_iniName.c_str(), m_listenAddress.c_str(), + NT_DEFAULT_PORT); + } + } +} + NetworkTablesSettings::NetworkTablesSettings(NT_Inst inst, - const char* storageName) - : m_inst{inst} { + const char* storageName) { auto& storage = glass::GetStorage(storageName); m_pMode = storage.GetIntRef("mode"); m_pIniName = storage.GetStringRef("iniName", "networktables.ini"); m_pServerTeam = storage.GetStringRef("serverTeam"); m_pListenAddress = storage.GetStringRef("listenAddress"); + m_pDsClient = storage.GetBoolRef("dsClient", true); + + m_thread.Start(inst); } void NetworkTablesSettings::Update() { @@ -32,27 +96,16 @@ void NetworkTablesSettings::Update() { return; } m_restart = false; - nt::StopClient(m_inst); - nt::StopServer(m_inst); - nt::StopLocal(m_inst); - if (*m_pMode == 1) { - wpi::StringRef serverTeam{*m_pServerTeam}; - unsigned int team; - if (!serverTeam.contains('.') && !serverTeam.getAsInteger(10, team)) { - nt::StartClientTeam(m_inst, team, NT_DEFAULT_PORT); - } else { - wpi::SmallVector serverNames; - wpi::SmallVector, 4> servers; - serverTeam.split(serverNames, ',', -1, false); - for (auto&& serverName : serverNames) { - servers.emplace_back(serverName, NT_DEFAULT_PORT); - } - nt::StartClient(m_inst, servers); - } - } else if (*m_pMode == 2) { - nt::StartServer(m_inst, m_pIniName->c_str(), m_pListenAddress->c_str(), - NT_DEFAULT_PORT); - } + + // do actual operation on thread + auto thr = m_thread.GetThread(); + thr->m_restart = true; + thr->m_mode = *m_pMode; + thr->m_iniName = *m_pIniName; + thr->m_serverTeam = *m_pServerTeam; + thr->m_listenAddress = *m_pListenAddress; + thr->m_dsClient = *m_pDsClient; + thr->m_cond.notify_one(); } bool NetworkTablesSettings::Display() { @@ -61,6 +114,7 @@ bool NetworkTablesSettings::Display() { switch (*m_pMode) { case 1: ImGui::InputText("Team/IP", m_pServerTeam); + ImGui::Checkbox("Get Address from DS", m_pDsClient); break; case 2: ImGui::InputText("Listen Address", m_pListenAddress); diff --git a/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h b/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h index 09cbf063bc..4736e6f4d0 100644 --- a/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h +++ b/glass/src/libnt/native/include/glass/networktables/NetworkTablesSettings.h @@ -7,6 +7,7 @@ #include #include +#include namespace wpi { template @@ -25,12 +26,28 @@ class NetworkTablesSettings { bool Display(); private: - NT_Inst m_inst; bool m_restart = true; int* m_pMode; std::string* m_pIniName; std::string* m_pServerTeam; std::string* m_pListenAddress; + bool* m_pDsClient; + + class Thread : public wpi::SafeThread { + public: + explicit Thread(NT_Inst inst) : m_inst{inst} {} + + void Main() override; + + NT_Inst m_inst; + bool m_restart = false; + int m_mode; + std::string m_iniName; + std::string m_serverTeam; + std::string m_listenAddress; + bool m_dsClient; + }; + wpi::SafeThreadOwner m_thread; }; } // namespace glass