c++ - how to do boost::asio::spawn with io_service-per-CPU? -


my server based on boost spawn echo server.

the server runs fine on single-core machine, not 1 crash several months. when takes 100% cpu still works fine.

but need handle more client requests, use multi-core machine. use cpus run io_service on several thread, this:

#include <boost/asio/io_service.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/spawn.hpp> #include <boost/asio/steady_timer.hpp> #include <boost/asio/write.hpp> #include <boost/thread/thread.hpp> #include <iostream> #include <memory> #include <thread> using namespace std;  using boost::asio::ip::tcp;  class session : public std::enable_shared_from_this<session>{ public:     explicit session(tcp::socket socket)         : socket_(std::move(socket)),         timer_(socket_.get_io_service()),         strand_(socket_.get_io_service())     {}      void go()     {         auto self(shared_from_this());         boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield)         {            try {                char data[1024] = {'3'};                for( ; ;) {                    timer_.expires_from_now(std::chrono::seconds(10));                    std::size_t n = socket_.async_read_some(boost::asio::buffer(data, sizeof(data)), yield);                    // data                    // write                    boost::asio::async_write(socket_, boost::asio::buffer(data, sizeof(data)), yield);                }            } catch(...)   {                socket_.close();                timer_.cancel();            }         });          boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield)         {            while(socket_.is_open()) {                boost::system::error_code ignored_ec;                timer_.async_wait(yield[ignored_ec]);                if(timer_.expires_from_now() <= std::chrono::seconds(0))                    socket_.close();            }         });     }  private:     tcp::socket socket_;     boost::asio::steady_timer timer_;     boost::asio::io_service::strand strand_; };  int main(int argc, char* argv[]) {     try {          boost::asio::io_service io_service;          boost::asio::spawn(io_service, [&](boost::asio::yield_context yield)         {             tcp::acceptor acceptor(io_service, #define port "7788"             tcp::endpoint(tcp::v4(), std::atoi(port)));              for( ; ;) {                 boost::system::error_code ec;                 tcp::socket socket(io_service);                 acceptor.async_accept(socket, yield[ec]);                 if(!ec)                     // std::make_shared<session>(std::move(socket))->go();                     io_service.post(boost::bind(&session::go, std::make_shared<session>(std::move(socket))));             }         });          // ----------- works fine on single-core machine ------------         {             // io_service.run();         }          // ----------- crashes (with multi core) ----------         {             auto thread_count = std::thread::hardware_concurrency(); // multi core             boost::thread_group threads;             for(auto = 0; < thread_count; ++i)                 threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));              threads.join_all();         }      } catch(std::exception& e) {         std::cerr << "exception: " << e.what() << "\n";     }      return 0; } 

the code works fine on single-core maching, crashes time on 2-core/4-core/8-core machine. crash dump don't see related code, boost::spawn , randomly named lambda.

so want try this: run io_service per cpu.

i found demo, uses async function:

void server::start_accept() {   new_connection_.reset(new connection(         io_service_pool_.get_io_service(), request_handler_));   acceptor_.async_accept(new_connection_->socket(),       boost::bind(&server::handle_accept, this,         boost::asio::placeholders::error)); }  void server::handle_accept(const boost::system::error_code& e) {   if (!e)   {     new_connection_->start();   }    start_accept(); } 

the io_service_pool_.get_io_service() randomly pickup io_service, code uses spawn

boost::asio::spawn(io_service, ... 

how spawn random io_service?

seems asking wrong question, spawn cannot work multiple io_service, socket can. modified code this:

int main(int argc, char* argv[]) {     try {          boost::asio::io_service io_service;         boost::asio::io_service::work work(io_service);          auto core_count = std::thread::hardware_concurrency();         // io_service_pool.hpp , io_service_pool.cpp boost's example         io_service_pool pool(core_count);          boost::asio::spawn(io_service, [&](boost::asio::yield_context yield)         { #define port "7788"             tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), std::atoi(port)));              for( ; ;) {                 boost::system::error_code ec;                 boost::asio::io_service& ios = pool.get_io_service();                 tcp::socket socket(ios);                 acceptor.async_accept(socket, yield[ec]);                 if(!ec)                     ios.post(boost::bind(&session::go, std::make_shared<session>(std::move(socket))));             }         });          { // run io_service             thread t([&] { pool.run(); });             t.detach();              io_service.run();         }      } catch(std::exception& e) {         std::cerr << "exception: " << e.what() << "\n";     }      return 0; } 

now server doesn't crash anymore. still have no idea cause crash if use single io_service threads.


Comments

Popular posts from this blog

javascript - Clear button on addentry page doesn't work -

c# - Selenium Authentication Popup preventing driver close or quit -

tensorflow when input_data MNIST_data , zlib.error: Error -3 while decompressing: invalid block type -