{"id":192,"date":"2021-07-12T11:41:28","date_gmt":"2021-07-12T03:41:28","guid":{"rendered":"https:\/\/blog.king011.com\/?p=192"},"modified":"2021-07-17T08:56:03","modified_gmt":"2021-07-17T00:56:03","slug":"asio-%e5%a4%9a%e7%b7%9a%e7%a8%8b%e6%a8%a1%e5%bc%8f","status":"publish","type":"post","link":"https:\/\/blog.king011.com\/?p=192","title":{"rendered":"asio \u591a\u7dda\u7a0b\u6a21\u5f0f"},"content":{"rendered":"\n<p>asio \u6709\u5169\u7a2e\u65b9\u5f0f\u4f86\u652f\u6301\u591a\u7dda\u7a0b\uff0c\u672c\u6587\u5728\u65bc\u63a2\u8a0e\u5176\u5dee\u5225\u548c\u5728\u5be6\u969b\u9805\u76ee\u4e2d\u5982\u4f55\u7c21\u55ae\u5207\u63db\u9019\u5169\u7a2e\u6a21\u5f0f\u7684\u65b9\u6848\u3002\u672c\u6587\u7684\u5b8c\u6574\u793a\u4f8b\u5728<a rel=\"noreferrer noopener\" href=\"https:\/\/gitlab.com\/king011_example\/cc\/-\/tree\/main\/boost\/asio\/context\" target=\"_blank\">gitlab<\/a>\u4e0a\u53ef\u67e5\u770b\u5230\u3002<\/p>\n\n\n\n<p>\u9996\u5148\u4f86\u770b\u770b\u8981\u5982\u4f55\u4f7f\u7528\u9019\u5169\u7a2e\u65b9\u5f0f\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>\u65b9\u6848A -&gt; \u5206\u914d\u4e00\u500b\u5168\u5c40\u7684 io_context\uff0c\u7136\u5f8c\u5728\u591a\u500b\u7dda\u7a0b\u4e2d\u8abf\u7528 io_context \u7684 run \u65b9\u6cd5<\/li><li>\u65b9\u6848B -&gt; \u7232\u6bcf\u500b\u7dda\u7a0b\u5275\u5efa\u55ae\u7368\u7684 io_context\uff0c\u7136\u5f8c\u7dda\u7a0b\u8abf\u7528\u81ea\u5df1 io_context \u7684 run \u65b9\u6cd5<\/li><\/ul>\n\n\n\n<p>\u65b9\u6848A \u7684\u512a\u9ede\u5728\u65bc\u4ee3\u78bc\u7c21\u55ae\uff0c\u554f\u984c\u5728\u65bc\u6548\u7387\u7565\u905c\u65b9\u6848B\uff0c\u4e14\u56e0\u7232\u6240\u6709\u7dda\u7a0b\u5171\u4eab\u540c\u500b io_context \u6240\u4ee5\u5982\u679c\u67d0\u500bsocket \u5feb\u901f\u8b80\u53d6\u5169\u6b21\uff0c\u9019\u5169\u6b21\u7684\u8655\u7406\u7a0b\u5e8f\u5c07\u904b\u884c\u5728\u4e0d\u540c\u7684\u7dda\u7a0b\u4e0a\uff0c\u5982\u4e0d\u6ce8\u610f\u9019\u53ef\u80fd\u6703\u5f15\u767c\u5947\u602a\u7684 bug\u3002<\/p>\n\n\n\n<p>\u65b9\u6848B \u7684\u512a\u9ede\u5728\u65bc\u6548\u7387\u66f4\u597d\uff0c\u56e0\u7232\u6bcf\u500b\u7dda\u7a0b\u64c1\u6709\u81ea\u5df1\u7368\u7acb\u7684 io_context \uff0cio_context \u4e0d\u9700\u8981\u5728\u591a\u7dda\u7a0b\u9593\u5171\u4eab\u4ee5\u53ca\u540c\u6b65\u4e8b\u4ef6\u3002\u7f3a\u9ede\u5728\u65bc \u65b9\u6848A \u4e2d\u4e8b\u4ef6\u8655\u7406\u6703\u88ab asio \u81ea\u52d5\u6d3e\u767c\u5230\u7a7a\u9592\u7684 \u7dda\u7a0b\u4e2d\uff0c\u65b9\u6848B \u5247\u9700\u8981\u6211\u5011\u81ea\u5df1\u5be6\u73fe\u7b97\u6cd5\u5c07\u4efb\u52d9\u5408\u7406\u7684\u5206\u914d\u5230\u4e0d\u540c io_context(\u5373\u4e0d\u540c\u7684\u7dda\u7a0b\u4e2d)\uff0c\u5b58\u5728\u7f3a\u9677\u7684\u7b97\u6cd5\u53ef\u80fd\u6703\u5c0e\u81f4\u67d0\u4e9b\u7dda\u7a0b\u904e\u65bc\u5fd9\u788c\u53e6\u5916\u4e00\u4e9b\u7dda\u7a0b\u537b\u7121\u4e8b\u53ef\u5e79\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5728\u5169\u7a2e\u6a21\u5f0f\u9593\u5207\u63db<\/h2>\n\n\n\n<p>\u5169\u7a2e\u6a21\u5f0f\u5404\u6709\u7279\u8272\uff0c\u4e26\u4e14\u90fd\u9700\u8981\u4e00\u9ede\u984d\u5916\u7684\u4ee3\u78bc\u4f86\u5553\u52d5\u7dda\u7a0b\u4e4b\u985e\u7684\u64cd\u4f5c\uff0c\u65e2\u7136\u5982\u6b64\u4f55\u4e0d\u5c07\u5176\u4ee3\u78bc\u5c01\u88dd\u4e0b\uff0c\u4ee5\u8b93\u4f7f\u7528\u66f4\u7c21\u55ae\u4e26\u63d0\u4f9b\u4e00\u500b\u516c\u5171\u63a5\u53e3\u4f86\u9069\u914d\u5169\u7a2e\u6a21\u5f0f\uff0c\u4f7f\u5176\u4f7f\u7528\u8da8\u65bc\u4e00\u81f4\u3002\u5c0d\u65bc c++ \u4f86\u8aaa\u53ef\u4ee5\u5b9a\u7fa9\u4e00\u500b \u7d14\u865b\u985e \u4f86\u4f5c\u7232\u516c\u5171\u63a5\u53e3\uff0c\u7136\u5f8c\u7232\u5169\u7a2e\u6a21\u5f0f\u5be6\u73fe\u5b50\u985e\u7b97\u6cd5\u5373\u53ef\uff0c\u672c\u55b5\u5982\u4e0b\u5b9a\u7fa9\u6b64\u985e\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>namespace king011::context\n{\n    class basic_context_t\n    {\n    public:\n        typedef boost::asio::io_context context_type;\n        typedef std::pair&lt;std::size_t, context_type &amp;&gt; pair_type;\n\n        basic_context_t() = default;\n        virtual ~basic_context_t() = default;\n        \/\/ \u7372\u53d6\u4e00\u500b\u5c31\u7dd2\u7684 context \u548c\u5176\u7d22\u5f15 \u4e26\u7232\u5176\u589e\u52a0\u4efb\u52d9\u8a08\u6578\n        virtual pair_type get_context() = 0;\n        \/\/ \u8fd4\u56de\u6240\u6709\u7368\u7acb\u7684 context \u4e26\u7232\u5176\u589e\u52a0\u4efb\u52d9\u8a08\u6578\n        virtual std::vector&lt;pair_type&gt; get_contexts() = 0;\n        \/\/ \u6e1b\u5c11 context \u4e0a\u7684\u4efb\u52d9\u8a08\u6578\n        virtual void put_context(std::size_t) = 0;\n        \/\/ \u904b\u884c context\n        virtual void run() = 0;\n        \/\/ \u505c\u6b62 context\n        virtual void stop() = 0;\n    };\n};<\/code><\/pre>\n\n\n\n<p>basic_context_t \u63a5\u53e3\u6703\u5728\u5167\u90e8\u4fdd\u5b58 io_context\uff0c\u4e26\u4e14\u5b89\u6392\u7dda\u7a0b\u53bb\u8abf\u7528\u5176 run \u65b9\u6cd5\uff0c\u5176\u63d0\u4f9b\u7684\u516c\u5171\u51fd\u6578\u6709\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>get_context -&gt; \u8fd4\u56de\u4e00\u500bstd::pair \u5176\u4e2d\u5305\u542b io_context \u7684\u5f15\u7528 \u4ee5\u53ca\u8207 io_context \u95dc\u806f\u7684\u4e00\u500b\u6a19\u8b58(\u5c0d\u65bc\u65b9\u6848A \u56fa\u5b9a\u8fd4\u56de\u5171\u4eab\u7684 io_context \u4ee5\u53ca 0 \u4f5c\u7232\u6a19\u8b58\u5373\u53ef\uff0c\u65b9\u6848 B \u5247\u4f7f\u7528\u81ea\u5df1\u7684\u4efb\u52d9\u5206\u914d\u7b97\u6cd5 \u8fd4\u56de\u4e00\u500b io_context \u4ee5\u53ca\u5176\u95dc\u806f\u7684 \u6a19\u8b58\u5373\u53ef)<\/li><li>put_context -&gt; \u50b3\u5165 io_context \u95dc\u806f\u7684\u6a19\u8b58\uff0c\u4ee5\u901a\u77e5\u4efb\u52d9\u5206\u914d\u7b97\u6cd5\u6b64 io_context \u6e1b\u5c11\u4e00\u500b\u4efb\u52d9\u8a08\u6578<\/li><li>run -&gt; \u5728\u5167\u90e8\u7dda\u7a0b\u4e2d\u8abf\u7528 io_context \u7684 run \u4e26\u7b49\u5f85\u5176\u8fd4\u56de<\/li><li>stop -&gt; \u7232\u6240\u6709 io_context \u8abf\u7528 stop<\/li><\/ul>\n\n\n\n<p>\u5982\u6b64\u6211\u5011\u4fbf\u53ef\u4ee5\u5be6\u73fe\u5404\u7a2e basic_context_t \u7684\u5b50\u985e\u4ee5\u8b93 asio \u4f86\u4f7f\u7528\u4e0d\u540c\u6a21\u5f0f\u548c\u7b97\u6cd5\u4f86\u904b\u884c\uff0c\u800c\u53ea\u9700\u8981\u7c21\u55ae\u7684 \u5207\u63db\u5be6\u4f8b\u5316\u7684 \u5b50\u985e\u5373\u53ef\u7c21\u55ae\u7684\u5207\u63db\u7b97\u6cd5\u548c\u6a21\u5f0f\u3002<\/p>\n\n\n\n<p>\u5728\u5275\u5efa\u7570\u6b65\u5c0d\u8c61\u6bd4\u5982 boost::asio::ip::tcp::socket \u6642\uff0c\u6211\u5011\u9700\u8981\u8abf\u7528 get_context \u4f86\u7372\u53d6\u4e00\u500b\u95dc\u806f\u7684 io_context \u5206\u914d\u7b97\u6cd5\u6703\u8fd4\u56de\u5408\u9069\u7684 io_context \u4e26\u77e5\u9053\u5979\u88ab\u95dc\u806f\u5230\u4e00\u7d44\u7570\u6b65\u4efb\u52d9\uff0c\u7576\u6b64 socket \u92b7\u6bc0\u6642\u6211\u5011\u9700\u8981\u8abf\u7528 put_context \u4f86\u901a\u77e5\u4efb\u52d9\u5206\u914d\u7b97\u6cd5\u95dc\u806f\u7684\u4e00\u7d44\u4efb\u52d9\u5df2\u7d93\u5b8c\u6210\u3002\u6240\u4ee5 get_context \u8207 put_context \u7684\u8abf\u7528\u61c9\u8a72\u662f\u4e00\u4e00\u5c0d\u61c9\u7684\uff0c\u7232\u4e86\u907f\u514d put_context \u672a\u88ab\u8abf\u7528\uff0c\u6211\u5011\u53ef\u4ee5\u6a21\u4eff std::unique_lock \u548c std::lock_guard \u4f86\u5be6\u73fe RAII \u65b9\u5f0f\u7684\u8abf\u7528\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nnamespace king011::context\n{\n    class context_guard_t final\n    {\n    public:\n        typedef std::pair&lt;std::size_t, basic_context_t::context_type &amp;&gt; value_type;\n\n    private:\n        value_type value_;\n        basic_context_t &amp;context_;\n\n    public:\n        explicit context_guard_t(basic_context_t &amp;context)\n            : context_(context),\n              value_(context.get_context())\n        {\n        }\n        explicit context_guard_t(const context_guard_t &amp;) = delete;\n        context_guard_t &amp;operator=(const context_guard_t &amp;) = delete;\n        ~context_guard_t()\n        {\n            context_.put_context(value_.first);\n        }\n        basic_context_t::context_type &amp;get_context() noexcept\n        {\n            return value_.second;\n        }\n    };\n    class unique_context_t final\n    {\n    public:\n    private:\n        std::size_t id_ = 0;\n        basic_context_t::context_type *type_ = nullptr;\n        basic_context_t *context_ = nullptr;\n\n    public:\n        explicit unique_context_t(basic_context_t &amp;context)\n            : context_(&amp;context)\n        {\n            auto elem = context.get_context();\n            id_ = elem.first;\n            type_ = &amp;elem.second;\n        }\n        unique_context_t(unique_context_t &amp;&amp;o) noexcept : context_(o.context_)\n        {\n            id_ = o.id_;\n            type_ = o.type_;\n\n            o.context_ = nullptr;\n        }\n        explicit unique_context_t(const unique_context_t &amp;) = delete;\n        unique_context_t &amp;operator=(const unique_context_t &amp;) = delete;\n        unique_context_t &amp;operator=(unique_context_t &amp;&amp;o) noexcept\n        {\n            if (context_)\n            {\n                context_-&gt;put_context(id_);\n                context_ = nullptr;\n            }\n\n            context_ = o.context_;\n            id_ = o.id_;\n            type_ = o.type_;\n            if (o.context_)\n            {\n                o.context_ = nullptr;\n            }\n            return *this;\n        }\n        ~unique_context_t()\n        {\n            put_context();\n        }\n        void put_context()\n        {\n            if (context_)\n            {\n                context_-&gt;put_context(id_);\n                context_ = nullptr;\n            }\n        }\n        basic_context_t::context_type &amp;get_context() noexcept\n        {\n            return *type_;\n        }\n        operator bool() const noexcept\n        {\n            return context_;\n        }\n    };\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5feb\u901f\u958b\u59cb<\/h2>\n\n\n\n<p>\u672c\u55b5\u5728\u793a\u4f8b\u4e2d\u5275\u5efa\u4e86\u4e09\u500b basic_context_t \u7684\u5b50\u985e\u4f86\u5be6\u73fe\u4f7f\u7528\u4e0d\u540c\u6a21\u5f0f\u548c\u7b97\u6cd5<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>threads_context_t -&gt; \u65b9\u6848A\u7684 \u591a\u7dda\u7a0b\u5171\u4eab io_context \u6a21\u5f0f<\/li><li>round_robin_context_t -&gt; \u65b9\u6848B\u7684 \u7dda\u7a0b\u7368\u4eab io_context \u6a21\u5f0f\uff0c\u5728\u5206\u914d\u4efb\u52d9\u6642 \u4f7f\u7528\u4f9d\u6b21\u5faa\u74b0\u7684\u65b9\u5f0f<\/li><li>shared_work_context_t -&gt; \u65b9\u6848B\u7684 \u7dda\u7a0b\u7368\u4eab io_context \u6a21\u5f0f\uff0c\u5728\u5206\u914d\u4efb\u52d9\u6642 \u4f7f\u7528\u6700\u5c0f\u5806\u5c07\u4efb\u52d9\u5206\u914d\u7d66\u95dc\u806f\u7570\u6b65\u5c0d\u8c61\u6700\u5c11\u7684 io_context<\/li><\/ol>\n\n\n\n<p>\u6709\u4e86\u9019\u4e09\u500b\u5c0d\u8c61\uff0c\u4f9d\u64da\u7528\u6236\u50b3\u5165\u4e0d\u540c\u53c3\u6578\u5be6\u4f8b\u5316\u4e0d\u540c\u7684 basic_context_t \u5b50\u985e\u5373\u53ef\uff0c\u4e0b\u9762\u662f\u4e00\u500b echo \u670d\u52d9\u5668\u7684\u4f8b\u5b50\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;iostream&gt;\n#include \"CLI11.hpp\"\n#include \"version.h\"\n\/\/ #define __CONTEXT__CONTEXT_SHARED_WORK_TEST__\n\/\/ #define __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n#include \"context\/round_robin.hpp\"\n#include \"context\/threads.hpp\"\n#include \"context\/shared_work.hpp\"\n\n#include &lt;boost\/lexical_cast.hpp&gt;\n#include &lt;boost\/asio.hpp&gt;\n#include &lt;boost\/asio\/spawn.hpp&gt;\n#define BUFFER_SIZE (1024 * 32)\ntypedef boost::asio::io_context io_context_t;\ntypedef boost::asio::ip::tcp::acceptor acceptor_t;\ntypedef boost::asio::ip::tcp::socket socket_t;\ntypedef boost::asio::ip::tcp::endpoint endpoint_t;\nendpoint_t get_endpoint(const std::string &amp;addr)\n{\n    auto find = addr.find_last_of(\":\");\n    if (find == std::string::npos)\n    {\n        throw std::domain_error(\"bad addr\");\n    }\n    auto port = boost::lexical_cast&lt;boost::asio::ip::port_type&gt;(addr.substr(find + 1));\n    auto domain = addr.substr(0, find);\n    if (domain.empty())\n    {\n        return endpoint_t(boost::asio::ip::tcp::v6(), port);\n    }\n    else\n    {\n        return endpoint_t(boost::asio::ip::address::from_string(domain), port);\n    }\n}\nvoid accept_sleep(const std::exception &amp;e, std::size_t &amp;temp_delay, acceptor_t &amp;acceptor, boost::asio::yield_context yield)\n{\n    if (temp_delay)\n    {\n        temp_delay *= 2;\n        if (temp_delay &gt; 1000)\n        {\n            temp_delay = 1000;\n        }\n    }\n    else\n    {\n        temp_delay = 5;\n    }\n\n    boost::asio::deadline_timer sleep(acceptor.get_executor(), boost::posix_time::milliseconds(temp_delay));\n    std::cerr &lt;&lt; \"Accept error: \" &lt;&lt; e.what()\n              &lt;&lt; \"; retrying in \" &lt;&lt; temp_delay &lt;&lt; \"ms\"\n              &lt;&lt; std::endl;\n\n    sleep.async_wait(yield);\n}\nvoid accept_routine(king011::context::basic_context_t &amp;pool, acceptor_t &amp;acceptor, boost::asio::yield_context yield)\n{\n    std::size_t temp_delay = 0;\n    for (;;)\n    {\n        try\n        {\n            \/\/ \u63a5\u53d7\u4e00\u500b\u65b0\u9023\u63a5\n            king011::context::unique_context_t unique_context(pool);\n            auto &amp;context = unique_context.get_context();\n            socket_t s(context);\n            acceptor.async_accept(s, yield);\n            temp_delay = 0;\n            \/\/ \u5553\u52d5 socket \u5354\u7a0b\n            boost::asio::spawn(context, &#91;s = boost::move(s), unique_context = std::move(unique_context)](boost::asio::yield_context yield) mutable\n                               {\n                                   auto remote = s.remote_endpoint();\n                                   try\n                                   {\n                                       char buffer&#91;BUFFER_SIZE];\n                                       for (;;)\n                                       {\n                                           \/\/ \u8b80\u53d6\n                                           size_t length = s.async_read_some(\n                                               boost::asio::buffer(buffer, BUFFER_SIZE),\n                                               yield);\n                                           \/\/ \u5beb\u5165\n                                           s.async_write_some(\n                                               boost::asio::buffer(buffer, length),\n                                               yield);\n                                       }\n                                   }\n                                   catch (const boost::system::system_error &amp;e)\n                                   {\n                                       if (e.code().value() != boost::asio::error::eof)\n                                       {\n                                           std::cout &lt;&lt; boost::diagnostic_information(e) &lt;&lt; std::endl;\n                                       }\n                                   }\n                                   catch (const std::exception &amp;e)\n                                   {\n                                       std::cout &lt;&lt; e.what() &lt;&lt; std::endl;\n                                   }\n                               });\n        }\n        catch (const std::exception &amp;e)\n        {\n            accept_sleep(e, temp_delay, acceptor, yield);\n        }\n    }\n}\nvoid run(const std::string &amp;mode, king011::context::basic_context_t &amp;pool, const std::string &amp;addr)\n{\n    \/\/ \u5275\u5efa\u76e3\u807d\u5668\n    auto endpoint = get_endpoint(addr);\n    auto context = pool.get_context();\n    acceptor_t acceptor(context.second, endpoint);\n    std::cout &lt;&lt; mode &lt;&lt; \" work at \" &lt;&lt; addr &lt;&lt; std::endl;\n\n    auto contexts = pool.get_contexts();\n    for (auto &amp;context : contexts)\n    {\n        \/\/ \u904b\u884c\u76e3\u807d\u5668\u5354\u7a0b\n        boost::asio::spawn(\n            context.second,\n            std::bind(accept_routine,\n                      std::ref(pool),\n                      std::ref(acceptor),\n                      std::placeholders::_1));\n    }\n\n    \/\/ \u904b\u884c\u670d\u52d9\n    pool.run();\n}\nint main(int argc, char *argv&#91;])\n{\n    CLI::App app(\"context\");\n    app.callback(\n        &#91;&amp;cmd = app]\n        {\n            const CLI::Option &amp;v = *cmd.get_option(\"--version\");\n            auto addr = cmd.get_option(\"--addr\")-&gt;as&lt;std::string&gt;();\n            if (v)\n            {\n                std::cout &lt;&lt; CONTEXT_VERSION\n                          &lt;&lt; std::endl;\n            }\n            else if (!addr.empty())\n            {\n                auto mode = cmd.get_option(\"--mode\")-&gt;as&lt;std::string&gt;();\n                if (\"threads\" == mode)\n                {\n                    king011::context::threads_context_t context;\n                    run(mode, context, addr);\n                }\n                else if (\"round\" == mode)\n                {\n                    king011::context::round_robin_context_t context;\n                    run(mode, context, addr);\n                }\n                else if (\"shared\" == mode)\n                {\n                    king011::context::shared_work_context_t context;\n                    run(mode, context, addr);\n                }\n                else\n                {\n                    throw std::runtime_error(\"unknow mode\");\n                }\n            }\n            else\n            {\n                throw CLI::CallForHelp();\n            }\n        });\n    app.add_flag(\"-v,--version\", \"display version\");\n    std::string addr = \":9000\";\n    app.add_option(\"-a,--addr\",\n                   addr,\n                   \"listen addr\",\n                   true);\n    std::string mode = \"shared\";\n    app.add_option(\"-m,--mode\",\n                   mode,\n                   \"work mode &#91;threads round shared]\",\n                   true);\n    CLI11_PARSE(app, argc, argv);\n    return 0;\n}<\/code><\/pre>\n\n\n\n<p>\u6838\u5fc3\u4ee3\u78bc\u53ea\u6709 accept_routine \u51fd\u6578\u5c31\u662f\u901a\u5e38\u7684 asio \u5354\u7a0b\u5beb\u6cd5\uff0c\u4ee5\u53ca run \u51fd\u6578\u8abf\u7528 basic_context_t \u7684 run \u65b9\u6cd5\u5553\u52d5\u5de5\u4f5c\u7dda\u7a0b\uff0c\u5176\u5b83\u4ee3\u78bc\u5247\u7528\u65bc\u89e3\u6790\u547d\u4ee4\u884c\u53c3\u6578\u3002<\/p>\n\n\n\n<p>\u5f8c\u9762\u6211\u5011\u4f86\u770b\u770b threads_context_t round_robin_context_t shared_work_context_t \u8981\u5982\u4f55\u5be6\u73fe<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">threads_context_t<\/h2>\n\n\n\n<p>threads_context_t \u9700\u8981\u4fdd\u5b58\u4e00\u500b io_context \u4ee5\u53ca\u4e00\u500b std::size_t \u8a18\u9304\u9700\u8981\u5553\u52d5\u7684\u7dda\u7a0b\u6578\u5373\u53ef<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>get_contexts \u51fd\u6578\u8fd4\u56de io_context<\/li><li>put_context \u51fd\u6578\u7a7a\u5be6\u73fe<\/li><li>run \u51fd\u6578\u5553\u52d5\u5404\u7a2e\u7dda\u7a0b\u4e26\u8abf\u7528 io_context \u7684 run<\/li><li>stop \u5247\u8abf\u7528 io_context \u7684 stop \u5373\u53ef<\/li><\/ol>\n\n\n\n<p>\u6ce8\u610f run \u51fd\u6578\u9084\u61c9\u8a72\u5275\u5efa\u4e00\u500b io_context::work \u4ee5\u907f\u514d\u5de5\u4f5c\u7dda\u7a0b\u56e0\u7232 asio \u6c92\u6709\u4efb\u4f55\u7570\u6b65\u4efb\u52d9\u800c\u9000\u51fa\uff0c\u800c stop \u51fd\u6578\u61c9\u8a72\u92b7\u6bc0 run \u4e2d\u5275\u5efa\u7684 io_context::work\u3002<\/p>\n\n\n\n<p>\u5b8c\u6574\u7684\u5be6\u73fe\u4ee3\u78bc\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef __CONTEXT__CONTEXT_THREAD_HPP__\n#define __CONTEXT__CONTEXT_THREAD_HPP__\n#include \"basic.hpp\"\n#include &lt;thread&gt;\nnamespace king011::context\n{\n    template &lt;typename Mutex = std::mutex&gt;\n    class threads_context_t final : public basic_context_t\n    {\n    public:\n        typedef Mutex mutex_type;\n\n    private:\n        typedef std::promise&lt;boost::system::error_code&gt; promise_type;\n        typedef std::shared_future&lt;boost::system::error_code&gt; future_type;\n        typedef std::pair&lt;std::shared_ptr&lt;promise_type&gt;, future_type&gt; completer_type;\n        \/\/ \u57f7\u884c\u4e0a\u4e0b\u6587\n        context_type context_;\n        \/\/ \u9632\u6b62 io_context \u7a7a\u9592\u9000\u51fa\n        std::vector&lt;context_type::work&gt; works_;\n        completer_type completer_;\n        \/\/ \u540c\u6b65\u5c0d\u8c61\n        mutex_type mutex_;\n        \/\/ \u4f75\u767c\u7dda\u7a0b\u6578\n        std::size_t concurrency_;\n\n    public:\n        explicit threads_context_t(std::size_t concurrency = std::thread::hardware_concurrency())\n        {\n            if (concurrency &lt; 1)\n            {\n                throw std::length_error(\"concurrency should be &gt; 0\");\n            }\n            concurrency_ = concurrency;\n        }\n        threads_context_t(const threads_context_t &amp;) = delete;\n        threads_context_t *operator=(const threads_context_t &amp;) = delete;\n        virtual ~threads_context_t()\n        {\n            stop();\n        }\n        virtual pair_type get_context() override\n        {\n            return pair_type(0, context_);\n        }\n        virtual std::vector&lt;pair_type&gt; get_contexts() override\n        {\n            return std::vector&lt;pair_type&gt;(1, pair_type(0, context_));\n        }\n        virtual void put_context(std::size_t) override {}\n        virtual void run() override\n        {\n            completer_type completer;\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer_.first)\n                {\n                    completer = completer_;\n                }\n                else\n                {\n                    auto promise = std::make_shared&lt;promise_type&gt;();\n                    completer = std::make_pair(promise, promise-&gt;get_future().share());\n                    completer_ = completer;\n                    works_.emplace_back(context_);\n                    std::thread(&#91;promise, &amp;context = context_, concurrency = concurrency_]\n                                {\n                                    std::vector&lt;std::thread&gt; threads;\n                                    for (size_t i = 1; i &lt; concurrency; i++)\n                                    {\n                                        threads.emplace_back(&#91;&amp;context]\n                                                             {\n                                                                 boost::system::error_code ec;\n                                                                 context.run(ec);\n                                                             });\n                                    }\n                                    boost::system::error_code ec;\n                                    context.run(ec);\n                                    for (auto &amp;thread : threads)\n                                    {\n                                        thread.join();\n                                    }\n                                    promise-&gt;set_value(ec);\n                                })\n                        .detach();\n                }\n            }\n            \/\/ \u7b49\u5f85\u5b8c\u6210\n            auto ec = completer.second.get();\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer.first == completer_.first)\n                {\n                    completer_.first.reset();\n                }\n            }\n            if (ec)\n            {\n                throw boost::system::system_error(ec);\n            }\n        }\n        virtual void stop() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            context_.stop();\n            works_.clear();\n        }\n    };\n}\n#endif \/\/ __CONTEXT__CONTEXT_THREAD_HPP__<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">round_robin_context_t<\/h2>\n\n\n\n<p>round_robin_context_t \u63a1\u7528\u65b9\u6848 B \u7684\u5de5\u4f5c\u6a21\u5f0f\uff0c\u7232\u6bcf\u500b\u4f75\u767c\u7684\u7dda\u7a0b\uff0c\u5275\u5efa\u4e00\u500b\u7368\u7acb\u7684 io_context\uff0cget_context \u5c07\u5faa\u74b0\u5f9e io_context \u6578\u7d44\u4e2d\u4f9d\u6b21\u8fd4\u56de \u4e00\u500b io_context\uff0c\u6240\u6709 io_context \u90fd\u6703\u88ab\u516c\u5e73\u7684\u5206\u914d\uff0c\u9019\u6a23\u7684\u5be6\u73fe\u512a\u9ede\u5728\u65bc\u4ee3\u78bc\u7c21\u55ae\uff0c\u5206\u914d\u7b97\u6cd5\u9ad8\u6548\uff0c\u4f46\u5982\u679c io_context \u95dc\u806f\u7684\u7570\u6b65\u5c0d\u8c61\u751f\u547d\u671f\u5f88\u9577\u800c\u53e6\u5916\u4e00\u4e9b io_context \u95dc\u806f\u7684 \u7570\u6b65\u5c0d\u8c61\u751f\u547d\u671f\u5f88\u77ed\uff0c\u53ef\u80fd\u6703\u5c0e\u81f4 \u95dc\u806f\u9577\u751f\u547d\u671f\u7684 io_context \u5f88\u5fd9\u788c\uff0c\u95dc\u806f\u77ed\u751f\u547d\u671f\u7684 io_context \u5f88\u60a0\u9592\u3002<\/p>\n\n\n\n<p>\u4f46\u901a\u5e38\u60c5\u6cc1\u4e0b round_robin_context_t \u90fd\u53ef\u4ee5\u9ad8\u6548\u7684\u6b63\u5e38\u5de5\u4f5c\uff0c\u9084\u662f\u770b\u4e0b \u5982\u4f55\u5be6\u73fe round_robin_context_t\u3002<\/p>\n\n\n\n<p>round_robin_context_t \u9700\u8981\u4fdd\u5b58\u4e00\u500b io_context \u6578\u7d44\u4ee5\u53ca\u4e00\u500b next \u904a\u6a19\u6307\u793a\u4e0b\u6b21 get_context \u61c9\u8a72\u8fd4\u56de\u6578\u7d44\u4e2d\u7684\u54ea\u500b io_context\uff0c\u540c\u6642\u7576\u8abf\u7528\u904e get_context \u5f8c\u5c07\u904a\u6a19\u5411\u5f8c\u79fb\u52d5\uff0c\u5b8c\u6574\u4ee3\u78bc\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef __CONTEXT__CONTEXT_ROUND_ROBIN_HPP__\n#define __CONTEXT__CONTEXT_ROUND_ROBIN_HPP__\n#include \"basic.hpp\"\n#include &lt;thread&gt;\nnamespace king011::context\n{\n    template &lt;typename Mutex = std::mutex&gt;\n    class round_robin_context_t final : public basic_context_t\n    {\n    public:\n        typedef Mutex mutex_type;\n\n    private:\n        typedef std::promise&lt;boost::system::error_code&gt; promise_type;\n        typedef std::shared_future&lt;boost::system::error_code&gt; future_type;\n        typedef std::pair&lt;std::shared_ptr&lt;promise_type&gt;, future_type&gt; completer_type;\n        \/\/ \u57f7\u884c\u4e0a\u4e0b\u6587\n        std::vector&lt;context_type&gt; contexts_;\n        \/\/ \u9632\u6b62 io_context \u7a7a\u9592\u9000\u51fa\n        std::vector&lt;context_type::work&gt; works_;\n        completer_type completer_;\n        \/\/ \u540c\u6b65\u5c0d\u8c61\n        mutex_type mutex_;\n        \/\/ \u5faa\u74b0 \u7d22\u5f15\n        std::size_t next_;\n\n    public:\n        explicit round_robin_context_t(std::size_t concurrency = std::thread::hardware_concurrency()) : next_(0)\n        {\n            if (concurrency &lt; 1)\n            {\n                throw std::length_error(\"concurrency should be &gt; 0\");\n            }\n            contexts_ = std::move(std::vector&lt;context_type&gt;(concurrency));\n        }\n        round_robin_context_t(const round_robin_context_t &amp;) = delete;\n        round_robin_context_t *operator=(const round_robin_context_t &amp;) = delete;\n        virtual ~round_robin_context_t()\n        {\n            stop();\n        }\n        \/\/ \u8fd4\u56de\u4e0b\u500b context \u4e26\u79fb\u52d5\u7d22\u5f15\n        virtual pair_type get_context() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            auto i = next_++;\n            if (next_ == contexts_.size())\n            {\n                next_ = 0;\n            }\n            return pair_type(i, contexts_&#91;i]);\n        }\n        virtual std::vector&lt;pair_type&gt; get_contexts() override\n        {\n            std::vector&lt;pair_type&gt; result;\n            std::size_t i;\n            for (auto &amp;context : contexts_)\n            {\n                result.emplace_back(i++, context);\n            }\n            return std::move(result);\n        }\n        virtual void put_context(std::size_t) override {}\n        virtual void run() override\n        {\n            completer_type completer;\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer_.first)\n                {\n                    completer = completer_;\n                }\n                else\n                {\n                    auto promise = std::make_shared&lt;promise_type&gt;();\n                    completer = std::make_pair(promise, promise-&gt;get_future().share());\n                    completer_ = completer;\n                    auto count = contexts_.size();\n                    for (size_t i = 0; i &lt; count; i++)\n                    {\n                        works_.emplace_back(contexts_&#91;i]);\n                    }\n                    std::thread(&#91;promise, &amp;contexts = contexts_]\n                                {\n                                    std::vector&lt;std::thread&gt; threads;\n                                    auto count = contexts.size();\n                                    for (size_t i = 1; i &lt; count; i++)\n                                    {\n                                        threads.emplace_back(&#91;&amp;context = contexts&#91;i]]\n                                                             {\n                                                                 boost::system::error_code ec;\n                                                                 context.run(ec);\n                                                             });\n                                    }\n                                    boost::system::error_code ec;\n                                    contexts&#91;0].run(ec);\n                                    for (auto &amp;thread : threads)\n                                    {\n                                        thread.join();\n                                    }\n                                    promise-&gt;set_value(ec);\n                                })\n                        .detach();\n                }\n            }\n            \/\/ \u7b49\u5f85\u5b8c\u6210\n            auto ec = completer.second.get();\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer.first == completer_.first)\n                {\n                    completer_.first.reset();\n                }\n            }\n            if (ec)\n            {\n                throw boost::system::system_error(ec);\n            }\n        }\n        virtual void stop() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            for (auto &amp;context : contexts_)\n            {\n                context.stop();\n            }\n            works_.clear();\n        }\n    };\n};\n#endif \/\/ __CONTEXT__CONTEXT_ROUND_ROBIN_HPP__<\/code><\/pre>\n\n\n\n<p>\u6ce8\u610f\u73fe\u5728 run \u51fd\u6578\u4e2d\u61c9\u8a72\u7232\u6bcf\u500b io_context \u90fd\u5275\u5efa\u4e00\u500b io_context::work<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">shared_work_context_t<\/h2>\n\n\n\n<p>shared_work_context_t \u540c\u6a23\u662f\u63a1\u7528\u65b9\u6848 B \u7684\u5de5\u4f5c\u6a21\u5f0f\uff0c\u7232\u6bcf\u500b\u4f75\u767c\u7684\u7dda\u7a0b\uff0c\u5275\u5efa\u4e00\u500b\u7368\u7acb\u7684 io_context\u3002\u76f8\u5c0d round_robin_context_t \u7684\u512a\u52e2\u5728\u65bc\u4f7f\u7528\u4e86\u4e00\u500b\u6700\u5c0f\u5806\u8a18\u9304 io_context \u95dc\u806f\u7684\u7570\u6b65\u5c0d\u8c61\u6578\u91cf\uff0cget_context \u6bcf\u6b21\u8fd4\u56de\u95dc\u806f\u5c0d\u8c61\u6700\u5c11\u7684 io_context \uff0c\u4ee5\u5118\u91cf\u8b93\u6bcf\u500b\u7dda\u7a0b\u7576\u524d\u7684\u7e41\u5fd9\u5ea6\u5118\u91cf\u8da8\u65bc\u4e00\u81f4\u3002<\/p>\n\n\n\n<p>\u5728\u6709\u4e86 round_robin_context_t \u7684\u5be6\u73fe\u5f8c \u5f88\u5bb9\u6613\u4fee\u6539\u7232 shared_work_context_t \u53ea\u9700\u8981\u591a\u4fdd\u5b58\u4e00\u500b\u6700\u5c0f\u5806\u7528\u65bc\u6392\u5e8f\uff0c\u5728 get_context \u548c put_context \u5f8c\u91cd\u5beb\u8abf\u6574\u6700\u5c0f\u5806\u5373\u53ef\uff0c\u7136\u800c c++ \u6a19\u6e96\u5eab\u7684\u6700\u5c0f\u5806\u7576\u5143\u7d20\u4fee\u6539\u6642\u7121\u6cd5\u8abf\u6574\u53ea\u80fd\u91cd\u65b0\u521d\u59cb\u5316\u5806\uff0c\u7232\u6b64\u6211\u5011\u5148\u5be6\u73fe\u4e00\u500b\u81ea\u5df1\u7684\u5806\u6a21\u677f\uff0c\u4ee3\u78bc\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef __CONTEXT__CONTAINER_HEAP_HPP__\n#define __CONTEXT__CONTAINER_HEAP_HPP__\n#include &lt;vector&gt;\n#include &lt;functional&gt;\nnamespace king011::container\n{\n    template &lt;typename Type, typename Compare = std::less&lt;Type&gt;&gt;\n    class heap_t final\n    {\n    private:\n        Compare less_;\n\n    public:\n        typedef Type value_type;\n        std::vector&lt;value_type&gt; array;\n\n        explicit heap_t() = default;\n        ~heap_t() = default;\n        heap_t(const heap_t &amp;o) = delete;\n        heap_t &amp;operator=(const heap_t &amp;o) = delete;\n        explicit heap_t(heap_t &amp;&amp;o) : less_()\n        {\n            this-&gt;array = std::move(o.array);\n        }\n        explicit heap_t(std::vector&lt;value_type&gt; &amp;&amp;arr) : less_()\n        {\n            array = std::move(arr);\n        }\n        heap_t &amp;operator=(heap_t &amp;&amp;o)\n        {\n            array = std::move(o.array);\n            return *this;\n        }\n        heap_t &amp;operator=(std::vector&lt;value_type&gt; &amp;&amp;arr)\n        {\n            array = std::move(arr);\n            return *this;\n        }\n        inline void swap(heap_t &amp;o)\n        {\n            array.swap(o.array);\n        }\n\n        \/\/ \u521d\u59cb\u5316\u5806\n        void init()\n        {\n            \/\/ heapify\n            int n = array.size();\n            for (int i = n \/ 2 - 1; i &gt;= 0; i--)\n            {\n                _down(i, n);\n            }\n        }\n        \/\/ \u8fd4\u56de\u5806\u9802\u5143\u7d20\n        inline value_type &amp;top() noexcept\n        {\n            return array.front();\n        }\n        inline const value_type &amp;top() const noexcept\n        {\n            return array.front();\n        }\n        \/\/ \u5c07\u5806\u9802\u5143\u7d20\u5f48\u51fa\n        void pop()\n        {\n            int n = array.size();\n            --n;\n            _swap(0, n);\n            _down(0, n);\n\n            array.pop_back();\n        }\n        \/\/ \u5411\u5806\u4e2d\u6dfb\u52a0\u5143\u7d20\n        inline void push(value_type &amp;v)\n        {\n            array.push_back(v);\n            _up(array.size() - 1);\n        }\n        \/\/ \u5411\u5806\u4e2d\u6dfb\u52a0\u5143\u7d20\n        inline void push(value_type &amp;&amp;v)\n        {\n            array.push_back(std::move(v));\n            _up(array.size() - 1);\n        }\n        \/\/ \u7576\u5806\u4e2d\u5143\u7d20\u8b8a\u5316 \u4fee\u5fa9\u5806\u6027\u8cea\n        inline void fix(int i)\n        {\n            if (!_down(i, array.size()))\n            {\n                _up(i);\n            }\n        }\n        \/\/ \u79fb\u9664\u5806\u4e2d\u5143\u7d20\n        void remove(int i)\n        {\n            int n = array.size();\n            --n;\n            if (n != i)\n            {\n                _swap(i, n);\n                if (!_down(i, n))\n                {\n                    _up(i);\n                }\n            }\n            array.pop_back();\n        }\n\n        inline bool empty() const noexcept\n        {\n            return array.empty();\n        }\n        inline std::size_t size() const noexcept\n        {\n            return array.size();\n        }\n        inline value_type &amp;operator&#91;](std::size_t i) noexcept\n        {\n            return array&#91;i];\n        }\n        inline const value_type &amp;operator&#91;](std::size_t i) const noexcept\n        {\n            return array&#91;i];\n        }\n\n    private:\n        inline bool _less(int i, int j)\n        {\n            return less_(array&#91;i], array&#91;j]);\n        }\n        inline void _swap(int i, int j)\n        {\n            return std::swap(array&#91;i], array&#91;j]);\n        }\n        bool _down(int i0, int n)\n        {\n            auto i = i0;\n            for (;;)\n            {\n                auto j1 = 2 * i + 1;\n                if (j1 &gt;= n || j1 &lt; 0)\n                { \/\/ j1 &lt; 0 after int overflow\n                    break;\n                }\n                auto j = j1; \/\/ left child\n                if (auto j2 = j1 + 1; j2 &lt; n &amp;&amp; _less(j2, j1))\n                {\n                    j = j2; \/\/ = 2*i + 2  \/\/ right child\n                }\n                if (!_less(j, i))\n                {\n                    break;\n                }\n                _swap(i, j);\n                i = j;\n            }\n            return i &gt; i0;\n        }\n        void _up(int j)\n        {\n            for (;;)\n            {\n                auto i = (j - 1) \/ 2; \/\/ parent\n                if (i == j || !_less(j, i))\n                {\n                    break;\n                }\n                _swap(i, j);\n                j = i;\n            }\n        }\n    };\n};\n#endif \/\/ __CONTEXT__CONTAINER_HEAP_HPP__<\/code><\/pre>\n\n\n\n<p>\u6709\u4e86\u6700\u5c0f\u5806 \u5c07 round_robin_context_t \u8907\u88fd\u4e00\u4efd\u7232 shared_work_context_t \u4e26\u52a0\u5165\u6700\u5c0f\u5806\u5c6c\u6027\u4e26\u4e14\u4fee\u6539 get_context \u548c put_context \u7684\u5be6\u73fe\u5373\u53ef\uff0c\u7232\u4e86\u907f\u514d\u6bcf\u6b21  get_context \u548c put_context \u90fd\u6703\u8abf\u6574\u5806\uff0c\u53ef\u4ee5\u591a\u5b9a\u7fa9\u4e00\u500b adjust \u5c6c\u6027\u53ea\u6709\u7576 io_context \u8b8a\u5316\u6578\u8d85\u904e adjust \u6642\u624d\u91cd\u65b0\u8abf\u6574\u5806\uff0c\u5b8c\u6574\u4ee3\u78bc\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#ifndef __CONTEXT__CONTEXT_SHARED_WORK_HPP__\n#define __CONTEXT__CONTEXT_SHARED_WORK_HPP__\n#include \"basic.hpp\"\n#include &lt;thread&gt;\n#include &lt;container\/heap.hpp&gt;\nnamespace king011::context\n{\n    class priority_type\n    {\n    public:\n        std::size_t id;\n        std::size_t index;\n        std::size_t work;\n        priority_type(std::size_t id = 0, std::size_t index = 0, std::size_t work = 0)\n            : id(id),\n              index(index),\n              work(work) {}\n    };\n    class priority_wrapper\n    {\n    public:\n        priority_type *impl;\n        priority_wrapper(priority_type *impl = nullptr)\n            : impl(impl) {}\n\n        \/\/ \u91cd\u8f09\u6bd4\u8f03\n        bool operator&lt;(const priority_wrapper &amp;o) const noexcept\n        {\n            return impl-&gt;work &lt; o.impl-&gt;work;\n        }\n        void swap(priority_wrapper &amp;o) noexcept\n        {\n            std::swap(impl, o.impl);\n            std::swap(impl-&gt;index, o.impl-&gt;index);\n        }\n    };\n\n    template &lt;typename Mutex = std::mutex&gt;\n    class shared_work_context_t final : public basic_context_t\n    {\n    public:\n        typedef Mutex mutex_type;\n\n    private:\n        typedef std::promise&lt;boost::system::error_code&gt; promise_type;\n        typedef std::shared_future&lt;boost::system::error_code&gt; future_type;\n        typedef std::pair&lt;std::shared_ptr&lt;promise_type&gt;, future_type&gt; completer_type;\n        \/\/ \u57f7\u884c\u4e0a\u4e0b\u6587\n        std::vector&lt;context_type&gt; contexts_;\n        \/\/ \u9632\u6b62 io_context \u7a7a\u9592\u9000\u51fa\n        std::vector&lt;context_type::work&gt; works_;\n        completer_type completer_;\n        \/\/ \u540c\u6b65\u5c0d\u8c61\n        mutex_type mutex_;\n        \/\/ \u968a\u5217\u7d22\u5f15\n        std::vector&lt;priority_type&gt; keys_;\n        \/\/ \u512a\u5148\u968a\u5217\n        king011::container::heap_t&lt;priority_wrapper&gt; priority_;\n        \/\/ \u5118\u91cf\u907f\u514d \u968a\u5217\u6392\u5e8f\u7684 \u8abf\u6574\u503c\n        std::size_t adjust_;\n\n    public:\n        explicit shared_work_context_t(std::size_t concurrency = std::thread::hardware_concurrency(), std::size_t adjust = 50)\n            : adjust_(adjust)\n        {\n            if (concurrency &lt; 1)\n            {\n                throw std::length_error(\"concurrency should be &gt; 0\");\n            }\n            contexts_ = std::move(std::vector&lt;context_type&gt;(concurrency));\n            for (std::size_t i = 0; i &lt; concurrency; i++)\n            {\n                keys_.emplace_back(i, i);\n            }\n            auto data = keys_.data();\n            for (size_t i = 0; i &lt; concurrency; i++)\n            {\n                priority_.array.emplace_back(data + i);\n            }\n        }\n        shared_work_context_t(const shared_work_context_t &amp;) = delete;\n        shared_work_context_t *operator=(const shared_work_context_t &amp;) = delete;\n        virtual ~shared_work_context_t()\n        {\n            stop();\n        }\n        virtual pair_type get_context() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            auto elem = priority_.top().impl;\n            auto id = elem-&gt;id;\n            elem-&gt;work++;\n            if (adjust_ &lt; 2 || elem-&gt;work % adjust_ == 0)\n            {\n                auto index = elem-&gt;index;\n                priority_.fix(index);\n            }\n            return pair_type(id, contexts_&#91;id]);\n        }\n        virtual std::vector&lt;pair_type&gt; get_contexts() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            std::vector&lt;pair_type&gt; result;\n            for (auto &amp;node : keys_)\n            {\n                node.work++;\n                result.emplace_back(node.id, contexts_&#91;node.id]);\n            }\n            if (adjust_ &gt; 2)\n            {\n                priority_.init();\n            }\n            return std::move(result);\n        }\n        virtual void put_context(std::size_t id) override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            auto &amp;elem = keys_&#91;id];\n#ifdef __CONTEXT__CONTEXT_SHARED_WORK_TEST__\n            if (elem.id != id)\n            {\n                throw std::runtime_error(\"put_context error: id not match\");\n            }\n            auto index = elem.index;\n            auto impl = (priority_&#91;index]).impl;\n            if (impl-&gt;index != index)\n            {\n                throw std::runtime_error(\"put_context error: index not match\");\n            }\n            else if (impl-&gt;id != id)\n            {\n                throw std::runtime_error(\"put_context error: id2 not match\");\n            }\n#endif \/\/ __CONTEXT__CONTEXT_SHARED_WORK_TEST__\n            if (elem.work &gt; 0)\n            {\n                elem.work--;\n                if (adjust_ &lt; 2 || elem.work % adjust_ == 0)\n                {\n                    auto index = elem.index;\n                    priority_.fix(index);\n                }\n            }\n            else\n            {\n                throw std::runtime_error(\"put_context error: elem's work is 0\");\n            }\n        }\n        virtual void run() override\n        {\n            completer_type completer;\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer_.first)\n                {\n                    completer = completer_;\n                }\n                else\n                {\n                    auto promise = std::make_shared&lt;promise_type&gt;();\n                    completer = std::make_pair(promise, promise-&gt;get_future().share());\n                    completer_ = completer;\n                    auto count = contexts_.size();\n                    for (size_t i = 0; i &lt; count; i++)\n                    {\n                        works_.emplace_back(contexts_&#91;i]);\n                    }\n                    std::thread(&#91;\n#ifdef __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n                                    self = this,\n#endif \/\/__CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n                                    promise, &amp;contexts = contexts_]\n                                {\n                                    std::vector&lt;std::thread&gt; threads;\n                                    auto count = contexts.size();\n                                    for (size_t i = 1; i &lt; count; i++)\n                                    {\n                                        threads.emplace_back(&#91;&amp;context = contexts&#91;i]]\n                                                             {\n                                                                 boost::system::error_code ec;\n                                                                 context.run(ec);\n                                                             });\n                                    }\n#ifdef __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n                                    std::atomic_bool trace = true;\n                                    std::thread thread(&#91;&amp;trace, &amp;keys = self-&gt;keys_, &amp;mutex = self-&gt;mutex_]\n                                                       {\n                                                           while (trace)\n                                                           {\n                                                               std::this_thread::sleep_for(std::chrono::seconds(1));\n                                                               mutex.lock();\n                                                               for (auto &amp;node : keys)\n                                                               {\n                                                                   std::cout &lt;&lt; \"id=\" &lt;&lt; node.id &lt;&lt; \" index=\" &lt;&lt; node.index &lt;&lt; \" work=\" &lt;&lt; node.work &lt;&lt; \"\\n\";\n                                                               }\n                                                               std::cout &lt;&lt; std::endl;\n                                                               mutex.unlock();\n                                                           }\n                                                       });\n#endif \/\/ __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n\n                                    boost::system::error_code ec;\n                                    contexts&#91;0].run(ec);\n                                    for (auto &amp;thread : threads)\n                                    {\n                                        thread.join();\n                                    }\n#ifdef __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n                                    trace = false;\n                                    thread.join();\n#endif \/\/ __CONTEXT__CONTEXT_SHARED_WORK_TRACE__\n                                    promise-&gt;set_value(ec);\n                                })\n                        .detach();\n                }\n            }\n            \/\/ \u7b49\u5f85\u5b8c\u6210\n            auto ec = completer.second.get();\n            {\n                std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n                if (completer.first == completer_.first)\n                {\n                    completer_.first.reset();\n                }\n            }\n            if (ec)\n            {\n                throw boost::system::system_error(ec);\n            }\n        }\n        virtual void stop() override\n        {\n            std::lock_guard&lt;mutex_type&gt; lock(mutex_);\n            for (auto &amp;context : contexts_)\n            {\n                context.stop();\n            }\n            works_.clear();\n        }\n    };\n};\nnamespace std\n{\n    \/\/ \u7279\u5316 swap\n    template &lt;&gt;\n    void swap&lt;king011::context::priority_wrapper&gt;(king011::context::priority_wrapper &amp;a, king011::context::priority_wrapper &amp;b)\n    {\n        a.swap(b);\n    }\n};\n#endif \/\/ __CONTEXT__CONTEXT_SHARED_WORK_HPP__<\/code><\/pre>\n\n\n\n<p>\u7136\u800c shared_work_context_t \u53ea\u662f\u5e73\u8861\u4e86\u6bcf\u500b io_context \u95dc\u806f\u7684\u7570\u6b65\u5c0d\u8c61\u6578\u91cf\uff0c\u5373\u5e73\u8861\u4e86\u6bcf\u500b\u5de5\u4f5c\u7dda\u7a0b\u95dc\u806f\u7684\u7570\u6b65\u5c0d\u8c61\u6578\u91cf\uff0c\u5982\u679c\u67d0\u4e9b\u7570\u6b65\u5c0d\u8c61\u7684\u7570\u6b65\u4e8b\u4ef6\u5f88\u983b\u7e41\u800c\u53e6\u5916\u4e00\u4e9b\u5c0d\u8c61\u9577\u671f\u9592\u7f6e\u4f9d\u7136\u6703\u5c0e\u81f4\u67d0\u4e9b\u7dda\u7a0b\u7e41\u5fd9\u53e6\u5916\u4e00\u4e9b\u7a7a\u9592\uff0c\u4f46\u9019\u4e0d\u662f\u901a\u5e38\u60c5\u6cc1\uff0c\u5927\u90e8\u5206\u9700\u8981\u9ad8\u6548\u7684\u7e41\u5fd9\u670d\u52d9\u5668\u7570\u6b65\u4e8b\u4ef6\u548c\u7570\u6b65\u5c0d\u8c61\u662f\u6210\u7232\u6b63\u6bd4\u7684\uff0c\u5982\u679c\u9700\u8981\u5e73\u8861\u7570\u6b65\u4e8b\u4ef6\u800c\u975e\u5e73\u8861\u7570\u6b65\u5c0d\u8c61\u53ef\u4ee5\u4f7f\u7528 threads_context_t \u7684\u5be6\u73fe\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"> \u7e3d\u7d50<\/h2>\n\n\n\n<p>\u901a\u5e38\u4e0a\u8ff0\u4e09\u7a2e\u5be6\u73fe\u90fd\u53ef\u4ee5\u5f88\u597d\u4e26\u4e14\u9ad8\u6548\u7684\u5de5\u4f5c\uff0c\u9664\u975e\u6709\u7279\u6b8a\u9700\u6c42\u5426\u5247\u4efb\u9078\u4e00\u500b\u5373\u53ef<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>\u5982\u679c\u9700\u8981\u5de5\u4f5c\u7dda\u7a0b\u9593\u7684 \u7570\u6b65\u4e8b\u4ef6 \u80fd\u5920\u5e73\u8861 \u61c9\u8a72\u9078\u7528 threads_context_t<\/li><li>\u7570\u6b65\u5c0d\u8c61\u751f\u547d\u671f \u5dee\u4e0d\u591a \u9700\u8981\u5118\u53ef\u80fd\u9ad8\u6548\u5229\u7528 asio \u61c9\u8a72\u9078\u7528 round_robin_context_t<\/li><li>\u7570\u6b65\u5c0d\u8c61\u751f\u547d\u671f\u9577\u77ed\u4e0d\u4e00 \u540c\u6642\u9700\u8981\u5118\u53ef\u80fd\u9ad8\u6548\u5229\u7528 asio \u61c9\u8a72\u9078\u7528 shared_work_context_t<\/li><\/ol>\n","protected":false},"excerpt":{"rendered":"<p>asio multithreading mode<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[37,36,2],"tags":[39,38,40,41,42],"class_list":["post-192","post","type-post","status-publish","format-standard","hentry","category-boost","category-cc","category-code","tag-asio","tag-boost","tag-c","tag-cc","tag-42"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/192","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=192"}],"version-history":[{"count":21,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/192\/revisions"}],"predecessor-version":[{"id":214,"href":"https:\/\/blog.king011.com\/index.php?rest_route=\/wp\/v2\/posts\/192\/revisions\/214"}],"wp:attachment":[{"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=192"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.king011.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}