diff --git a/Makefile.am b/Makefile.am index f7356c98..0e352b23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,10 +47,25 @@ pubsub_SOURCES = $(top_srcdir)/examples/pubsub.cpp pubsub_CPPFLAGS = $(MY_CPPFLAGS) pubsub_LDADD = $(MY_LDADD) -noinst_PROGRAMS += ping -ping_SOURCES = $(top_srcdir)/examples/ping.cpp -ping_CPPFLAGS = $(MY_CPPFLAGS) -ping_LDADD = $(MY_LDADD) +noinst_PROGRAMS += advanced +advanced_SOURCES = $(top_srcdir)/examples/advanced.cpp +advanced_CPPFLAGS = $(MY_CPPFLAGS) +advanced_LDADD = $(MY_LDADD) + +noinst_PROGRAMS += basic1 +basic1_SOURCES = $(top_srcdir)/examples/basic1.cpp +basic1_CPPFLAGS = $(MY_CPPFLAGS) +basic1_LDADD = $(MY_LDADD) + +noinst_PROGRAMS += basic2 +basic2_SOURCES = $(top_srcdir)/examples/basic2.cpp +basic2_CPPFLAGS = $(MY_CPPFLAGS) +basic2_LDADD = $(MY_LDADD) + +noinst_PROGRAMS += basic3 +basic3_SOURCES = $(top_srcdir)/examples/basic3.cpp +basic3_CPPFLAGS = $(MY_CPPFLAGS) +basic3_LDADD = $(MY_LDADD) noinst_PROGRAMS += stl_containers stl_containers_SOURCES = $(top_srcdir)/examples/stl_containers.cpp diff --git a/examples/ping.cpp b/examples/advanced.cpp similarity index 64% rename from examples/ping.cpp rename to examples/advanced.cpp index 383379a2..bce497c9 100644 --- a/examples/ping.cpp +++ b/examples/advanced.cpp @@ -14,49 +14,6 @@ using namespace aedis; -/* Pushes three commands in a request, write and read them in the same response - * object. - */ -net::awaitable ping1() -{ - auto socket = co_await make_connection(); - resp3::stream stream{std::move(socket)}; - - resp3::request req; - req.push(command::hello, 3); - req.push(command::ping); - req.push(command::quit); - co_await stream.async_write(req); - - resp3::response resp; - co_await stream.async_read(resp); - co_await stream.async_read(resp); - co_await stream.async_read(resp); - - std::cout << resp << std::endl; -} - -/* Like above but uses a while loop to read the commands. - */ -net::awaitable ping2() -{ - auto socket = co_await make_connection(); - resp3::stream stream{std::move(socket)}; - - resp3::request req; - req.push(command::hello, 3); - req.push(command::ping); - req.push(command::quit); - co_await stream.async_write(req); - - while (!std::empty(req.commands)) { - resp3::response resp; - co_await stream.async_read(resp); - std::cout << req.commands.front() << ":\n" << resp << std::endl; - req.commands.pop(); - } -} - /* A more elaborate way of doing what has been done above where we send a new * command only after the last one has arrived. This is usually the starting * point for more complex applications. Here we also separate the application @@ -77,49 +34,9 @@ bool prepare_next(std::queue& reqs) return false; } -void process_response3(std::queue& requests, resp3::response& resp) -{ - std::cout << requests.front().commands.front() << ":\n" << resp << std::endl; - - switch (requests.front().commands.front()) { - case command::hello: - prepare_next(requests); - requests.back().push(command::ping); - break; - case command::ping: - prepare_next(requests); - requests.back().push(command::quit); - break; - default: {}; - } -} - -net::awaitable ping3() -{ - auto socket = co_await make_connection(); - resp3::stream stream{std::move(socket)}; - - std::queue requests; - requests.push({}); - requests.back().push(command::hello, 3); - - while (!std::empty(requests)) { - co_await stream.async_write(requests.front()); - while (!std::empty(requests.front().commands)) { - resp3::response resp; - co_await stream.async_read(resp); - process_response3(requests, resp); - requests.front().commands.pop(); - } - - requests.pop(); - } -} - /* More realistic usage example. Like above but we keep reading from * the socket in order to implement a full-duplex communication */ - class state : public std::enable_shared_from_this { private: resp3::stream stream_; @@ -226,7 +143,7 @@ public: }; -net::awaitable ping4() +net::awaitable ping() { auto socket = co_await make_connection(); std::make_shared(std::move(socket))->start(); @@ -235,9 +152,6 @@ net::awaitable ping4() int main() { net::io_context ioc; - co_spawn(ioc, ping1(), net::detached); - co_spawn(ioc, ping2(), net::detached); - co_spawn(ioc, ping3(), net::detached); - co_spawn(ioc, ping4(), net::detached); + co_spawn(ioc, ping(), net::detached); ioc.run(); } diff --git a/examples/basic1.cpp b/examples/basic1.cpp new file mode 100644 index 00000000..0e225b78 --- /dev/null +++ b/examples/basic1.cpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using namespace aedis; + +/* A very simple example to illustrate the basic principles. It adds + * three commands to the request and reads the response one after the + * other. + * + * Notice the responses are read in the same object for + * simplification. + */ +net::awaitable ping() +{ + auto socket = co_await make_connection(); + resp3::stream stream{std::move(socket)}; + + resp3::request req; + req.push(command::hello, 3); + req.push(command::ping); + req.push(command::quit); + + co_await stream.async_write(req); + + resp3::response resp; + co_await stream.async_read(resp); + co_await stream.async_read(resp); + co_await stream.async_read(resp); + + std::cout << resp << std::endl; +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, ping(), net::detached); + ioc.run(); +} diff --git a/examples/basic2.cpp b/examples/basic2.cpp new file mode 100644 index 00000000..e0202745 --- /dev/null +++ b/examples/basic2.cpp @@ -0,0 +1,47 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using namespace aedis; + +/* Similar to the basic1 example but + * + * 1. Reads the response in a loop. + * 2. Prints the command to which the response belongs. + */ +net::awaitable ping() +{ + auto socket = co_await make_connection(); + resp3::stream stream{std::move(socket)}; + + resp3::request req; + req.push(command::hello, 3); + req.push(command::ping); + req.push(command::quit); + + co_await stream.async_write(req); + + while (!std::empty(req.commands)) { + resp3::response resp; + co_await stream.async_read(resp); + std::cout << req.commands.front() << ":\n" << resp << std::endl; + req.commands.pop(); + } +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, ping(), net::detached); + ioc.run(); +} diff --git a/examples/basic3.cpp b/examples/basic3.cpp new file mode 100644 index 00000000..3473cf63 --- /dev/null +++ b/examples/basic3.cpp @@ -0,0 +1,80 @@ +/* Copyright (c) 2019 - 2021 Marcelo Zimbres Silva (mzimbres at gmail dot com) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include "types.hpp" +#include "utils.ipp" + +using namespace aedis; + +/* A more elaborate way sending requests where a new request is sent + * only after the last one has arrived. This can be used as a starting + * point for more complex applications. + * + * We also separate the application logic out out the coroutine for + * clarity. + */ + +// Adds a new element in the queue if necessary. +void prepare_next(std::queue& reqs) +{ + if (std::empty(reqs) || std::size(reqs) == 1) + reqs.push({}); +} + +void process_response( + std::queue& requests, + resp3::response& resp) +{ + std::cout + << requests.front().commands.front() << ":\n" + << resp << std::endl; + + switch (requests.front().commands.front()) { + case command::hello: + prepare_next(requests); + requests.back().push(command::ping); + break; + case command::ping: + prepare_next(requests); + requests.back().push(command::quit); + break; + default: {}; + } +} + +net::awaitable ping() +{ + auto socket = co_await make_connection(); + resp3::stream stream{std::move(socket)}; + + std::queue requests; + requests.push({}); + requests.back().push(command::hello, 3); + + while (!std::empty(requests)) { + co_await stream.async_write(requests.front()); + while (!std::empty(requests.front().commands)) { + resp3::response resp; + co_await stream.async_read(resp); + process_response(requests, resp); + requests.front().commands.pop(); + } + + requests.pop(); + } +} + +int main() +{ + net::io_context ioc; + co_spawn(ioc, ping(), net::detached); + ioc.run(); +}