librf
event_v1.h
1 #pragma once
2 
3 namespace resumef
4 {
5  namespace detail
6  {
7  struct event_impl;
8  typedef _awaker<event_impl> event_awaker;
9  typedef std::shared_ptr<event_awaker> event_awaker_ptr;
10 
11  struct event_impl : public std::enable_shared_from_this<event_impl>
12  {
13  private:
14  //typedef spinlock lock_type;
15  typedef std::recursive_mutex lock_type;
16 
17  std::list<event_awaker_ptr> _awakes;
18  intptr_t _counter;
19  lock_type _lock;
20  public:
21  event_impl(intptr_t initial_counter_);
22 
23  void signal();
24  void reset();
25 
26  //如果已经触发了awaker,则返回true
27  bool wait_(const event_awaker_ptr& awaker);
28 
29  template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, event_awaker_ptr>::value>>
30  decltype(auto) wait(callee_t&& awaker, dummy_t* dummy_ = nullptr)
31  {
32  (void)dummy_;
33  return wait_(std::make_shared<event_awaker>(std::forward<callee_t>(awaker)));
34  }
35 
36  event_impl(const event_impl&) = delete;
37  event_impl(event_impl&&) = delete;
38  event_impl& operator = (const event_impl&) = delete;
39  event_impl& operator = (event_impl&&) = delete;
40  };
41  }
42 
43 namespace event_v1
44 {
45 
46  //提供一种在协程和非协程之间同步的手段。
47  //典型用法是在非协程的线程,或者异步代码里,调用signal()方法触发信号,
48  //协程代码里,调用co_await wait()等系列方法等待同步。
49  struct event_t
50  {
51  typedef std::shared_ptr<detail::event_impl> event_impl_ptr;
52  typedef std::weak_ptr<detail::event_impl> event_impl_wptr;
53  typedef std::chrono::system_clock clock_type;
54  private:
55  event_impl_ptr _event;
56  struct wait_all_ctx;
57  public:
58  event_t(intptr_t initial_counter_ = 0);
59 
60  void signal() const
61  {
62  _event->signal();
63  }
64  void reset() const
65  {
66  _event->reset();
67  }
68 
69 
70 
71  future_t<bool>
72  wait() const;
73  template<class _Rep, class _Period>
74  future_t<bool>
75  wait_for(const std::chrono::duration<_Rep, _Period>& dt) const
76  {
77  return wait_for_(std::chrono::duration_cast<clock_type::duration>(dt));
78  }
79  template<class _Clock, class _Duration>
80  future_t<bool>
81  wait_until(const std::chrono::time_point<_Clock, _Duration>& tp) const
82  {
83  return wait_until_(std::chrono::time_point_cast<clock_type::duration>(tp));
84  }
85 
86 
87 
88 
89 
90  template<class _Iter>
91  static future_t<intptr_t>
92  wait_any(_Iter begin_, _Iter end_)
93  {
94  return wait_any_(make_event_vector(begin_, end_));
95  }
96  template<class _Cont>
97  static future_t<intptr_t>
98  wait_any(const _Cont& cnt_)
99  {
100  return wait_any_(make_event_vector(std::begin(cnt_), std::end(cnt_)));
101  }
102 
103  template<class _Rep, class _Period, class _Iter>
104  static future_t<intptr_t>
105  wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_)
106  {
107  return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_));
108  }
109  template<class _Rep, class _Period, class _Cont>
110  static future_t<intptr_t>
111  wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, const _Cont& cnt_)
112  {
113  return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_)));
114  }
115 
116  template<class _Clock, class _Duration, class _Iter>
117  static future_t<intptr_t>
118  wait_any_until(const std::chrono::time_point<_Clock, _Duration>& tp, _Iter begin_, _Iter end_)
119  {
120  return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_));
121  }
122  template<class _Clock, class _Duration, class _Cont>
123  static future_t<intptr_t>
124  wait_any_until(const std::chrono::time_point<_Clock, _Duration>& tp, const _Cont& cnt_)
125  {
126  return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_)));
127  }
128 
129 
130 
131 
132 
133  template<class _Iter>
134  static future_t<bool>
135  wait_all(_Iter begin_, _Iter end_)
136  {
137  return wait_all_(make_event_vector(begin_, end_));
138  }
139  template<class _Cont>
140  static future_t<bool>
141  wait_all(const _Cont& cnt_)
142  {
143  return wait_all(std::begin(cnt_), std::end(cnt_));
144  }
145 
146  template<class _Rep, class _Period, class _Iter>
147  static future_t<bool>
148  wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_)
149  {
150  return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_));
151  }
152  template<class _Rep, class _Period, class _Cont>
153  static future_t<bool>
154  wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, const _Cont& cnt_)
155  {
156  return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_)));
157  }
158 
159  template<class _Clock, class _Duration, class _Iter>
160  static future_t<bool>
161  wait_all_until(const std::chrono::time_point<_Clock, _Duration>& tp, _Iter begin_, _Iter end_)
162  {
163  return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_));
164  }
165  template<class _Clock, class _Duration, class _Cont>
166  static future_t<bool>
167  wait_all_until(const std::chrono::time_point<_Clock, _Duration>& tp, const _Cont& cnt_)
168  {
169  return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_)));
170  }
171 
172 
173 
174  event_t(const event_t&) = default;
175  event_t(event_t&&) = default;
176  event_t& operator = (const event_t&) = default;
177  event_t& operator = (event_t&&) = default;
178 
179  private:
180  template<class _Iter>
181  static std::vector<event_impl_ptr> make_event_vector(_Iter begin_, _Iter end_)
182  {
183  std::vector<event_impl_ptr> evts;
184  evts.reserve(std::distance(begin_, end_));
185  for (auto i = begin_; i != end_; ++i)
186  evts.push_back((*i)._event);
187 
188  return evts;
189  }
190 
191  inline future_t<bool> wait_for_(const clock_type::duration& dt) const
192  {
193  return wait_until_(clock_type::now() + dt);
194  }
195  future_t<bool> wait_until_(const clock_type::time_point& tp) const;
196 
197 
198  static future_t<intptr_t> wait_any_(std::vector<event_impl_ptr>&& evts);
199  inline static future_t<intptr_t> wait_any_for_(const clock_type::duration& dt, std::vector<event_impl_ptr>&& evts)
200  {
201  return wait_any_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts));
202  }
203  static future_t<intptr_t> wait_any_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts);
204 
205 
206  static future_t<bool> wait_all_(std::vector<event_impl_ptr>&& evts);
207  inline static future_t<bool> wait_all_for_(const clock_type::duration& dt, std::vector<event_impl_ptr>&& evts)
208  {
209  return wait_all_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts));
210  }
211  static future_t<bool> wait_all_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts);
212  };
213 
214 }
215 }