Skip to content

Commit

Permalink
uv::Async, uv::AsyncFunction: allow calling from within loop
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterJohnson committed Oct 16, 2018
1 parent 172e438 commit 7c1a733
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
12 changes: 10 additions & 2 deletions wpiutil/src/main/native/include/wpi/uv/Async.h
Expand Up @@ -11,6 +11,7 @@
#include <uv.h>

#include <memory>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -83,16 +84,23 @@ class Async final : public HandleImpl<Async<T...>, 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 <typename... U>
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>(u)...);
return;
}

{
std::lock_guard<wpi::mutex> lock(m_mutex);
m_data.emplace_back(std::forward_as_tuple(std::forward<U>(u)...));
}
if (auto loop = m_loop.lock()) this->Invoke(&uv_async_send, this->GetRaw());
if (loop) this->Invoke(&uv_async_send, this->GetRaw());
}

/**
Expand Down
12 changes: 10 additions & 2 deletions wpiutil/src/main/native/include/wpi/uv/AsyncFunction.h
Expand Up @@ -13,6 +13,7 @@

#include <functional>
#include <memory>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -112,7 +113,7 @@ class AsyncFunction<R(T...)> 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
Expand All @@ -123,6 +124,13 @@ class AsyncFunction<R(T...)> 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>(u)...);
return m_promises.CreateFuture(req);
}

// add the parameters to the input queue
{
std::lock_guard<wpi::mutex> lock(m_mutex);
Expand All @@ -132,7 +140,7 @@ class AsyncFunction<R(T...)> 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);
Expand Down

0 comments on commit 7c1a733

Please sign in to comment.