Skip to content

Commit 9cf00d6

Browse files
committed
Adds cpp17 async example.
1 parent a00c9e7 commit 9cf00d6

15 files changed

+504
-686
lines changed

CMakeLists.txt

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -73,92 +73,100 @@ endif()
7373
# Executables
7474
#=======================================================================
7575

76-
add_executable(intro examples/intro.cpp)
77-
target_link_libraries(intro common)
78-
target_compile_features(intro PUBLIC cxx_std_20)
79-
add_test(intro intro)
76+
add_executable(cpp20_intro examples/cpp20_intro.cpp)
77+
target_link_libraries(cpp20_intro common)
78+
target_compile_features(cpp20_intro PUBLIC cxx_std_20)
79+
add_test(cpp20_intro cpp20_intro)
8080
if (MSVC)
81-
target_compile_options(intro PRIVATE /bigobj)
82-
target_compile_definitions(intro PRIVATE _WIN32_WINNT=0x0601)
81+
target_compile_options(cpp20_intro PRIVATE /bigobj)
82+
target_compile_definitions(cpp20_intro PRIVATE _WIN32_WINNT=0x0601)
8383
endif()
8484

85-
add_executable(intro_sync examples/intro_sync.cpp)
86-
target_compile_features(intro_sync PUBLIC cxx_std_20)
87-
add_test(intro_sync intro_sync)
88-
add_test(intro_sync intro_sync)
85+
add_executable(cpp17_intro examples/cpp17_intro.cpp)
86+
target_compile_features(cpp17_intro PUBLIC cxx_std_17)
87+
add_test(cpp17_intro cpp17_intro)
8988
if (MSVC)
90-
target_compile_options(intro_sync PRIVATE /bigobj)
91-
target_compile_definitions(intro_sync PRIVATE _WIN32_WINNT=0x0601)
89+
target_compile_options(cpp17_intro PRIVATE /bigobj)
90+
target_compile_definitions(cpp17_intro PRIVATE _WIN32_WINNT=0x0601)
9291
endif()
9392

94-
add_executable(chat_room examples/chat_room.cpp)
95-
target_compile_features(chat_room PUBLIC cxx_std_20)
96-
target_link_libraries(chat_room common)
93+
add_executable(cpp17_intro_sync examples/cpp17_intro_sync.cpp)
94+
target_compile_features(cpp17_intro_sync PUBLIC cxx_std_17)
95+
add_test(cpp17_intro_sync cpp17_intro_sync)
96+
add_test(cpp17_intro_sync cpp17_intro_sync)
9797
if (MSVC)
98-
target_compile_options(chat_room PRIVATE /bigobj)
99-
target_compile_definitions(chat_room PRIVATE _WIN32_WINNT=0x0601)
98+
target_compile_options(cpp17_intro_sync PRIVATE /bigobj)
99+
target_compile_definitions(cpp17_intro_sync PRIVATE _WIN32_WINNT=0x0601)
100100
endif()
101101

102-
add_executable(containers examples/containers.cpp)
103-
target_compile_features(containers PUBLIC cxx_std_20)
104-
target_link_libraries(containers common)
105-
add_test(containers containers)
102+
add_executable(cpp20_chat_room examples/cpp20_chat_room.cpp)
103+
target_compile_features(cpp20_chat_room PUBLIC cxx_std_20)
104+
target_link_libraries(cpp20_chat_room common)
106105
if (MSVC)
107-
target_compile_options(containers PRIVATE /bigobj)
108-
target_compile_definitions(containers PRIVATE _WIN32_WINNT=0x0601)
106+
target_compile_options(cpp20_chat_room PRIVATE /bigobj)
107+
target_compile_definitions(cpp20_chat_room PRIVATE _WIN32_WINNT=0x0601)
109108
endif()
110109

111-
add_executable(echo_server examples/echo_server.cpp)
112-
target_compile_features(echo_server PUBLIC cxx_std_20)
113-
target_link_libraries(echo_server common)
110+
add_executable(cpp20_containers examples/cpp20_containers.cpp)
111+
target_compile_features(cpp20_containers PUBLIC cxx_std_20)
112+
target_link_libraries(cpp20_containers common)
113+
add_test(cpp20_containers cpp20_containers)
114114
if (MSVC)
115-
target_compile_options(echo_server PRIVATE /bigobj)
116-
target_compile_definitions(echo_server PRIVATE _WIN32_WINNT=0x0601)
115+
target_compile_options(cpp20_containers PRIVATE /bigobj)
116+
target_compile_definitions(cpp20_containers PRIVATE _WIN32_WINNT=0x0601)
117117
endif()
118118

119-
add_executable(resolve_with_sentinel examples/resolve_with_sentinel.cpp)
120-
target_compile_features(resolve_with_sentinel PUBLIC cxx_std_20)
121-
target_link_libraries(resolve_with_sentinel common)
122-
#add_test(resolve_with_sentinel resolve_with_sentinel)
119+
add_executable(cpp20_echo_server examples/cpp20_echo_server.cpp)
120+
target_compile_features(cpp20_echo_server PUBLIC cxx_std_20)
121+
target_link_libraries(cpp20_echo_server common)
123122
if (MSVC)
124-
target_compile_options(resolve_with_sentinel PRIVATE /bigobj)
125-
target_compile_definitions(resolve_with_sentinel PRIVATE _WIN32_WINNT=0x0601)
123+
target_compile_options(cpp20_echo_server PRIVATE /bigobj)
124+
target_compile_definitions(cpp20_echo_server PRIVATE _WIN32_WINNT=0x0601)
126125
endif()
127126

128-
add_executable(serialization examples/serialization.cpp)
129-
target_compile_features(serialization PUBLIC cxx_std_20)
130-
target_link_libraries(serialization common)
131-
add_test(serialization serialization)
127+
add_executable(cpp20_resolve_with_sentinel examples/cpp20_resolve_with_sentinel.cpp)
128+
target_compile_features(cpp20_resolve_with_sentinel PUBLIC cxx_std_20)
129+
target_link_libraries(cpp20_resolve_with_sentinel common)
130+
#add_test(cpp20_resolve_with_sentinel cpp20_resolve_with_sentinel)
132131
if (MSVC)
133-
target_compile_options(serialization PRIVATE /bigobj)
134-
target_compile_definitions(serialization PRIVATE _WIN32_WINNT=0x0601)
132+
target_compile_options(cpp20_resolve_with_sentinel PRIVATE /bigobj)
133+
target_compile_definitions(cpp20_resolve_with_sentinel PRIVATE _WIN32_WINNT=0x0601)
135134
endif()
136135

137-
add_executable(subscriber examples/subscriber.cpp)
138-
target_compile_features(subscriber PUBLIC cxx_std_20)
139-
target_link_libraries(subscriber common)
136+
add_executable(cpp20_serialization examples/cpp20_serialization.cpp)
137+
target_compile_features(cpp20_serialization PUBLIC cxx_std_20)
138+
target_link_libraries(cpp20_serialization common)
139+
add_test(cpp20_serialization cpp20_serialization)
140140
if (MSVC)
141-
target_compile_options(subscriber PRIVATE /bigobj)
142-
target_compile_definitions(subscriber PRIVATE _WIN32_WINNT=0x0601)
141+
target_compile_options(cpp20_serialization PRIVATE /bigobj)
142+
target_compile_definitions(cpp20_serialization PRIVATE _WIN32_WINNT=0x0601)
143143
endif()
144144

145-
add_executable(intro_tls examples/intro_tls.cpp)
146-
target_compile_features(intro_tls PUBLIC cxx_std_20)
147-
add_test(intro_tls intro_tls)
148-
target_link_libraries(intro_tls OpenSSL::Crypto OpenSSL::SSL)
149-
target_link_libraries(intro_tls common)
145+
add_executable(cpp20_subscriber examples/cpp20_subscriber.cpp)
146+
target_compile_features(cpp20_subscriber PUBLIC cxx_std_20)
147+
target_link_libraries(cpp20_subscriber common)
150148
if (MSVC)
151-
target_compile_options(intro_tls PRIVATE /bigobj)
152-
target_compile_definitions(intro_tls PRIVATE _WIN32_WINNT=0x0601)
149+
target_compile_options(cpp20_subscriber PRIVATE /bigobj)
150+
target_compile_definitions(cpp20_subscriber PRIVATE _WIN32_WINNT=0x0601)
153151
endif()
154152

155-
add_executable(low_level_async examples/low_level_async.cpp)
156-
target_compile_features(low_level_async PUBLIC cxx_std_20)
157-
add_test(low_level_async low_level_async)
158-
target_link_libraries(low_level_async common)
153+
add_executable(cpp20_intro_tls examples/cpp20_intro_tls.cpp)
154+
target_compile_features(cpp20_intro_tls PUBLIC cxx_std_20)
155+
add_test(cpp20_intro_tls cpp20_intro_tls)
156+
target_link_libraries(cpp20_intro_tls OpenSSL::Crypto OpenSSL::SSL)
157+
target_link_libraries(cpp20_intro_tls common)
159158
if (MSVC)
160-
target_compile_options(low_level_async PRIVATE /bigobj)
161-
target_compile_definitions(low_level_async PRIVATE _WIN32_WINNT=0x0601)
159+
target_compile_options(cpp20_intro_tls PRIVATE /bigobj)
160+
target_compile_definitions(cpp20_intro_tls PRIVATE _WIN32_WINNT=0x0601)
161+
endif()
162+
163+
add_executable(cpp20_low_level_async examples/cpp20_low_level_async.cpp)
164+
target_compile_features(cpp20_low_level_async PUBLIC cxx_std_20)
165+
add_test(cpp20_low_level_async cpp20_low_level_async)
166+
target_link_libraries(cpp20_low_level_async common)
167+
if (MSVC)
168+
target_compile_options(cpp20_low_level_async PRIVATE /bigobj)
169+
target_compile_definitions(cpp20_low_level_async PRIVATE _WIN32_WINNT=0x0601)
162170
endif()
163171

164172
add_executable(echo_server_client benchmarks/cpp/asio/echo_server_client.cpp)
@@ -175,12 +183,12 @@ if (MSVC)
175183
target_compile_definitions(echo_server_direct PRIVATE _WIN32_WINNT=0x0601)
176184
endif()
177185

178-
add_executable(low_level_sync examples/low_level_sync.cpp)
179-
target_compile_features(low_level_sync PUBLIC cxx_std_17)
180-
add_test(low_level_sync low_level_sync)
186+
add_executable(cpp17_low_level_sync examples/cpp17_low_level_sync.cpp)
187+
target_compile_features(cpp17_low_level_sync PUBLIC cxx_std_17)
188+
add_test(cpp17_low_level_sync cpp17_low_level_sync)
181189
if (MSVC)
182-
target_compile_options(low_level_sync PRIVATE /bigobj)
183-
target_compile_definitions(low_level_sync PRIVATE _WIN32_WINNT=0x0601)
190+
target_compile_options(cpp17_low_level_sync PRIVATE /bigobj)
191+
target_compile_definitions(cpp17_low_level_sync PRIVATE _WIN32_WINNT=0x0601)
184192
endif()
185193

186194
add_executable(test_conn_exec tests/conn_exec.cpp)

README.md

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ the cases will be concerned with only three library entities
1515

1616
For example, the coroutine below uses a short-lived connection to read Redis
1717
[hashes](https://redis.io/docs/data-types/hashes/)
18-
in a `std::map` (see intro.cpp and containers.cpp)
18+
in a `std::map` (see cpp20_intro.cpp, cpp17_intro.cpp and containers.cpp)
1919

2020
```cpp
2121
auto async_main() -> net::awaitable<void>
@@ -51,30 +51,27 @@ completes, these functions play the following roles
5151
called from multiple places in your code concurrently.
5252
* `connection::async_run`: Coordinate low-level read and write
5353
operations. More specifically, it will hand IO control to
54-
`async_exec` when a response arrives and to
55-
`aedis::connection::async_receive` when a server-push is received.
56-
It will also trigger writes of pending requests when a reconnection
57-
occurs. It remains suspended until the connection is lost.
58-
59-
By carefully choosing the flags `aedis::resp3::request::config` users
60-
can also express their desire to not automatically cancel pending
61-
requests when the connection is lost, giving the opportunity to
62-
reconnect and call `async_run` again after a failover to trigger their
63-
execution, perhaps in another Redis instance. Before we approach
64-
long-lived connections in the next section users will find it helpful
65-
to skim over the examples
66-
67-
* intro.cpp: The Aedis hello-world program. Sends one command and quits the connection.
68-
* intro_tls.cpp: Same as intro.cpp but over TLS.
69-
* intro_sync.cpp: Shows how to use the connection class synchronously.
70-
* containers.cpp: Shows how to send and receive STL containers and how to use transactions.
71-
* serialization.cpp: Shows how to serialize types using Boost.Json.
72-
* resolve_with_sentinel.cpp: Shows how to resolve a master address using sentinels.
73-
* subscriber.cpp: Shows how to implement pubsub with reconnection re-subscription.
74-
* echo_server.cpp: A simple TCP echo server.
75-
* chat_room.cpp: A command line chat built on Redis pubsub.
76-
* low_level_sync.cpp: Sends a ping synchronously using the low-level API.
77-
* low_level_async.cpp: Sends a ping asynchronously using the low-level API.
54+
`async_exec` when a response arrives, to
55+
`aedis::connection::async_receive` when a server-push is received
56+
and will trigger writes of pending requests when a reconnection
57+
occurs.
58+
59+
The role played by `async_run` can be better understood in the context
60+
of long-lived connections, which we will cover in the next section.
61+
Before that however, the reader might want to skim over the examples
62+
63+
* cpp17_intro.cpp: The Aedis hello-world program. Sends one command and quits the connection.
64+
* cpp17_intro_sync.cpp: Shows how to use the connection class synchronously.
65+
* cpp17_low_level_sync.cpp: Sends a ping synchronously using the low-level API.
66+
* cpp20_intro.cpp: Like cpp17_intro.cpp but uses awaitable operators.
67+
* cpp20_intro_tls.cpp: Same as intro.cpp but over TLS.
68+
* cpp20_containers.cpp: Shows how to send and receive STL containers and how to use transactions.
69+
* cpp20_serialization.cpp: Shows how to serialize types using Boost.Json.
70+
* cpp20_resolve_with_sentinel.cpp: Shows how to resolve a master address using sentinels.
71+
* cpp20_subscriber.cpp: Shows how to implement pubsub with reconnection re-subscription.
72+
* cpp20_echo_server.cpp: A simple TCP echo server.
73+
* cpp20_chat_room.cpp: A command line chat built on Redis pubsub.
74+
* cpp20_low_level_async.cpp: Sends a ping asynchronously using the low-level API.
7875

7976
To avoid repetition code that is common to some examples has been
8077
grouped in common.hpp. The main function used in some async examples

examples/cpp17_intro.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva ([email protected])
2+
*
3+
* Distributed under the Boost Software License, Version 1.0. (See
4+
* accompanying file LICENSE.txt)
5+
*/
6+
7+
#include <iostream>
8+
#include <boost/asio.hpp>
9+
#include <aedis.hpp>
10+
#include <aedis/src.hpp>
11+
12+
namespace net = boost::asio;
13+
namespace resp3 = aedis::resp3;
14+
using aedis::resp3::request;
15+
using aedis::adapt;
16+
using aedis::operation;
17+
18+
void log(boost::system::error_code const& ec, char const* prefix)
19+
{
20+
std::clog << prefix << ec.message() << std::endl;
21+
}
22+
23+
auto main() -> int
24+
{
25+
try {
26+
// The request
27+
resp3::request req;
28+
req.push("HELLO", 3);
29+
req.push("PING", "Hello world");
30+
req.push("QUIT");
31+
32+
// The response.
33+
std::tuple<aedis::ignore, std::string, aedis::ignore> resp;
34+
35+
net::io_context ioc;
36+
37+
// IO objects.
38+
net::ip::tcp::resolver resv{ioc};
39+
aedis::connection conn{ioc};
40+
41+
// Resolve endpoints.
42+
net::ip::tcp::resolver::results_type endpoints;
43+
44+
// async_run callback.
45+
auto on_run = [](auto ec)
46+
{
47+
if (ec)
48+
return log(ec, "on_exec: ");
49+
};
50+
51+
// async_exec callback.
52+
auto on_exec = [&](auto ec, auto)
53+
{
54+
if (ec) {
55+
conn.cancel(operation::run);
56+
return log(ec, "on_exec: ");
57+
}
58+
59+
std::cout << "PING: " << std::get<1>(resp) << std::endl;
60+
};
61+
62+
// Connect callback.
63+
auto on_connect = [&](auto ec, auto)
64+
{
65+
if (ec)
66+
return log(ec, "on_connect: ");
67+
68+
conn.async_run(on_run);
69+
conn.async_exec(req, adapt(resp), on_exec);
70+
};
71+
72+
// Resolve callback.
73+
auto on_resolve = [&](auto ec, auto const& addrs)
74+
{
75+
if (ec)
76+
return log(ec, "on_resolve: ");
77+
78+
endpoints = addrs;
79+
net::async_connect(conn.next_layer(), endpoints, on_connect);
80+
};
81+
82+
resv.async_resolve("127.0.0.1", "6379", on_resolve);
83+
84+
ioc.run();
85+
return 0;
86+
87+
} catch (std::exception const& e) {
88+
std::cerr << "Error: " << e.what() << std::endl;
89+
}
90+
91+
return 1;
92+
}
93+
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)