mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-23 01:21:42 +00:00
Move immediate connection notification logic into Dispatcher.
This prevents a race condition that could result in out of order notifications.
This commit is contained in:
@@ -57,9 +57,9 @@ class ConnectionNotifier
|
||||
|
||||
void Start();
|
||||
|
||||
unsigned int Add(
|
||||
std::function<void(const ConnectionNotification& event)> callback);
|
||||
unsigned int AddPolled(unsigned int poller_uid);
|
||||
unsigned int Add(std::function<void(const ConnectionNotification& event)>
|
||||
callback) override;
|
||||
unsigned int AddPolled(unsigned int poller_uid) override;
|
||||
|
||||
void NotifyConnection(bool connected, const ConnectionInfo& conn_info,
|
||||
unsigned int only_listener = UINT_MAX) override;
|
||||
|
||||
@@ -239,6 +239,35 @@ bool DispatcherBase::IsConnected() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int DispatcherBase::AddListener(
|
||||
std::function<void(const ConnectionNotification& event)> callback,
|
||||
bool immediate_notify) const {
|
||||
std::lock_guard<std::mutex> lock(m_user_mutex);
|
||||
unsigned int uid = m_notifier.Add(callback);
|
||||
// perform immediate notifications
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() != NetworkConnection::kActive) continue;
|
||||
m_notifier.NotifyConnection(true, conn->info(), uid);
|
||||
}
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
unsigned int DispatcherBase::AddPolledListener(unsigned int poller_uid,
|
||||
bool immediate_notify) const {
|
||||
std::lock_guard<std::mutex> lock(m_user_mutex);
|
||||
unsigned int uid = m_notifier.AddPolled(poller_uid);
|
||||
// perform immediate notifications
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : m_connections) {
|
||||
if (conn->state() != NetworkConnection::kActive) continue;
|
||||
m_notifier.NotifyConnection(true, conn->info(), uid);
|
||||
}
|
||||
}
|
||||
return uid;
|
||||
}
|
||||
|
||||
void DispatcherBase::SetConnector(Connector connector) {
|
||||
std::lock_guard<std::mutex> lock(m_user_mutex);
|
||||
m_client_connector = std::move(connector);
|
||||
|
||||
@@ -56,6 +56,12 @@ class DispatcherBase : public IDispatcher {
|
||||
std::vector<ConnectionInfo> GetConnections() const;
|
||||
bool IsConnected() const;
|
||||
|
||||
unsigned int AddListener(
|
||||
std::function<void(const ConnectionNotification& event)> callback,
|
||||
bool immediate_notify) const;
|
||||
unsigned int AddPolledListener(unsigned int poller_uid,
|
||||
bool immediate_notify) const;
|
||||
|
||||
void SetConnector(Connector connector);
|
||||
void SetConnectorOverride(Connector connector);
|
||||
void ClearConnectorOverride();
|
||||
|
||||
@@ -20,6 +20,9 @@ class IConnectionNotifier {
|
||||
IConnectionNotifier(const IConnectionNotifier&) = delete;
|
||||
IConnectionNotifier& operator=(const IConnectionNotifier&) = delete;
|
||||
virtual ~IConnectionNotifier() = default;
|
||||
virtual unsigned int Add(
|
||||
std::function<void(const ConnectionNotification& event)> callback) = 0;
|
||||
virtual unsigned int AddPolled(unsigned int poller_uid) = 0;
|
||||
virtual void NotifyConnection(bool connected, const ConnectionInfo& conn_info,
|
||||
unsigned int only_listener = UINT_MAX) = 0;
|
||||
};
|
||||
|
||||
@@ -388,11 +388,7 @@ NT_ConnectionListener AddConnectionListener(
|
||||
auto ii = InstanceImpl::Get(i);
|
||||
if (!ii) return 0;
|
||||
|
||||
unsigned int uid = ii->connection_notifier.Add(callback);
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : ii->dispatcher.GetConnections())
|
||||
ii->connection_notifier.NotifyConnection(true, conn, uid);
|
||||
}
|
||||
unsigned int uid = ii->dispatcher.AddListener(callback, immediate_notify);
|
||||
return Handle(i, uid, Handle::kConnectionListener);
|
||||
}
|
||||
|
||||
@@ -422,12 +418,7 @@ NT_ConnectionListener AddPolledConnectionListener(
|
||||
auto ii = InstanceImpl::Get(i);
|
||||
if (id < 0 || !ii) return 0;
|
||||
|
||||
unsigned int uid = ii->connection_notifier.AddPolled(id);
|
||||
// perform immediate notifications
|
||||
if (immediate_notify) {
|
||||
for (auto& conn : ii->dispatcher.GetConnections())
|
||||
ii->connection_notifier.NotifyConnection(true, conn, uid);
|
||||
}
|
||||
unsigned int uid = ii->dispatcher.AddPolledListener(id, immediate_notify);
|
||||
return Handle(i, uid, Handle::kConnectionListener);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user