2018-07-17 01:06:24 -07:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
|
|
|
|
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
|
|
|
|
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
|
|
|
|
/* the project. */
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "wpi/EventLoopRunner.h"
|
|
|
|
|
|
|
|
|
|
#include "wpi/SmallVector.h"
|
|
|
|
|
#include "wpi/condition_variable.h"
|
|
|
|
|
#include "wpi/mutex.h"
|
2018-08-14 21:01:20 -07:00
|
|
|
#include "wpi/uv/AsyncFunction.h"
|
2018-07-17 01:06:24 -07:00
|
|
|
#include "wpi/uv/Loop.h"
|
|
|
|
|
|
|
|
|
|
using namespace wpi;
|
|
|
|
|
|
|
|
|
|
class EventLoopRunner::Thread : public SafeThread {
|
|
|
|
|
public:
|
2018-08-14 21:01:20 -07:00
|
|
|
using UvExecFunc = uv::AsyncFunction<void(LoopFunc)>;
|
|
|
|
|
|
2018-07-17 01:06:24 -07:00
|
|
|
Thread() : m_loop(uv::Loop::Create()) {
|
|
|
|
|
// set up async handles
|
|
|
|
|
if (!m_loop) return;
|
|
|
|
|
|
|
|
|
|
// run function
|
2018-08-14 21:01:20 -07:00
|
|
|
m_doExec = UvExecFunc::Create(
|
2018-09-05 23:01:57 -07:00
|
|
|
m_loop, [loop = m_loop.get()](auto out, LoopFunc func) {
|
|
|
|
|
func(*loop);
|
|
|
|
|
out.set_value();
|
|
|
|
|
});
|
2018-07-17 01:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Main() {
|
|
|
|
|
if (m_loop) m_loop->Run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// the loop
|
|
|
|
|
std::shared_ptr<uv::Loop> m_loop;
|
|
|
|
|
|
|
|
|
|
// run function
|
2018-08-14 21:01:20 -07:00
|
|
|
std::weak_ptr<UvExecFunc> m_doExec;
|
2018-07-17 01:06:24 -07:00
|
|
|
};
|
|
|
|
|
|
2018-10-05 16:32:43 -07:00
|
|
|
EventLoopRunner::EventLoopRunner() { m_owner.Start(); }
|
2018-07-17 01:06:24 -07:00
|
|
|
|
2018-11-06 23:27:46 -08:00
|
|
|
EventLoopRunner::~EventLoopRunner() { Stop(); }
|
|
|
|
|
|
|
|
|
|
void EventLoopRunner::Stop() {
|
2018-08-14 21:01:20 -07:00
|
|
|
ExecAsync([](uv::Loop& loop) {
|
|
|
|
|
// close all handles; this will (eventually) stop the loop
|
|
|
|
|
loop.Walk([](uv::Handle& h) { h.Close(); });
|
|
|
|
|
});
|
2018-11-06 23:27:46 -08:00
|
|
|
m_owner.Join();
|
2018-07-17 01:06:24 -07:00
|
|
|
}
|
|
|
|
|
|
2018-08-14 21:01:20 -07:00
|
|
|
void EventLoopRunner::ExecAsync(LoopFunc func) {
|
2018-07-17 01:06:24 -07:00
|
|
|
if (auto thr = m_owner.GetThread()) {
|
|
|
|
|
if (auto doExec = thr->m_doExec.lock()) {
|
2018-09-05 23:01:57 -07:00
|
|
|
doExec->Call(func);
|
2018-07-17 01:06:24 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 21:01:20 -07:00
|
|
|
void EventLoopRunner::ExecSync(LoopFunc func) {
|
2018-11-06 23:27:46 -08:00
|
|
|
wpi::future<void> f;
|
2018-07-17 01:06:24 -07:00
|
|
|
if (auto thr = m_owner.GetThread()) {
|
|
|
|
|
if (auto doExec = thr->m_doExec.lock()) {
|
2018-11-06 23:27:46 -08:00
|
|
|
f = doExec->Call(func);
|
2018-07-17 01:06:24 -07:00
|
|
|
}
|
|
|
|
|
}
|
2018-11-06 23:27:46 -08:00
|
|
|
if (f.valid()) f.wait();
|
2018-07-17 01:06:24 -07:00
|
|
|
}
|
2018-09-23 16:14:56 -07:00
|
|
|
|
|
|
|
|
std::shared_ptr<uv::Loop> EventLoopRunner::GetLoop() {
|
|
|
|
|
if (auto thr = m_owner.GetThread()) return thr->m_loop;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|