[hal] SimDevice: Don't hold lock during callbacks (#6855)

This can cause lock inversions with other code (in particular with
the simulation WebSockets interface).
This commit is contained in:
Peter Johnson
2024-07-20 22:09:09 -07:00
committed by GitHub
parent b4d42d8980
commit 8548d83b03
2 changed files with 39 additions and 23 deletions

View File

@@ -58,12 +58,19 @@ class SimUnnamedCallbackRegistry {
1;
}
template <typename... U>
void Invoke(const char* name, U&&... u) const {
template <typename Mutex, typename... U>
void Invoke(std::unique_lock<Mutex>& lock, const char* name, U&&... u) const {
if (m_callbacks) {
for (auto&& cb : *m_callbacks) {
reinterpret_cast<CallbackFunction>(cb.callback)(name, cb.param,
std::forward<U>(u)...);
for (size_t i = 0; i < m_callbacks->size(); ++i) {
auto& cb = (*m_callbacks)[i];
if (cb.callback) {
auto callback = cb.callback;
auto param = cb.param;
lock.unlock();
reinterpret_cast<CallbackFunction>(callback)(name, param,
std::forward<U>(u)...);
lock.lock();
}
}
}
}
@@ -115,12 +122,17 @@ class SimPrefixCallbackRegistry {
return m_callbacks->emplace_back(prefix, param, callback) + 1;
}
template <typename... U>
void Invoke(const char* name, U&&... u) const {
template <typename Mutex, typename... U>
void Invoke(std::unique_lock<Mutex>& lock, const char* name, U&&... u) const {
if (m_callbacks) {
for (auto&& cb : *m_callbacks) {
if (wpi::starts_with(name, cb.prefix)) {
cb.callback(name, cb.param, std::forward<U>(u)...);
for (size_t i = 0; i < m_callbacks->size(); ++i) {
auto& cb = (*m_callbacks)[i];
if (cb.callback && wpi::starts_with(name, cb.prefix)) {
auto callback = cb.callback;
auto param = cb.param;
lock.unlock();
callback(name, param, std::forward<U>(u)...);
lock.lock();
}
}
}