blob: 7c7e79c116abf32e3db49b39c1746511accd90e2 [file] [log] [blame]
James Kuszmaulcf324122023-01-14 14:07:17 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "wpinet/EventLoopRunner.h"
6
7#include <wpi/SmallVector.h>
8#include <wpi/condition_variable.h>
9#include <wpi/mutex.h>
10
11#include "wpinet/uv/AsyncFunction.h"
12#include "wpinet/uv/Loop.h"
13
14using namespace wpi;
15
16class EventLoopRunner::Thread : public SafeThread {
17 public:
18 using UvExecFunc = uv::AsyncFunction<void(LoopFunc)>;
19
20 Thread() : m_loop(uv::Loop::Create()) {
21 // set up async handles
22 if (!m_loop) {
23 return;
24 }
25
26 // run function
27 m_doExec = UvExecFunc::Create(
28 m_loop, [loop = m_loop.get()](auto out, LoopFunc func) {
29 func(*loop);
30 out.set_value();
31 });
32 }
33
34 void Main() override {
35 if (m_loop) {
36 m_loop->Run();
37 }
38 }
39
40 // the loop
41 std::shared_ptr<uv::Loop> m_loop;
42
43 // run function
44 std::weak_ptr<UvExecFunc> m_doExec;
45};
46
47EventLoopRunner::EventLoopRunner() {
48 m_owner.Start();
49}
50
51EventLoopRunner::~EventLoopRunner() {
52 Stop();
53}
54
55void EventLoopRunner::Stop() {
56 ExecAsync([](uv::Loop& loop) {
57 // close all handles; this will (eventually) stop the loop
58 loop.Walk([](uv::Handle& h) {
59 h.SetLoopClosing(true);
60 h.Close();
61 });
62 });
63 m_owner.Join();
64}
65
66void EventLoopRunner::ExecAsync(LoopFunc func) {
67 if (auto thr = m_owner.GetThread()) {
68 if (auto doExec = thr->m_doExec.lock()) {
69 doExec->Call(std::move(func));
70 }
71 }
72}
73
74void EventLoopRunner::ExecSync(LoopFunc func) {
75 wpi::future<void> f;
76 if (auto thr = m_owner.GetThread()) {
77 if (auto doExec = thr->m_doExec.lock()) {
78 f = doExec->Call(std::move(func));
79 }
80 }
81 if (f.valid()) {
82 f.wait();
83 }
84}
85
86std::shared_ptr<uv::Loop> EventLoopRunner::GetLoop() {
87 if (auto thr = m_owner.GetThread()) {
88 return thr->m_loop;
89 }
90 return nullptr;
91}