Commit 30780732e4e02d172de74c7fb5d6f089cc97ed06

Authored by Grzegorz Jabłoński
1 parent 7603e01a

Second multithreaded version

Showing 1 changed file with 128 additions and 0 deletions
14-daytime9.cpp 0 → 100644
  1 +//
  2 +// server.cpp
  3 +// ~~~~~~~~~~
  4 +//
  5 +// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6 +//
  7 +// Distributed under the Boost Software License, Version 1.0. (See accompanying
  8 +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9 +//
  10 +
  11 +#include <asio.hpp>
  12 +#include <ctime>
  13 +#include <iostream>
  14 +#include <string>
  15 +
  16 +using asio::ip::tcp;
  17 +
  18 +std::string make_daytime_string() {
  19 + using namespace std; // For time_t, time and ctime;
  20 + time_t now = time(0);
  21 +
  22 + sleep(5);
  23 +
  24 + char buf[26];
  25 + return ctime_r(&now, buf);
  26 +}
  27 +
  28 +class tcp_connection : public std::enable_shared_from_this<tcp_connection> {
  29 +public:
  30 + typedef std::shared_ptr<tcp_connection> pointer;
  31 +
  32 + static pointer create(asio::io_context &io_context) {
  33 + return pointer(new tcp_connection(io_context));
  34 + }
  35 +
  36 + tcp::socket &socket() { return socket_; }
  37 +
  38 + void start() {
  39 + auto thread = std::thread(std::bind(&tcp_connection::long_operation, shared_from_this()));
  40 + thread.detach();
  41 + }
  42 +
  43 + ~tcp_connection()
  44 + {
  45 + std::cout << "~tcp_connection()" << std::endl;
  46 + }
  47 +private:
  48 + tcp_connection(asio::io_context &io_context) : socket_(io_context) {}
  49 +
  50 + void handle_write(const asio::error_code &error, size_t bytes_transferred) {
  51 + std::cout << error.category().name() << " : " << error.value() << " : "
  52 + << error.message() << std::endl;
  53 + if (error)
  54 + std::cout << "Error" << std::endl;
  55 + else
  56 + std::cout << "Written " << bytes_transferred << " bytes" << std::endl;
  57 + }
  58 +
  59 + void long_operation()
  60 + {
  61 + message_ = make_daytime_string();
  62 + asio::async_write(socket_, asio::buffer(message_),
  63 + std::bind(&tcp_connection::handle_write, shared_from_this(),
  64 + std::placeholders::_1, std::placeholders::_2));
  65 + }
  66 +
  67 + tcp::socket socket_;
  68 + std::string message_;
  69 +};
  70 +
  71 +class tcp_server {
  72 +public:
  73 + tcp_server(asio::io_context &io_context)
  74 + : io_context_(io_context),
  75 + acceptor_(io_context, tcp::endpoint(tcp::v4(), 13)) {
  76 + start_accept();
  77 + }
  78 +
  79 +private:
  80 + void start_accept() {
  81 + tcp_connection::pointer new_connection =
  82 + tcp_connection::create(io_context_);
  83 +
  84 + acceptor_.async_accept(new_connection->socket(),
  85 + std::bind(&tcp_server::handle_accept, this,
  86 + new_connection, std::placeholders::_1));
  87 + }
  88 +
  89 + void handle_accept(tcp_connection::pointer new_connection,
  90 + const asio::error_code &error) {
  91 + if (!error) {
  92 + io_context_.post(std::bind(&tcp_connection::start, new_connection));
  93 + }
  94 + start_accept();
  95 + }
  96 +
  97 + asio::io_context &io_context_;
  98 + tcp::acceptor acceptor_;
  99 +};
  100 +
  101 +int main() {
  102 + try {
  103 + asio::io_context io_context;
  104 +
  105 + asio::executor_work_guard work_guard(io_context.get_executor()); //prevent run() from exiting immediately after all work is done
  106 +
  107 + std::vector<std::thread> threads;
  108 +
  109 + for (int i = 0; i < 1; i++)
  110 + threads.emplace_back([&io_context]{io_context.run();});
  111 +
  112 + tcp_server server(io_context);
  113 +
  114 + std::cout << "Press ENTER key to exit!" << std::endl;
  115 +
  116 + std::cin.get();
  117 +
  118 + io_context.stop();
  119 +
  120 + for (auto &i : threads)
  121 + i.join();
  122 +
  123 + } catch (std::exception &e) {
  124 + std::cerr << e.what() << std::endl;
  125 + }
  126 +
  127 + return 0;
  128 +}
... ...