{"id":3815,"date":"2019-08-25T22:11:20","date_gmt":"2019-08-25T14:11:20","guid":{"rendered":"https:\/\/damogame.cn\/wordpress\/?p=3815"},"modified":"2019-08-25T22:14:32","modified_gmt":"2019-08-25T14:14:32","slug":"condition%e7%9a%84wait-notify%e7%94%a8%e6%b3%95%e7%a4%ba%e4%be%8b","status":"publish","type":"post","link":"https:\/\/i007.cc\/wordpress\/archives\/3815","title":{"rendered":"condition\u7684wait notify\u7528\u6cd5\u793a\u4f8b"},"content":{"rendered":"<p>\u8fd9\u4e2a\u4f8b\u5b50\u4f4d\u4e8easio\u7684examples\\cpp14\\excutors\\priority_scheduler.cpp<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">#include &lt;asio\/ts\/executor.hpp&gt;\r\n#include &lt;condition_variable&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;memory&gt;\r\n#include &lt;mutex&gt;\r\n#include &lt;queue&gt;\r\n\r\nusing asio::dispatch;\r\nusing asio::execution_context;\r\n\r\nclass priority_scheduler : public execution_context\r\n{\r\npublic:\r\n  \/\/ A class that satisfies the Executor requirements.\r\n  class executor_type\r\n  {\r\n  public:\r\n    executor_type(priority_scheduler&amp; ctx, int pri) noexcept\r\n      : context_(ctx), priority_(pri)\r\n    {\r\n    }\r\n\r\n    priority_scheduler&amp; context() const noexcept\r\n    {\r\n      return context_;\r\n    }\r\n\r\n    void on_work_started() const noexcept\r\n    {\r\n      \/\/ This executor doesn't count work. Instead, the scheduler simply runs\r\n      \/\/ until explicitly stopped.\r\n    }\r\n\r\n    void on_work_finished() const noexcept\r\n    {\r\n      \/\/ This executor doesn't count work. Instead, the scheduler simply runs\r\n      \/\/ until explicitly stopped.\r\n    }\r\n\r\n    template &lt;class Func, class Alloc&gt;\r\n    void dispatch(Func&amp;&amp; f, const Alloc&amp; a) const\r\n    {\r\n      post(std::forward&lt;Func&gt;(f), a);\r\n    }\r\n\r\n    template &lt;class Func, class Alloc&gt;\r\n    void post(Func f, const Alloc&amp; a) const\r\n    {\r\n      auto p(std::allocate_shared&lt;item&lt;Func&gt;&gt;(\r\n            typename std::allocator_traits&lt;\r\n              Alloc&gt;::template rebind_alloc&lt;char&gt;(a),\r\n            priority_, std::move(f)));\r\n      std::lock_guard&lt;std::mutex&gt; lock(context_.mutex_);\r\n      context_.queue_.push(p);\r\n      context_.condition_.notify_one();\r\n    }\r\n\r\n    template &lt;class Func, class Alloc&gt;\r\n    void defer(Func&amp;&amp; f, const Alloc&amp; a) const\r\n    {\r\n      post(std::forward&lt;Func&gt;(f), a);\r\n    }\r\n\r\n    friend bool operator==(const executor_type&amp; a,\r\n        const executor_type&amp; b) noexcept\r\n    {\r\n      return &amp;a.context_ == &amp;b.context_;\r\n    }\r\n\r\n    friend bool operator!=(const executor_type&amp; a,\r\n        const executor_type&amp; b) noexcept\r\n    {\r\n      return &amp;a.context_ != &amp;b.context_;\r\n    }\r\n\r\n  private:\r\n    priority_scheduler&amp; context_;\r\n    int priority_;\r\n  };\r\n\r\n  executor_type get_executor(int pri = 0) noexcept\r\n  {\r\n    return executor_type(*const_cast&lt;priority_scheduler*&gt;(this), pri);\r\n  }\r\n\r\n  void run()\r\n  {\r\n    std::unique_lock&lt;std::mutex&gt; lock(mutex_);\r\n    for (;;)\r\n    {\r\n      condition_.wait(lock, [&amp;]{ return stopped_ || !queue_.empty(); });\r\n      if (stopped_)\r\n        return;\r\n      auto p(queue_.top());\r\n      queue_.pop();\r\n      lock.unlock();\r\n      p-&gt;execute_(p);\r\n      lock.lock();\r\n    }\r\n  }\r\n\r\n  void stop()\r\n  {\r\n    std::lock_guard&lt;std::mutex&gt; lock(mutex_);\r\n    stopped_ = true;\r\n    condition_.notify_all();\r\n  }\r\n\r\nprivate:\r\n  struct item_base\r\n  {\r\n    int priority_;\r\n    void (*execute_)(std::shared_ptr&lt;item_base&gt;&amp;);\r\n  };\r\n\r\n  template &lt;class Func&gt;\r\n  struct item : item_base\r\n  {\r\n    item(int pri, Func f) : function_(std::move(f))\r\n    {\r\n      priority_ = pri;\r\n      execute_ = [](std::shared_ptr&lt;item_base&gt;&amp; p)\r\n      {\r\n        Func tmp(std::move(static_cast&lt;item*&gt;(p.get())-&gt;function_));\r\n        p.reset();\r\n        tmp();\r\n      };\r\n    }\r\n\r\n    Func function_;\r\n  };\r\n\r\n  struct item_comp\r\n  {\r\n    bool operator()(\r\n        const std::shared_ptr&lt;item_base&gt;&amp; a,\r\n        const std::shared_ptr&lt;item_base&gt;&amp; b)\r\n    {\r\n      return a-&gt;priority_ &lt; b-&gt;priority_;\r\n    }\r\n  };\r\n\r\n  std::mutex mutex_;\r\n  std::condition_variable condition_;\r\n  std::priority_queue&lt;\r\n    std::shared_ptr&lt;item_base&gt;,\r\n    std::vector&lt;std::shared_ptr&lt;item_base&gt;&gt;,\r\n    item_comp&gt; queue_;\r\n  bool stopped_ = false;\r\n};\r\n\r\nint main()\r\n{\r\n  priority_scheduler sched;\r\n  auto low = sched.get_executor(0);\r\n  auto med = sched.get_executor(1);\r\n  auto high = sched.get_executor(2);\r\n  dispatch(low, []{ std::cout &lt;&lt; \"1\\n\"; });\r\n  dispatch(low, []{ std::cout &lt;&lt; \"11\\n\"; });\r\n  dispatch(med, []{ std::cout &lt;&lt; \"2\\n\"; });\r\n  dispatch(med, []{ std::cout &lt;&lt; \"22\\n\"; });\r\n  dispatch(high, []{ std::cout &lt;&lt; \"3\\n\"; });\r\n  dispatch(high, []{ std::cout &lt;&lt; \"33\\n\"; });\r\n  dispatch(high, []{ std::cout &lt;&lt; \"333\\n\"; });\r\n  dispatch(sched.get_executor(-1), [&amp;]{ sched.stop(); });\r\n  sched.run();\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8fd9\u4e2a\u4f8b\u5b50\u4f4d\u4e8easio\u7684examples\\<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[],"tags":[119],"class_list":["post-3815","post","type-post","status-publish","format-standard","hentry","tag-03-"],"_links":{"self":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/3815","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/comments?post=3815"}],"version-history":[{"count":0,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/posts\/3815\/revisions"}],"wp:attachment":[{"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/media?parent=3815"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/categories?post=3815"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/i007.cc\/wordpress\/wp-json\/wp\/v2\/tags?post=3815"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}