{"id":310631,"date":"2020-09-28T21:00:39","date_gmt":"2020-09-28T21:00:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=310631"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=310631","title":{"rendered":"\u041a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u0432 C++20. \u0427\u0430\u0441\u0442\u044c 2"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/521058\/\">\n<h1 id=\"vvedenie\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h1>\n<p>  <\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u043c <a href=\"https:\/\/habr.com\/ru\/post\/520756\/\">\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<p>  <\/p>\n<h1 id=\"beskonechnyy-potok-dannyh-pri-pomoschi-co_yield\">\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>co_yield<\/code><\/h1>\n<p>  <\/p>\n<p>\u041a\u043e\u0434 \u043d\u0438\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445. \u041a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 <code>getNext<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>co_yield<\/code> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u043e <code>start<\/code> \u0438 \u0432\u044b\u0434\u0430\u0435\u0442 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043a\u0430\u0436\u0434\u043e\u0435 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u0448\u0430\u0433\u043e\u043c <code>step<\/code>.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/\/infiniteDataStream.cpp #include &lt;coroutine&gt; #include &lt;memory&gt; #include &lt;iostream&gt;  template &lt;typename T&gt; struct Generator {     struct promise_type;     using handle_type = std::coroutine_handle&lt;promise_type&gt;;     Generator(handle_type h) : coro(h) {}                       \/\/ (3)     handle_type coro;     std::shared_ptr&lt;T&gt; value;     ~Generator() {         if (coro) {             coro.destroy();         }     }     Generator(const Generator &amp;) = delete;     Generator&amp; operator=(const Generator &amp;) = delete;     Generator(Generator &amp;&amp;other) : coro(other.coro) {         other.coro = nullptr;     }     Generator&amp; operator=(Generator &amp;&amp;other) {         coro = other.coro;         other.coro = nullptr;         return *this;     }     T getValue() {         return coro.promise().current_value;     }     bool next() {                                               \/\/ (5)         coro.resume();         return not coro.done();     }     struct promise_type {         promise_type() = default;                               \/\/ (1)         ~promise_type() = default;         auto initial_suspend() {                                \/\/ (4)             return std::suspend_always{};         }         auto final_suspend() {             return std::suspend_always{};         }         auto get_return_object() {                              \/\/ (2)             return Generator{handle_type::from_promise(*this)};         }         auto return_void() {             return std::suspend_never{};         }         auto yield_value(T value) {                             \/\/ (6)             current_value = value;             return std::suspend_always{};         }         void unhandled_exception() {             std::exit(1);         }         T current_value;     }; }; Generator &lt;int&gt; getNext(int start = 0, int step = 1) {     auto value = start;     for (int i = 0; ; ++i) {         co_yield value;         value += step;     } } int main() {     std::cout &lt;&lt; &quot;getNext():&quot;;     auto gen = getNext();     for (int i = 0; i &lt;= 10; ++i) {         gen.next();         std::cout &lt;&lt; &quot; &quot; &lt;&lt; gen.getValue();                     \/\/ (7)     }     std::cout &lt;&lt; &quot;\\ngetNext(100, -10):&quot;;     auto gen2 = getNext(100, -10);     for (int i = 0; i &lt;= 20; ++i) {         gen2.next();         std::cout &lt;&lt; &quot; &quot; &lt;&lt; gen2.getValue();     }     std::cout &lt;&lt; std::endl; }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u0441\u0431\u043e\u0440\u043a\u0443 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>g++ -fcoroutines infiniteDataStream.cpp<\/code><\/em><br \/>  \u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>main<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f 2 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b. \u041f\u0435\u0440\u0432\u0430\u044f, <code>gen<\/code>, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0442 0 \u0434\u043e 10. \u0412\u0442\u043e\u0440\u0430\u044f, <code>gen2<\/code>, \u2014 \u043e\u0442 100 \u0434\u043e -100 \u0441 \u0448\u0430\u0433\u043e\u043c 10. \u0412\u044b\u0432\u043e\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ .\/infDS getNext(): 0 1 2 3 4 5 6 7 8 9 10 getNext(100, -10): 100 90 80 70 60 50 40 30 20 10 0 -10 -20 -30 -40 -50 -60 -70 -80 -90 -100<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u0435\u0442\u043a\u0438 \u0441 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 <code>infiniteDataStream.cpp<\/code> \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442 \u043f\u0435\u0440\u0432\u0443\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 promise \u043e\u0431\u044a\u0435\u043a\u0442\u0430<\/li>\n<li>\u0412\u044b\u0437\u043e\u0432 <code>promise.get_return_object()<\/code> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430<\/li>\n<li>\u0412\u044b\u0437\u043e\u0432 <code>promise.initial_suspend()<\/code>, \u0442.\u043a. \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 &quot;\u043b\u0435\u043d\u0438\u0432\u044b\u0439&quot;, \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, <code>suspend_always<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0444\u043b\u0430\u0433\u0430, \u0435\u0441\u043b\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0438\u0441\u0447\u0435\u0440\u043f\u0430\u043b \u0441\u0435\u0431\u044f<\/li>\n<li>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u043d\u0430 <code>co_yield<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/li>\n<li>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0448\u0430\u0433\u0438 5 \u0438 6.<\/p>\n<p>  <\/p>\n<h1 id=\"sinhronizaciya-potokov-posredstvom-co_await\">\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c <code>co_await<\/code><\/h1>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>co_await<\/code>. \u041f\u043e\u043a\u0430 \u043e\u0434\u0438\u043d \u043f\u043e\u0442\u043e\u043a \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0430\u043a\u0435\u0442, \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0432\u043e\u0439. \u0423\u0441\u043b\u043e\u0432\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 (condition variables), promises \u0438 futures, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u0444\u043b\u0430\u0433\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c-\u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044c. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u0438 \u0438\u0437\u0431\u0435\u0433\u0430\u044f \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u0435 \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0440\u0438\u0441\u043a\u0438, \u043a\u0430\u043a \u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u044f (spurious wakeups) \u0438 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u0443\u0436\u0434\u0435\u043d\u0438\u044f (lost wakeups).<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/\/ senderReceiver.cpp #include &lt;coroutine&gt; #include &lt;chrono&gt; #include &lt;iostream&gt; #include &lt;functional&gt; #include &lt;string&gt; #include &lt;stdexcept&gt; #include &lt;atomic&gt; #include &lt;thread&gt;  class Event { public:     Event() = default;     Event(const Event &amp;) = delete;     Event(Event &amp;&amp;) = delete;     Event&amp; operator=(const Event &amp;) = delete;     Event&amp; operator=(Event &amp;&amp;) = delete;     class Awaiter;     Awaiter operator co_await() const;     void notify(); private:     friend class Awaiter;     mutable std::atomic&lt;void *&gt; suspendedWaiter{nullptr};     mutable std::atomic&lt;bool&gt; notified{false}; };  class Event::Awaiter { public:     Awaiter(const Event &amp;e) : event(e) {}     bool await_ready() const;     bool await_suspend(std::coroutine_handle&lt;&gt; ch);     void await_resume() {} private:     friend class Event;     const Event &amp;event;     std::coroutine_handle&lt;&gt; coroutineHandle; };  bool Event::Awaiter::await_ready() const {     if (event.suspendedWaiter.load() != nullptr) {         throw std::runtime_error(&quot;More than one waiter is not valid&quot;);     }     return event.notified; \/\/ true - \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, false - \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 }  bool Event::Awaiter::await_suspend(std::coroutine_handle&lt;&gt; ch) {     coroutineHandle = ch;     if (event.notified) {         return false;     }     \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c waiter \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f     event.suspendedWaiter.store(this);     return true; }  void Event::notify() {     notified = true;     \/\/ \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c waiter     auto *waiter = static_cast&lt;Awaiter *&gt;(suspendedWaiter.load());     \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043b\u0438 waiter     if (waiter != nullptr) {         \/\/ \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b         waiter-&gt;coroutineHandle.resume();     } }  Event::Awaiter Event::operator co_await() const {     return Awaiter{*this}; }  struct Task {     struct promise_type {         Task get_return_object() { return {}; }         std::suspend_never initial_suspend() { return {}; }         std::suspend_never final_suspend() { return {}; }         void return_void() {}         void unhandled_exception() {}     }; };  Task receiver(Event &amp;event) {     auto start = std::chrono::high_resolution_clock::now();     co_await event;     std::cout &lt;&lt; &quot;Got the notification!&quot; &lt;&lt; std::endl;     auto end = std::chrono::high_resolution_clock::now();     std::chrono::duration&lt;double&gt; elapsed = end - start;     std::cout &lt;&lt; &quot;Waited &quot; &lt;&lt; elapsed.count() &lt;&lt; &quot; seconds.&quot; &lt;&lt; std::endl; }  int main() {     std::cout &lt;&lt; &quot;Notification before waiting&quot; &lt;&lt; std::endl;     Event event1{};     auto senderThread1 = std::thread([&amp;event1] { event1.notify(); });     auto receiverThread1 = std::thread(receiver, std::ref(event1));     receiverThread1.join();     senderThread1.join();      std::cout &lt;&lt; &quot;\\nNotification after 2 seconds waiting&quot; &lt;&lt; std::endl;     Event event2{};     auto receiverThread2 = std::thread(receiver, std::ref(event2));     auto senderThread2 = std::thread([&amp;event2] {                                          using namespace std::chrono_literals;                                          std::this_thread::sleep_for(2s);                                          event2.notify();                                      });     receiverThread2.join();     senderThread2.join(); }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0447\u0438\u043a\u0430: \u0441\u0431\u043e\u0440\u043a\u0443 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u043b \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <code>g++ -pthread -fcoroutines senderReceiver.cpp<\/code><\/em><\/p>\n<p>  <\/p>\n<p>\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043a\u043e\u0440\u0443\u0442\u0438\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430. \u0421\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <code>senderReceiver.cpp<\/code> \u043f\u043e\u0442\u043e\u043a <code>senderThread1<\/code> \u0438 <code>senderThread2<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>event<\/code> \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 (<code>eventN.notify()<\/code>). \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 <code>receiver<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043a\u0430\u0445 <code>receiverThread1<\/code> \u0438 <code>receiverThread2<\/code>. \u0412\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043c\u0435\u0440 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0432\u044b\u0432\u043e\u0434 \u0435\u0433\u043e \u043d\u0430 \u044d\u043a\u0440\u0430\u043d, \u0447\u0442\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043a\u0430\u043a \u0434\u043e\u043b\u0433\u043e \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u043b\u0430 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432\u044b\u0432\u043e\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>  <\/p>\n<p><strong>\u0412\u044b\u0432\u043e\u0434 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b senderReceiver<\/strong><\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ .\/senderReceiver Notification before waiting Got the notification! Waited 3.7006e-05 seconds.  Notification after 2 seconds waiting Got the notification! Waited 2.00056 seconds.<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>Generator<\/code> \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043a\u043b\u0430\u0441\u0441 <code>Event<\/code> \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f. \u0412 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, <code>Generator<\/code> \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 awaitable \u0438 awaiter; <code>Event<\/code> \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>operator co_await<\/code> \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 awaiter. \u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 awaitable \u0438 awaiter \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043a\u043e\u0434\u0430.<\/p>\n<p>  <\/p>\n<p>\u0418\u0437 \u0432\u044b\u0432\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0432\u043e\u0434, \u0447\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c 2 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041f\u0440\u0438\u0447\u0438\u043d\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e <code>event1<\/code> \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430, \u043e\u0434\u043d\u0430\u043a\u043e <code>event2<\/code> \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u0440\u043e\u0448\u043b\u043e 2 \u0441\u0435\u043a\u0443\u043d\u0434\u044b.<br \/>  \u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 <code>senderReceiver.cpp<\/code> \u043d\u0435 \u0442\u0430\u043a \u043b\u0451\u0433\u043e\u043a \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f. \u041a\u043b\u0430\u0441\u0441 <code>Event<\/code> \u0438\u043c\u0435\u0435\u0442 \u043f\u0430\u0440\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0447\u043b\u0435\u043d\u043e\u0432: <code>suspendedWaiter<\/code> \u0438 <code>notified<\/code>. \u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 waiter \u0434\u043b\u044f \u043f\u043e\u0441\u044b\u043b\u043a\u0438 \u0441\u0438\u0433\u043d\u0430\u043b\u0430, \u0432\u0442\u043e\u0440\u043e\u0439 \u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e, <code>event1<\/code> \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0434\u043e \u0442\u043e\u0433\u043e \u043a\u0430\u043a <code>receiverThread1<\/code> \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d. \u0412\u044b\u0437\u043e\u0432 <code>even1.notify()<\/code> \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0444\u043b\u0430\u0433 <code>notified<\/code> \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e waiter. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 <code>waiter<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>nullptr<\/code> \u0442.\u043a. \u043d\u0435 \u0431\u044b\u043b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0440\u0430\u043d\u0435\u0435, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 <code>waiter-&gt;coroutineHandle.resume()<\/code> \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d. \u0412\u043f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u043c\u0435\u0442\u043e\u0434 <code>await_ready<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0431\u044b\u043b \u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d waiter \u0438, \u0435\u0441\u043b\u0438 \u0431\u044b\u043b, \u0431\u0440\u043e\u0441\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <code>std::runtime_error<\/code>. \u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u043e \u0442\u0443\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>notified<\/code> \u0431\u044b\u043b\u043e \u0440\u0430\u043d\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 <code>true<\/code> \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>notify<\/code>, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0447\u0442\u043e \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 \u043d\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <code>event2<\/code> \u0432\u044b\u0437\u043e\u0432 <code>co_await event<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435. \u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 <code>await_ready<\/code>. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435, \u0447\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u043b\u0430\u0433 <code>event.notified<\/code> \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>false<\/code> \u0447\u0442\u043e \u043e\u0431\u0443\u0441\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b. \u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>await_suspend<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 handle \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b <code>ch<\/code> \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0435\u0433\u043e \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>corotineHandle<\/code>. \u041f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u044b\u0437\u043e\u0432, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b. \u041a \u0442\u043e\u043c\u0443 \u0436\u0435, <code>waiter<\/code> \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 <code>suspendedWaiter<\/code>. \u041a\u043e\u0433\u0434\u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <code>event2.notify<\/code> \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 <code>notify<\/code>. \u0420\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0442\u0443\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0433\u0434\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043b\u0438 <code>waiter<\/code> \u0442\u0430\u043a\u043e\u0432\u043e\u0439 \u0443\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 <code>nullptr<\/code>. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 <code>waiter<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>coroutineHandle<\/code> \u0434\u043b\u044f \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043e\u0440\u0443\u0442\u0438\u043d\u044b.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/521058\/\"> https:\/\/habr.com\/ru\/post\/521058\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/521058\/\">\n<h1 id=\"vvedenie\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h1>\n<p>  <\/p>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435\u043c <a href=\"https:\/\/habr.com\/ru\/post\/520756\/\">\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>.<\/p>\n<p>  <\/p>\n<h1 id=\"beskonechnyy-potok-dannyh-pri-pomoschi-co_yield\">\u0411\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>co_yield<\/code><\/h1>\n<p>  <\/p>\n<p>\u041a\u043e\u0434 \u043d\u0438\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445. \u041a\u043e\u0440\u0443\u0442\u0438\u043d\u0430 <code>getNext<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <code>co_yield<\/code> \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u043e <code>start<\/code> \u0438 \u0432\u044b\u0434\u0430\u0435\u0442 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043a\u0430\u0436\u0434\u043e\u0435 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441 \u0448\u0430\u0433\u043e\u043c <code>step<\/code>.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-310631","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/310631","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=310631"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/310631\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=310631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=310631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=310631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}