WPILibC++  2019.4.1-3-g655763a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
Async.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2018 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/STLExtras.h"
20 #include "wpi/Signal.h"
21 #include "wpi/mutex.h"
22 #include "wpi/uv/Handle.h"
23 #include "wpi/uv/Loop.h"
24 
25 namespace wpi {
26 namespace uv {
27 
39 template <typename... T>
40 class Async final : public HandleImpl<Async<T...>, uv_async_t> {
41  struct private_init {};
42 
43  public:
44  Async(const std::shared_ptr<Loop>& loop, const private_init&)
45  : m_loop{loop} {}
46  ~Async() noexcept override {
47  if (auto loop = m_loop.lock())
48  this->Close();
49  else
50  this->ForceClosed();
51  }
52 
58  static std::shared_ptr<Async> Create(Loop& loop) {
59  return Create(loop.shared_from_this());
60  }
61 
67  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop) {
68  auto h = std::make_shared<Async>(loop, private_init{});
69  int err =
70  uv_async_init(loop->GetRaw(), h->GetRaw(), [](uv_async_t* handle) {
71  auto& h = *static_cast<Async*>(handle->data);
72  std::lock_guard<wpi::mutex> lock(h.m_mutex);
73  for (auto&& v : h.m_data) apply_tuple(h.wakeup, v);
74  h.m_data.clear();
75  });
76  if (err < 0) {
77  loop->ReportError(err);
78  return nullptr;
79  }
80  h->Keep();
81  return h;
82  }
83 
90  template <typename... U>
91  void Send(U&&... u) {
92  auto loop = m_loop.lock();
93  if (loop && loop->GetThreadId() == std::this_thread::get_id()) {
94  // called from within the loop, just call the function directly
95  wakeup(std::forward<U>(u)...);
96  return;
97  }
98 
99  {
100  std::lock_guard<wpi::mutex> lock(m_mutex);
101  m_data.emplace_back(std::forward_as_tuple(std::forward<U>(u)...));
102  }
103  if (loop) this->Invoke(&uv_async_send, this->GetRaw());
104  }
105 
110 
111  private:
112  wpi::mutex m_mutex;
113  std::vector<std::tuple<T...>> m_data;
114  std::weak_ptr<Loop> m_loop;
115 };
116 
121 template <>
122 class Async<> final : public HandleImpl<Async<>, uv_async_t> {
123  struct private_init {};
124 
125  public:
126  Async(const std::shared_ptr<Loop>& loop, const private_init&)
127  : m_loop(loop) {}
128  ~Async() noexcept override;
129 
135  static std::shared_ptr<Async> Create(Loop& loop) {
136  return Create(loop.shared_from_this());
137  }
138 
144  static std::shared_ptr<Async> Create(const std::shared_ptr<Loop>& loop);
145 
152  void Send() {
153  if (auto loop = m_loop.lock()) Invoke(&uv_async_send, GetRaw());
154  }
155 
160 
161  private:
162  std::weak_ptr<Loop> m_loop;
163 };
164 
165 } // namespace uv
166 } // namespace wpi
167 
168 #endif // WPIUTIL_WPI_UV_ASYNC_H_
static std::shared_ptr< Async > Create(Loop &loop)
Create an async handle.
Definition: Async.h:135
uv_async_t * GetRaw() const noexcept
Get the underlying handle data structure.
Definition: Handle.h:264
sig::Signal wakeup
Signal generated (on event loop thread) when the async event occurs.
Definition: Async.h:159
Handle.
Definition: Handle.h:249
void Close() noexcept
Request handle to be closed.
WPILib C++ utilities (wpiutil) namespace.
Definition: SmallString.h:21
static std::shared_ptr< Async > Create(Loop &loop)
Create an async handle.
Definition: Async.h:58
void Send()
Wakeup the event loop and emit the event.
Definition: Async.h:152
auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(std::forward< F >(f), std::forward< Tuple >(t), build_index_impl< std::tuple_size< typename std::decay< Tuple >::type >::value >
Given an input tuple (a1, a2, ..., an), pass the arguments of the tuple variadically to f as if by ca...
Definition: STLExtras.h:1209
sig::Signal< T...> wakeup
Signal generated (on event loop thread) when the async event occurs.
Definition: Async.h:109
static std::shared_ptr< Async > Create(const std::shared_ptr< Loop > &loop)
Create an async handle.
Definition: Async.h:67
Definition: uv.h:768
Event loop.
Definition: Loop.h:39
void Send(U &&...u)
Wakeup the event loop and emit the event.
Definition: Async.h:91
Async handle.
Definition: Async.h:40
SignalBase is an implementation of the observer pattern, through the use of an emitting object and sl...
Definition: Signal.h:495