Hello

https://think-async.com/Asio/asio-1.24.0/doc/asio/tutorial/tuttimer1.html

./code/Makefile
 1CXXFLAGS := -I /ceph-fj/fangjun/software/asio/include -pthread
 2
 3srcs := $(shell find . -type f -name "*.cc" -printf "%f ")
 4targets :=$(srcs:%.cc=%)
 5
 6all: $(targets)
 7
 8%: %.cc
 9	$(CXX) $(CXXFLAGS) -o $@ $<
10
11
12.PHONY: clean
13clean:
14	$(RM) $(targets)
./code/1-timer-synchronous.cc
 1#include "asio.hpp"
 2#include <iostream>
 3
 4int main() {
 5  asio::io_context io;
 6  std::cout << "sleep for 1 second\n";
 7  asio::steady_timer t(io, asio::chrono::seconds(1));
 8  t.wait();
 9  std::cout << "hello world\n";
10  return 0;
11}
./code/2-timer-asynchronous.cc
 1#include "asio.hpp"
 2#include <iostream>
 3
 4void print(const asio::error_code &) { std::cout << "done\n"; }
 5
 6int main() {
 7  asio::io_context io;
 8  std::cout << "sleep for 1 seconds\n";
 9  asio::steady_timer t(io, asio::chrono::seconds(1));
10
11  t.async_wait(&print);
12  t.async_wait(&print);
13  io.run();
14  return 0;
15}
./code/3-timer-async-bind-argument.cc
 1#include "asio.hpp"
 2#include <iostream>
 3
 4void print(const asio::error_code &ec, asio::steady_timer *t, int *counter) {
 5  if (*counter < 3) {
 6    std::cout << *counter << "\n";
 7    *counter += 1;
 8    t->expires_at(t->expiry() + asio::chrono::seconds(1));
 9    t->async_wait(
10        [t, counter](const asio::error_code &e) { print(e, t, counter); });
11  }
12}
13
14int main() {
15  asio::io_context io;
16  asio::steady_timer t(io, asio::chrono::seconds(1));
17  int counter = 0;
18
19  // use a lambda to pass extra parameters
20  t.async_wait(
21      [&t, &counter](const asio::error_code &ec) { print(ec, &t, &counter); });
22  io.run();
23  return 0;
24}
./code/4-timer-async-member-function.cc
 1#include "asio.hpp"
 2#include <iostream>
 3
 4class printer {
 5public:
 6  printer(asio::io_context &io)
 7      : t_(io, asio::chrono::seconds(1)), counter_(0) {
 8    t_.async_wait([this](const asio::error_code &ec) { print(ec); });
 9  }
10
11  void print(const asio::error_code &ec) {
12    if (counter_ < 6) {
13      std::cout << counter_ << "\n";
14      counter_ += 1;
15      t_.async_wait([this](const asio::error_code &e) { this->print(e); });
16    }
17  }
18
19private:
20  asio::steady_timer t_;
21  int counter_;
22};
23int main() {
24  asio::io_context io;
25  printer p(io);
26  io.run();
27  return 0;
28}
./code/5-timer-async-thread-non-synchronization.cc
 1#include "asio.hpp"
 2#include <iostream>
 3#include <thread>
 4
 5class printer {
 6public:
 7  printer(asio::io_context &io)
 8      : t1_(io, asio::chrono::seconds(1)), t2_(io, asio::chrono::seconds(1)) {
 9    t1_.async_wait([this](const asio::error_code &e) { print1(e); });
10    t2_.async_wait([this](const asio::error_code &e) { print2(e); });
11  }
12
13  void print1(const asio::error_code &ec) {
14    if (counter_ < 8) {
15      std::cout << "print1 id: " << std::this_thread::get_id() << ", counter "
16                << counter_ << "\n";
17      counter_ += 1;
18      t1_.expires_at(t1_.expiry() + asio::chrono::seconds(1));
19      t1_.async_wait([this](const asio::error_code &e) { print1(e); });
20    }
21  }
22
23  void print2(const asio::error_code &ec) {
24    if (counter_ < 8) {
25      std::cout << "print2 id: " << std::this_thread::get_id() << ", counter "
26                << counter_ << "\n";
27      counter_ += 1;
28      t2_.expires_at(t2_.expiry() + asio::chrono::seconds(1));
29      t2_.async_wait([this](const asio::error_code &e) { print2(e); });
30    }
31  }
32
33private:
34  asio::steady_timer t1_;
35  asio::steady_timer t2_;
36  int counter_ = 0;
37};
38
39int main() {
40  asio::io_context io;
41  printer p(io);
42  std::thread t([&io]() { io.run(); }); // NOTE: print1() and print2() can run
43                                        // either in t or in the main thread
44  io.run();
45  t.join();
46}
47
48#if 0
49(py38) kuangfangjun:code$ ./5-timer-async-thread-non-synchronization
50print1 id: print2 id: 140164266059584, counter 0
51140164247860992, counter 1
52print1 id: 140164266059584, counter 2
53print2 id: 140164247860992, counter 3
54print1 id: 140164266059584, counter 4
55print2 id: 140164247860992, counter 5
56print1 id: 140164266059584, counter 6
57print2 id: 140164247860992, counter 7
58(py38) kuangfangjun:code$ ./5-timer-async-thread-non-synchronization
59print2 id: print1 id: 140191018206976, counter 140191036405568, counter 0
600
61print1 id: 140191018206976, counter print2 id: 2
62140191036405568, counter 3
63print1 id: 140191018206976, counter 4
64print2 id: 140191036405568, counter 5
65print1 id: 140191018206976, counter 6
66print2 id: 140191036405568, counter 7
67#endif
./code/6-timer-async-thread-with-synchronization.cc
 1#include "asio.hpp"
 2#include <iostream>
 3#include <thread>
 4
 5class printer {
 6public:
 7  printer(asio::io_context &io)
 8      : strand_(asio::make_strand(io)), t1_(io, asio::chrono::seconds(1)),
 9        t2_(io, asio::chrono::seconds(1)) {
10    t1_.async_wait(asio::bind_executor(
11        strand_, [this](const asio::error_code &e) { print1(e); }));
12    t2_.async_wait(asio::bind_executor(
13        strand_, [this](const asio::error_code &e) { print2(e); }));
14  }
15
16  void print1(const asio::error_code &ec) {
17    if (counter_ < 8) {
18      std::cout << "print1 id: " << std::this_thread::get_id() << ", counter "
19                << counter_ << "\n";
20      counter_ += 1;
21      t1_.expires_at(t1_.expiry() + asio::chrono::seconds(1));
22      t1_.async_wait([this](const asio::error_code &e) { print1(e); });
23    }
24  }
25
26  void print2(const asio::error_code &ec) {
27    if (counter_ < 8) {
28      std::cout << "print2 id: " << std::this_thread::get_id() << ", counter "
29                << counter_ << "\n";
30      counter_ += 1;
31      t2_.expires_at(t2_.expiry() + asio::chrono::seconds(1));
32      t2_.async_wait([this](const asio::error_code &e) { print2(e); });
33    }
34  }
35
36private:
37  asio::strand<asio::io_context::executor_type> strand_;
38  asio::steady_timer t1_;
39  asio::steady_timer t2_;
40  int counter_ = 0;
41};
42
43int main() {
44  asio::io_context io;
45  printer p(io);
46  std::thread t([&io]() { io.run(); }); // NOTE: print1() and print2() can run
47                                        // either in t or in the main thread
48  io.run();
49  t.join();
50}
51#if 0
52(py38) kuangfangjun:code$ ./6-timer-async-thread-with-synchronization
53print1 id: 140648598263616, counter 0
54print2 id: 140648598263616, counter 1
55print1 id: 140648580065024, counter 2
56print2 id: 140648598263616, counter 3
57print1 id: 140648580065024, counter 4
58print2 id: 140648598263616, counter 5
59print1 id: 140648580065024, counter 6
60print2 id: 140648598263616, counter 7
61(py38) kuangfangjun:code$ ./6-timer-async-thread-with-synchronization
62print1 id: 139671509145408, counter 0
63print2 id: 139671509145408, counter 1
64print1 id: 139671490946816, counter 2
65print2 id: 139671509145408, counter 3
66print1 id: 139671490946816, counter 4
67print2 id: 139671509145408, counter 5
68print1 id: 139671490946816, counter 6
69print2 id: 139671509145408, counter 7
70#endif
./code/7-daytime-sync-client.cc
 1#include "asio.hpp"
 2#include <array>
 3#include <iostream>
 4
 5using asio::ip::tcp;
 6int main(int argc, char *argv[]) {
 7  try {
 8    if (argc != 2) {
 9      std::cerr << "Usage: client <host>" << std::endl;
10      return 1;
11    }
12
13    asio::io_context io;
14    tcp::resolver resolver(io);
15
16    tcp::resolver::results_type endpoints =
17        resolver.resolve(argv[1], "daytime");
18
19    tcp::socket socket(io);
20    asio::connect(socket, endpoints);
21
22    for (;;) {
23      std::array<char, 128> buf;
24      asio::error_code ec;
25      size_t len = socket.read_some(asio::buffer(buf), ec);
26      if (ec == asio::error::eof) {
27        break;
28      } else if (ec) {
29        throw asio::system_error(ec);
30      }
31      std::cout.write(buf.data(), len);
32    }
33  } catch (std::exception &e) {
34    std::cerr << "exception: " << e.what() << "\n";
35  }
36  return 0;
37}
./code/8-daytime-sync-server.cc
 1#include "asio.hpp"
 2#include <ctime>
 3#include <iostream>
 4#include <string>
 5
 6using asio::ip::tcp;
 7std::string make_daytime_string() {
 8  using namespace std;
 9  time_t now = time(0);
10  return ctime(&now);
11}
12
13int main() {
14  try {
15    asio::io_context io;
16    // need sudo permission to bind port 13
17    tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 13));
18    std::cout << "started\n";
19    for (;;) {
20      tcp::socket socket(io);
21      acceptor.accept(socket);
22
23      auto message = make_daytime_string();
24      asio::error_code ec;
25      asio::write(socket, asio::buffer(message), ec);
26    }
27  } catch (std::exception &e) {
28    std::cout << "Exception: " << e.what() << "\n";
29  }
30  return 0;
31}
./code/9-daytime-async-server.cc
 1#include "asio.hpp"
 2#include <ctime>
 3#include <iostream>
 4#include <memory>
 5
 6using asio::ip::tcp;
 7
 8std::string make_daytime_string() {
 9  using namespace std;
10  time_t now = time(0);
11  return ctime(&now);
12}
13
14class tcp_connection : public std::enable_shared_from_this<tcp_connection> {
15public:
16  using pointer = std::shared_ptr<tcp_connection>;
17
18  static pointer create(asio::io_context &io) {
19    return pointer(new tcp_connection(io));
20    // return std::make_shared<tcp_connection>(io);
21  }
22
23  tcp::socket &socket() { return socket_; }
24
25  void start() {
26    message_ = make_daytime_string();
27    auto p = shared_from_this();
28    asio::async_write(
29        socket_, asio::buffer(message_),
30        [p](const asio::error_code &ec, size_t bytes_transferred) {
31          p->handle_write(ec, bytes_transferred);
32        });
33  }
34
35private:
36  tcp_connection(asio::io_context &io) : socket_(io) {}
37
38  void handle_write(const asio::error_code & /*ec*/,
39                    size_t /*bytes_transferred*/) {}
40
41  tcp::socket socket_;
42  std::string message_;
43};
44
45class tcp_server {
46public:
47  tcp_server(asio::io_context &io)
48      : io_(io), acceptor_(io, tcp::endpoint(tcp::v4(), 13)) {
49    start_accept();
50  }
51
52private:
53  void start_accept() {
54    tcp_connection::pointer new_connection = tcp_connection::create(io_);
55    acceptor_.async_accept(new_connection->socket(),
56                           [this, new_connection](const asio::error_code &ec) {
57                             this->handle_accept(new_connection, ec);
58                           });
59  }
60  void handle_accept(tcp_connection::pointer new_connection,
61                     const asio::error_code &ec) {
62    if (!ec) {
63      new_connection->start();
64    }
65    start_accept();
66  }
67
68  asio::io_context &io_;
69  tcp::acceptor acceptor_;
70};
71
72int main() {
73  try {
74    asio::io_context io;
75    tcp_server server(io);
76    io.run();
77  } catch (std::exception &e) {
78    std::cout << "Exception: " << e.what();
79  }
80  return 0;
81}