From 8d8f120cc3ea530284b65636a2b9727e09c691e7 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 14 Aug 2018 21:01:20 -0700 Subject: [PATCH] EventLoopRunner: Use AsyncFunction --- .../src/main/native/cpp/EventLoopRunner.cpp | 52 +++++-------------- .../main/native/include/wpi/EventLoopRunner.h | 6 ++- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/wpiutil/src/main/native/cpp/EventLoopRunner.cpp b/wpiutil/src/main/native/cpp/EventLoopRunner.cpp index 8c65d4a41b..2061e96681 100644 --- a/wpiutil/src/main/native/cpp/EventLoopRunner.cpp +++ b/wpiutil/src/main/native/cpp/EventLoopRunner.cpp @@ -10,39 +10,22 @@ #include "wpi/SmallVector.h" #include "wpi/condition_variable.h" #include "wpi/mutex.h" -#include "wpi/uv/Async.h" +#include "wpi/uv/AsyncFunction.h" #include "wpi/uv/Loop.h" using namespace wpi; class EventLoopRunner::Thread : public SafeThread { public: + using UvExecFunc = uv::AsyncFunction; + Thread() : m_loop(uv::Loop::Create()) { // set up async handles if (!m_loop) return; // run function - auto doExec = uv::Async::Create(m_loop); - if (!doExec) return; - m_doExec = doExec; - doExec->wakeup.connect([ async = doExec.get(), this ]() { - uv::Loop& loop = async->GetLoopRef(); - { - std::lock_guard lock{m_mutex}; - for (auto&& func : m_exec) func(loop); - m_exec.clear(); - } - m_execDone.notify_all(); - }); - - // exit loop - auto doExit = uv::Async::Create(m_loop); - if (!doExit) return; - m_doExit = doExit; - doExit->wakeup.connect([async = doExit.get()]() { - // close all handles; this will (eventually) stop the loop - async->GetLoopRef().Walk([](uv::Handle& h) { h.Close(); }); - }); + m_doExec = UvExecFunc::Create( + m_loop, [loop = m_loop.get()](LoopFunc func) { func(*loop); }); } void Main() { @@ -53,37 +36,30 @@ class EventLoopRunner::Thread : public SafeThread { std::shared_ptr m_loop; // run function - std::weak_ptr m_doExec; - wpi::SmallVector, 4> m_exec; - wpi::condition_variable m_execDone; - - // exit loop (thread cleanup) - std::weak_ptr m_doExit; + std::weak_ptr m_doExec; }; EventLoopRunner::EventLoopRunner() { m_owner.Start(new Thread); } EventLoopRunner::~EventLoopRunner() { - if (auto thr = m_owner.GetThread()) { - if (auto doExit = thr->m_doExit.lock()) doExit->Send(); - } + ExecAsync([](uv::Loop& loop) { + // close all handles; this will (eventually) stop the loop + loop.Walk([](uv::Handle& h) { h.Close(); }); + }); } -void EventLoopRunner::ExecAsync(std::function func) { +void EventLoopRunner::ExecAsync(LoopFunc func) { if (auto thr = m_owner.GetThread()) { if (auto doExec = thr->m_doExec.lock()) { - thr->m_exec.emplace_back(func); - doExec->Send(); + doExec->Send(func); } } } -void EventLoopRunner::ExecSync(std::function func) { +void EventLoopRunner::ExecSync(LoopFunc func) { if (auto thr = m_owner.GetThread()) { if (auto doExec = thr->m_doExec.lock()) { - thr->m_exec.emplace_back(func); - doExec->Send(); - thr->m_execDone.wait(thr.GetLock(), [&] { return thr->m_exec.empty(); }); + doExec->Call(func); } } } diff --git a/wpiutil/src/main/native/include/wpi/EventLoopRunner.h b/wpiutil/src/main/native/include/wpi/EventLoopRunner.h index 9255b91cb7..28114f64c4 100644 --- a/wpiutil/src/main/native/include/wpi/EventLoopRunner.h +++ b/wpiutil/src/main/native/include/wpi/EventLoopRunner.h @@ -20,6 +20,8 @@ namespace wpi { */ class EventLoopRunner { public: + using LoopFunc = std::function; + EventLoopRunner(); virtual ~EventLoopRunner(); @@ -29,7 +31,7 @@ class EventLoopRunner { * provided function (it will deadlock). * @param func function to execute on the loop */ - void ExecAsync(std::function func); + void ExecAsync(LoopFunc func); /** * Run a function synchronously (once) on the loop. @@ -38,7 +40,7 @@ class EventLoopRunner { * This does not return until the function finishes executing. * @param func function to execute on the loop */ - void ExecSync(std::function func); + void ExecSync(LoopFunc func); private: class Thread;