From 97a4769d3547a36250274449207701f6e84fb167 Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Thu, 15 Sep 2022 16:42:51 -0400 Subject: [PATCH] neorados: Use C++20 Coroutines in exerciser/demo Just as a demonstration to see how well they work and how to put things together with them. Signed-off-by: Adam C. Emerson --- src/tools/CMakeLists.txt | 2 +- src/tools/neorados.cc | 98 ++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index aeb9d0248ea6e..4a891e22fa174 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -20,7 +20,7 @@ if(NOT WIN32) set(neorados_srcs neorados.cc) add_executable(neorados ${neorados_srcs}) - target_link_libraries(neorados libneorados spawn fmt::fmt ${CMAKE_DL_LIBS}) + target_link_libraries(neorados libneorados fmt::fmt ${CMAKE_DL_LIBS}) #install(TARGETS neorados DESTINATION bin) endif() diff --git a/src/tools/neorados.cc b/src/tools/neorados.cc index c89fb49c9c50f..f1b0eff753e94 100644 --- a/src/tools/neorados.cc +++ b/src/tools/neorados.cc @@ -13,10 +13,9 @@ * */ -#define BOOST_COROUTINES_NO_DEPRECATION_WARNING - #include #include +#include #include #include #include @@ -24,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,8 +31,6 @@ #include #include -#include - #include "include/buffer.h" // :( #include "include/neorados/RADOS.hpp" @@ -42,7 +40,6 @@ using namespace std::literals; namespace ba = boost::asio; namespace bs = boost::system; namespace R = neorados; -namespace s = spawn; std::string verstr(const std::tuple& v) { @@ -68,91 +65,94 @@ void printseq(const V& v, std::ostream& m, F&& f) }); } -R::IOContext lookup_pool(R::RADOS& r, const std::string& pname, - s::yield_context y) +ba::awaitable lookup_pool(R::RADOS& r, const std::string& pname) { bs::error_code ec; - auto p = r.lookup_pool(pname, y[ec]); + auto p = co_await r.lookup_pool(pname, + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error( ec, fmt::format("when looking up '{}'", pname)); - return R::IOContext(p); + co_return R::IOContext(p); } -void lspools(R::RADOS& r, const std::vector&, - s::yield_context y) +ba::awaitable lspools(R::RADOS& r, const std::vector&) { - const auto l = r.list_pools(y); + const auto l = co_await r.list_pools(ba::use_awaitable); printseq(l, std::cout, [](const auto& p) -> const std::string& { return p.second; }); + co_return; } -void ls(R::RADOS& r, const std::vector& p, s::yield_context y) +ba::awaitable ls(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; - const auto pool = lookup_pool(r, pname, y).set_ns(R::all_nspaces); - + const auto pool = (co_await lookup_pool(r, pname)).set_ns(R::all_nspaces); std::vector ls; R::Cursor next = R::Cursor::begin(); bs::error_code ec; do { - std::tie(ls, next) = r.enumerate_objects(pool, next, R::Cursor::end(), - 1000, {}, y[ec]); + std::tie(ls, next) = + co_await r.enumerate_objects(pool, next, R::Cursor::end(), 1000, {}, + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format("when listing {}", pname)); printseq(ls, std::cout); ls.clear(); } while (next != R::Cursor::end()); + co_return; } -void mkpool(R::RADOS& r, const std::vector& p, - s::yield_context y) +ba::awaitable mkpool(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; bs::error_code ec; - r.create_pool(pname, std::nullopt, y[ec]); + co_await r.create_pool(pname, std::nullopt, + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format("when creating pool '{}'", pname)); + co_return; } -void rmpool(R::RADOS& r, const std::vector& p, - s::yield_context y) +ba::awaitable rmpool(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; bs::error_code ec; - r.delete_pool(pname, y[ec]); + co_await r.delete_pool(pname, ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format("when removing pool '{}'", pname)); + co_return; } -void create(R::RADOS& r, const std::vector& p, - s::yield_context y) +ba::awaitable create(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; const R::Object obj = p[1]; - const auto pool = lookup_pool(r, pname, y); + const auto pool = co_await lookup_pool(r, pname); bs::error_code ec; R::WriteOp op; op.create(true); - r.execute(obj, pool, std::move(op), y[ec]); + co_await r.execute(obj, pool, std::move(op), + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format( "when creating object '{}' in pool '{}'", obj, pname)); + co_return; } inline constexpr std::size_t io_size = 4 << 20; -void write(R::RADOS& r, const std::vector& p, s::yield_context y) +ba::awaitable write(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; const R::Object obj(p[1]); - const auto pool = lookup_pool(r, pname, y); + const auto pool = co_await lookup_pool(r, pname); bs::error_code ec; std::unique_ptr buf = std::make_unique(io_size); @@ -174,28 +174,30 @@ void write(R::RADOS& r, const std::vector& p, s::yield_context y) bl.append(buffer::create_static(len, buf.get())); R::WriteOp op; op.write(curoff, std::move(bl)); - r.execute(obj, pool, std::move(op), y[ec]); + co_await r.execute(obj, pool, std::move(op), + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format( "when writing object '{}' in pool '{}'", obj, pname)); } + co_return; } -void read(R::RADOS& r, const std::vector& p, s::yield_context y) +ba::awaitable read(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; const R::Object obj(p[1]); - const auto pool = lookup_pool(r, pname, y); + const auto pool = co_await lookup_pool(r, pname); bs::error_code ec; std::uint64_t len; { R::ReadOp op; op.stat(&len, nullptr); - r.execute(obj, pool, std::move(op), - nullptr, y[ec]); + co_await r.execute(obj, pool, std::move(op), + nullptr, ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error( ec, @@ -208,7 +210,8 @@ void read(R::RADOS& r, const std::vector& p, s::yield_context y) while (auto toread = std::min(len - off, io_size)) { R::ReadOp op; op.read(off, toread, &bl); - r.execute(obj, pool, std::move(op), nullptr, y[ec]); + co_await r.execute(obj, pool, std::move(op), nullptr, + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error( ec, @@ -219,28 +222,31 @@ void read(R::RADOS& r, const std::vector& p, s::yield_context y) bl.write_stream(std::cout); bl.clear(); } + co_return; } -void rm(R::RADOS& r, const std::vector& p, s::yield_context y) +ba::awaitable rm(R::RADOS& r, const std::vector& p) { const auto& pname = p[0]; const R::Object obj = p[1]; - const auto pool = lookup_pool(r, pname, y); + const auto pool = co_await lookup_pool(r, pname); bs::error_code ec; R::WriteOp op; op.remove(); - r.execute(obj, pool, std::move(op), y[ec]); + co_await r.execute(obj, pool, std::move(op), + ba::redirect_error(ba::use_awaitable, ec)); if (ec) throw bs::system_error(ec, fmt::format( "when removing object '{}' in pool '{}'", obj, pname)); + co_return; } static constexpr auto version = std::make_tuple(0ul, 0ul, 1ul); -using cmdfunc = void (*)(R::RADOS& r, const std::vector& p, - s::yield_context); +using cmdfunc = + ba::awaitable (*)(R::RADOS& r, const std::vector& p); struct cmdesc { std::string_view name; @@ -371,10 +377,14 @@ int main(int argc, char* argv[]) prog, command, ci->name, ci->usage); return 1; } - s::spawn(c, [&](s::yield_context y) { - auto r = R::RADOS::Builder{}.build(c, y); - ci->f(r, parameters, y); - }); + ba::co_spawn(c, + [&]() -> ba::awaitable { + auto r = co_await R::RADOS::Builder{}.build( + c, ba::use_awaitable); + co_await ci->f(r, parameters); + }, [](std::exception_ptr e) { + if (e) std::rethrow_exception(e); + }); } else { fmt::print(std::cerr, "{}: {}: unknown command\n", prog, command); return 1; -- 2.39.5