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 }