From dbb0b72cc582390de717f6526d134058aeeff920 Mon Sep 17 00:00:00 2001 From: iwubcode Date: Wed, 3 Mar 2021 17:57:18 -0600 Subject: [PATCH] InputCommon: instead of blocking on individual DSU server sockets, block on a selector built up from all server sockets --- .../DualShockUDPClient/DualShockUDPClient.cpp | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp index d5468e4e7b..99767dee4c 100644 --- a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp +++ b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp @@ -202,18 +202,6 @@ static bool IsSameController(const Proto::MessageType::PortInfo& a, std::tie(b.pad_id, b.pad_state, b.model, b.connection_type, b.pad_mac_address); } -static sf::Socket::Status ReceiveWithTimeout(sf::UdpSocket& socket, void* data, std::size_t size, - std::size_t& received, sf::IpAddress& remoteAddress, - unsigned short& remotePort, sf::Time timeout) -{ - sf::SocketSelector selector; - selector.add(socket); - if (selector.wait(timeout)) - return socket.receive(data, size, received, remoteAddress, remotePort); - else - return sf::Socket::NotReady; -} - static void HotplugThreadFunc() { Common::SetCurrentThreadName("DualShockUDPClient Hotplug Thread"); @@ -242,32 +230,50 @@ static void HotplugThreadFunc() } } + sf::SocketSelector selector; for (auto& server : s_servers) { - // Receive controller port info - using namespace std::chrono; - using namespace std::chrono_literals; + selector.add(server.m_socket); + } + + using namespace std::chrono; + using namespace std::chrono_literals; + const auto timeout = s_next_listports - SteadyClock::now(); + + // Selector's wait treats a timeout of zero as infinite timeout, which we don't want + const auto timeout_ms = std::max(duration_cast(timeout), 1ms); + if (!selector.wait(sf::milliseconds(timeout_ms.count()))) + { + continue; + } + + for (auto& server : s_servers) + { + if (!selector.isReady(server.m_socket)) + { + continue; + } + Proto::Message msg; - const auto timeout = s_next_listports - SteadyClock::now(); - // ReceiveWithTimeout treats a timeout of zero as infinite timeout, which we don't want - const auto timeout_ms = std::max(duration_cast(timeout), 1ms); std::size_t received_bytes; sf::IpAddress sender; u16 port; - if (ReceiveWithTimeout(server.m_socket, &msg, sizeof(msg), received_bytes, sender, port, - sf::milliseconds(timeout_ms.count())) == sf::Socket::Status::Done) + if (server.m_socket.receive(&msg, sizeof(msg), received_bytes, sender, port) != + sf::Socket::Status::Done) { - if (auto port_info = msg.CheckAndCastTo()) + continue; + } + + if (auto port_info = msg.CheckAndCastTo()) + { + const bool port_changed = + !IsSameController(*port_info, server.m_port_info[port_info->pad_id]); { - const bool port_changed = - !IsSameController(*port_info, server.m_port_info[port_info->pad_id]); - { - std::lock_guard lock{server.m_port_info_mutex}; - server.m_port_info[port_info->pad_id] = *port_info; - } - if (port_changed) - PopulateDevices(); + std::lock_guard lock{server.m_port_info_mutex}; + server.m_port_info[port_info->pad_id] = *port_info; } + if (port_changed) + PopulateDevices(); } } }