diff --git a/wpiutil/src/main/native/include/wpi/uv/Async.h b/wpiutil/src/main/native/include/wpi/uv/Async.h index 389052b566a..3ea3e5d1c9a 100644 --- a/wpiutil/src/main/native/include/wpi/uv/Async.h +++ b/wpiutil/src/main/native/include/wpi/uv/Async.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -83,16 +84,23 @@ class Async final : public HandleImpl, uv_async_t> { /** * Wakeup the event loop and emit the event. * - * It’s safe to call this function from any thread EXCEPT the loop thread. + * It’s safe to call this function from any thread including the loop thread. * An async event will be emitted on the loop thread. */ template void Send(U&&... u) { + auto loop = m_loop.lock(); + if (loop && loop->GetThreadId() == std::this_thread::get_id()) { + // called from within the loop, just call the function directly + wakeup(std::forward(u)...); + return; + } + { std::lock_guard lock(m_mutex); m_data.emplace_back(std::forward_as_tuple(std::forward(u)...)); } - if (auto loop = m_loop.lock()) this->Invoke(&uv_async_send, this->GetRaw()); + if (loop) this->Invoke(&uv_async_send, this->GetRaw()); } /** diff --git a/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h b/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h index c9e436cfca1..64308564d3d 100644 --- a/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h +++ b/wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -112,7 +113,7 @@ class AsyncFunction final * Wakeup the event loop, call the async function, and return a future for * the result. * - * It’s safe to call this function from any thread EXCEPT the loop thread. + * It’s safe to call this function from any thread including the loop thread. * The async function will be called on the loop thread. * * The future will return a default-constructed result if this handle is @@ -123,6 +124,13 @@ class AsyncFunction final // create the future uint64_t req = m_promises.CreateRequest(); + auto loop = m_loop.lock(); + if (loop && loop->GetThreadId() == std::this_thread::get_id()) { + // called from within the loop, just call the function directly + wakeup(m_promises.CreatePromise(req), std::forward(u)...); + return m_promises.CreateFuture(req); + } + // add the parameters to the input queue { std::lock_guard lock(m_mutex); @@ -132,7 +140,7 @@ class AsyncFunction final } // signal the loop - if (auto loop = m_loop.lock()) this->Invoke(&uv_async_send, this->GetRaw()); + if (loop) this->Invoke(&uv_async_send, this->GetRaw()); // return future return m_promises.CreateFuture(req);