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}