1

Objects of Data_t are sent via a TCP socket to a server. The server creates a ConnectionHandler object to handle each incoming connection.

In ConnectionHandler, Data_t objects are read one by one using async_read from the socket, and their num_ fields are summed up then saved to a field ConnectionHandler::total_sum_.

Do I need to lock ConnectionHandler::total_sum_ since multiple threads will write to it?

See the code below. Please note that

ConnectinHandler::received_data_ is re-used as a buffer to hold Data_t objects read from the socket. Is it safe to do so?

ConnectinHandler::process_data() processes a Data_t object first then call ConnectinHandler::read_pack() to read from the socket again.

struct Data_t
{
   int num_;
   //... some other data
}

template<typename ConnectionHandler>
class Server {
    using shared_handler_t = std::shared_ptr<ConnectionHandler>;
public:
    Server(int thread_count = 10) :
            thread_count_(thread_count), acceptor_(io_service_)
    void
    start_server(uint16_t port) {
        auto handler = std::make_shared<ConnectionHandler>(io_service_, configer_, thread_names_);
        // set up the acceptor to listen on the tcp port
        boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
        acceptor_.open(endpoint.protocol());
        boost::system::error_code ec;
        acceptor_.bind(endpoint);
        acceptor_.listen();
        acceptor_.async_accept(handler->socket(),
                               [=](boost::system::error_code const &ec) {
                                   handle_new_connection(handler, ec);
                               }); 
        // start pool of threads to process the asio events
        for (int i = 0; i < thread_count_; ++i) {
            thread_pool_.emplace_back([=] { io_service_.run(); });
        }
        // Wait for all threads in the pool to exit.
        for (std::size_t i = 0; i < thread_pool_.size(); ++i) {
            thread_pool_[i].join();
        }
    }
private:
    void
    handle_new_connection(shared_handler_t handler,
                          boost::system::error_code const &error) {
        if (error) {
            return;
        }
        handler->start();
        auto new_handler = std::make_shared<ConnectionHandler>(io_service_);
        acceptor_.async_accept(new_handler->socket(),
                               [=](boost::system::error_code const &ec) {
                                   handle_new_connection(new_handler, ec);
                               });
    }
    int thread_count_;
    std::vector<std::thread> thread_pool_;
    boost::asio::io_service io_service_;
    boost::asio::ip::tcp::acceptor acceptor_;
};


class ConnectionHandler : public std::enable_shared_from_this<ConnectionHandler> {
 public:
  ConnectionHandler (boost::asio::io_service &service) :
      service_ (service), socket_ (service)
  {
  }
  void
  start ()
  {
    read_packet ();
  }

 private:
  void
  read_packet ()
  {
    auto me = shared_from_this ();
    boost::asio::async_read (
        socket_, boost::asio::buffer (&received_data_, sizeof (Data_t)),
        boost::asio::transfer_exactly (sizeof (Data_t)),
        [me] (boost::system::error_code const &ec, std::size_t bytes_xfer)
        {
            me->process_data (ec, bytes_xfer);
        });

  }
  void
  process_data (boost::system::error_code const &error,
                    std::size_t bytes_transferred)
  {
    if (error)
      {
        socket_.close ();
        return;
      }
    total_sum_+=received_data_.num_;
    read_packet ();
  }
  boost::asio::io_service &service_;
  boost::asio::ip::tcp::socket socket_;
  Data_t received_data_;
  int total_sum_;
};
user3839198
  • 115
  • 1
  • 10
  • 2
    I can't see anyway for `ConnectionHandler ::total_sum_` to be accessed from multiple threads. It might be accessed from different threads but it will only be accessed by a single thread at a time? – Alan Birtles May 29 '18 at 14:25
  • That is what I think. Not 100% sure though. – user3839198 May 29 '18 at 14:26
  • See https://stackoverflow.com/questions/12794107/why-do-i-need-strand-per-connection-when-using-boostasio/12801042#12801042 – sehe May 29 '18 at 14:30

0 Answers0