mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
EventLoopRunner: Use AsyncFunction
This commit is contained in:
@@ -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<void(LoopFunc)>;
|
||||
|
||||
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<wpi::mutex> 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<uv::Loop> m_loop;
|
||||
|
||||
// run function
|
||||
std::weak_ptr<uv::Async> m_doExec;
|
||||
wpi::SmallVector<std::function<void(uv::Loop&)>, 4> m_exec;
|
||||
wpi::condition_variable m_execDone;
|
||||
|
||||
// exit loop (thread cleanup)
|
||||
std::weak_ptr<uv::Async> m_doExit;
|
||||
std::weak_ptr<UvExecFunc> 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<void(uv::Loop&)> 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<void(uv::Loop&)> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user