WPILibC++  2020.3.2
Async.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #ifndef WPIUTIL_WPI_UV_ASYNC_H_
9 #define WPIUTIL_WPI_UV_ASYNC_H_
10 
11 #include <uv.h>
12 
13 #include <memory>
14 #include <thread>
15 #include <tuple>
16 #include <utility>
17 #include <vector>
18 
19 #include "wpi/Signal.h"
20 #include "wpi/mutex.h"
21 #include "wpi/uv/Handle.h"
22 #include "wpi/uv/Loop.h"
23 
24 namespace wpi {
25 namespace uv {
26 
38 template <typename... T>
39 class Async final : public HandleImpl<Async<T...>, uv_async_t> {
40  struct private_init {};
41 
42  public:
43  Async(const std::shared_ptr<Loop>& loop, const private_init&)
44  : m_loop{loop} {}
45  ~Async() noexcept override {
46  if (auto loop = m_loop.lock())
47  this->Close();
48  else
49  this->ForceClosed();
50  }
51 
57  static std::shared_ptr<Async> Create(Loop& loop) {
58  return Create(loop.shared_from_this());
59  }
60 
66  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop) {
67  auto h = std::make_shared<Async>(loop, private_init{});
68  int err =
69  uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
70  auto& h = *static_cast<Async*>(handle->data);
71  std::scoped_lock lock(h.m_mutex);
72  for (auto&& v : h.m_data) std::apply(h.wakeup, v);
73  h.m_data.clear();
74  });
75  if (err < 0) {
76  loop->ReportError(err);
77  return nullptr;
78  }
79  h->Keep();
80  return h;
81  }
82 
89  template <typename... U>
90  void Send(U&&... u) {
91  auto loop = m_loop.lock();
92  if (loop && loop->GetThreadId() == std::this_thread::get_id()) {
93  // called from within the loop, just call the function directly
94  wakeup(std::forward<U>(u)...);
95  return;
96  }
97 
98  {
99  std::scoped_lock lock(m_mutex);
100  m_data.emplace_back(std::forward_as_tuple(std::forward<U>(u)...));
101  }
102  if (loop) this->Invoke(&uv_async_send, this->GetRaw());
103  }
104 
109 
110  private:
111  wpi::mutex m_mutex;
112  std::vector<std::tuple<T...>> m_data;
113  std::weak_ptr<Loop> m_loop;
114 };
115 
120 template <>
121 class Async<> final : public HandleImpl<Async<>, uv_async_t> {
122  struct private_init {};
123 
124  public:
125  Async(const std::shared_ptr<Loop>& loop, const private_init&)
126  : m_loop(loop) {}
127  ~Async() noexcept override;
128 
134  static std::shared_ptr<Async> Create(Loop& loop) {
135  return Create(loop.shared_from_this());
136  }
137 
143  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop);
144 
151  void Send() {
152  if (auto loop = m_loop.lock()) Invoke(&uv_async_send, GetRaw());
153  }
154 
159 
160  private:
161  std::weak_ptr<Loop> m_loop;
162 };
163 
164 } // namespace uv
165 } // namespace wpi
166 
167 #endif // WPIUTIL_WPI_UV_ASYNC_H_
wpi::uv::HandleImpl< Async< T... >, uv_async_t >::GetRaw
uv_async_t * GetRaw() const noexcept
Get the underlying handle data structure.
Definition: Handle.h:288
wpi::uv::Async::Create
static std::shared_ptr< Async > Create(Loop &loop)
Create an async handle.
Definition: Async.h:57
wpi::uv::Async::Create
static std::shared_ptr< Async > Create(const std::shared_ptr< Loop > &loop)
Create an async handle.
Definition: Async.h:66
wpi::uv::Async::Send
void Send(U &&... u)
Wakeup the event loop and emit the event.
Definition: Async.h:90
wpi::uv::Async::wakeup
sig::Signal< T... > wakeup
Signal generated (on event loop thread) when the async event occurs.
Definition: Async.h:108
wpi::uv::Async<>::Create
static std::shared_ptr< Async > Create(Loop &loop)
Create an async handle.
Definition: Async.h:134
wpi
WPILib C++ utilities (wpiutil) namespace.
Definition: EventLoopRunner.h:17
wpi::uv::HandleImpl
Handle.
Definition: Handle.h:273
wpi::uv::Async<>::wakeup
sig::Signal wakeup
Signal generated (on event loop thread) when the async event occurs.
Definition: Async.h:158
wpi::uv::Handle::Close
void Close() noexcept
Request handle to be closed.
wpi::uv::Async<>::Send
void Send()
Wakeup the event loop and emit the event.
Definition: Async.h:151
wpi::uv::Loop
Event loop.
Definition: Loop.h:39
wpi::sig::SignalBase
SignalBase is an implementation of the observer pattern, through the use of an emitting object and sl...
Definition: Signal.h:495
wpi::uv::Async
Async handle.
Definition: Async.h:39