8 #ifndef WPIUTIL_WPI_UV_ASYNCFUNCTION_H_
9 #define WPIUTIL_WPI_UV_ASYNCFUNCTION_H_
21 #include "wpi/future.h"
22 #include "wpi/mutex.h"
23 #include "wpi/uv/Handle.h"
24 #include "wpi/uv/Loop.h"
37 template <
typename R,
typename... T>
39 :
public HandleImpl<AsyncFunction<R(T...)>, uv_async_t> {
40 struct private_init {};
44 std::function<
void(
promise<R>, T...)> func,
const private_init&)
45 : wakeup{func}, m_loop{loop} {}
47 if (
auto loop = m_loop.lock())
62 static std::shared_ptr<AsyncFunction>
Create(
63 Loop& loop, std::function<
void(
promise<R>, T...)> func =
nullptr) {
64 return Create(loop.shared_from_this(), std::move(func));
76 static std::shared_ptr<AsyncFunction>
Create(
77 const std::shared_ptr<Loop>& loop,
78 std::function<
void(
promise<R>, T...)> func =
nullptr) {
80 std::make_shared<AsyncFunction>(loop, std::move(func), private_init{});
82 uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
83 auto& h = *static_cast<AsyncFunction*>(handle->data);
84 std::unique_lock lock(h.m_mutex);
86 if (!h.m_params.empty()) {
90 for (
auto&& v : h.m_params) {
91 auto p = h.m_promises.CreatePromise(v.first);
94 std::tuple_cat(std::make_tuple(std::move(p)),
95 std::move(v.second)));
100 h.m_promises.Notify();
104 loop->ReportError(err);
121 template <
typename... U>
124 uint64_t req = m_promises.CreateRequest();
126 auto loop = m_loop.lock();
127 if (loop && loop->GetThreadId() == std::this_thread::get_id()) {
129 wakeup(m_promises.CreatePromise(req), std::forward<U>(u)...);
130 return m_promises.CreateFuture(req);
135 std::scoped_lock lock(m_mutex);
136 m_params.emplace_back(std::piecewise_construct,
137 std::forward_as_tuple(req),
138 std::forward_as_tuple(std::forward<U>(u)...));
142 if (loop) this->Invoke(&uv_async_send, this->GetRaw());
145 return m_promises.CreateFuture(req);
148 template <
typename... U>
150 return Call(std::forward<U>(u)...);
160 std::vector<std::pair<uint64_t, std::tuple<T...>>> m_params;
162 std::weak_ptr<Loop> m_loop;
168 #endif // WPIUTIL_WPI_UV_ASYNCFUNCTION_H_