2
0
mirror of https://github.com/boostorg/cobalt.git synced 2026-01-19 04:02:16 +00:00

composition is not experimental anymore.

composition fix for immediate completion.
This commit is contained in:
Klemens Morgenstern
2025-06-22 14:13:41 +08:00
committed by Klemens Morgenstern
parent 6e5713de52
commit 0f502f36fc
18 changed files with 114 additions and 36 deletions

View File

@@ -24,7 +24,6 @@ constant boost_dependencies :
/boost/static_string//boost_static_string
/boost/system//boost_system
/boost/throw_exception//boost_throw_exception
/boost/url//boost_url
/boost/variant2//boost_variant2 ;
project /boost/cobalt

View File

@@ -77,10 +77,9 @@ include::reference/thread.adoc[]
include::reference/result.adoc[]
include::reference/async_for.adoc[]
include::reference/error.adoc[]
include::reference/composition.adoc[]
include::reference/config.adoc[]
include::reference/experimental/context.adoc[]
include::reference/io/buffer.adoc[]
include::reference/io/ops.adoc[]
include::reference/io/steady_timer.adoc[]
@@ -104,6 +103,9 @@ include::reference/io/resolver.adoc[]
include::reference/io/acceptor.adoc[]
include::reference/io/ssl.adoc[]
include::reference/experimental/context.adoc[]
= In-Depth
include::background/custom_executors.adoc[]

View File

@@ -0,0 +1,41 @@
[#detached]
== cobalt/composition.hpp
Including the `cobalt/composition.hpp` provides definitions to turn any function that
takes a `cobalt::completion_handler` as it's last argument. This allows simple creation of composed operations.
Results of `co_await` statements automatically get turned into tuples (akin to used `as_tuple`) to avoid exceptions.
The results need to be `co_return`-ed. The Handler passed into the coroutine must not be touched.
[source,cpp]
----
struct echo_op final : op<system::error_code>
{
echo_op(cobalt::io::stream & str) : stream(str) {}
void initiate(completion_handler<system::error_code>) final;
cobalt::io::stream & str;
};
void echo_op::initiate(completion_handler<system::error_code, std::size_t>)
{
char buf[4096];
auto [ec, n] = co_await str.read_some(buf);
auto buf = asio::buffer(buf, n);
while (!ec && !buf.empty() && !!co_await this_coro::cancelled)
{
std::tie(ec, n) = co_await str.write_some(buf);
buf += n;
}
if (!!co_await this_coro::cancelled)
co_return {asio::error::operation_aborted, m};
else
co_return {system::error_code{}, m};
}
----

View File

@@ -43,7 +43,7 @@ foreach(SRC ${ALL_EXAMPLES})
add_executable(boost_cobalt_example_${NAME} ${SRC})
target_link_libraries(boost_cobalt_example_${NAME} PUBLIC Boost::cobalt Boost::cobalt::io OpenSSL::SSL)
target_compile_definitions(boost_cobalt_example_${NAME} PUBLIC)
if (NAME STREQUAL python)
if (NAME STREQUAL echo_server)
target_link_libraries(boost_cobalt_example_${NAME} PUBLIC Boost::cobalt::io)
endif()
endforeach()

View File

@@ -23,7 +23,7 @@ project : requirements
exe channel : channel.cpp /boost/cobalt//boost_cobalt ;
exe delay : delay.cpp /boost/cobalt//boost_cobalt ;
exe delay_op : delay_op.cpp /boost/cobalt//boost_cobalt ;
exe echo_server : echo_server.cpp /boost/cobalt//boost_cobalt ;
exe echo_server : echo_server.cpp /boost/cobalt//boost_cobalt /boost/cobalt//boost_cobalt_io ;
exe outcome : outcome.cpp /boost/cobalt//boost_cobalt /boost/outcome//boost_outcome ;
exe thread : thread.cpp /boost/cobalt//boost_cobalt ;
exe thread_pool : thread_pool.cpp /boost/cobalt//boost_cobalt ;

View File

@@ -153,6 +153,15 @@ struct composition_promise
auto exec = handler.get_executor();
auto ho = handler.self.release();
detail::self_destroy(h, exec);
if (handler.completed_immediately != nullptr
&& *handler.completed_immediately == completed_immediately_t::initiating)
//not maybe here, because we don't go through the immediate executor
{
*handler.completed_immediately = completed_immediately_t::yes;
return std::noop_coroutine();
}
return ho;
}

View File

@@ -17,7 +17,7 @@
namespace boost::cobalt::io
{
struct acceptor
struct BOOST_SYMBOL_VISIBLE acceptor
{
using wait_type = asio::socket_base::wait_type;
constexpr static std::size_t max_listen_connections = asio::socket_base::max_listen_connections;

View File

@@ -15,7 +15,6 @@
#include <boost/endian/conversion.hpp>
#include <boost/static_string.hpp>
#include <boost/system/result.hpp>
#include <boost/url/static_url.hpp>
#include <array>
#include <algorithm>

View File

@@ -15,16 +15,15 @@
#include <boost/cobalt/promise.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/result.hpp>
#include <boost/url/url_view.hpp>
namespace boost::cobalt::io
{
struct resolver
struct BOOST_SYMBOL_VISIBLE resolver
{
using flags = asio::ip::resolver_base::flags;
resolver(const executor & exec = this_thread::get_executor());
resolver(resolver && ) = delete;
@@ -37,37 +36,39 @@ struct resolver
void initiate(completion_handler<system::error_code, endpoint_sequence> h) override;
resolve_op_(asio::ip::basic_resolver<protocol_type, executor> & resolver,
std::string_view host, std::string_view service)
: resolver_(resolver), host_(host), service_(service) {}
std::string_view host, std::string_view service, flags flags_ = {})
: resolver_(resolver), host_(host), service_(service), flags_(flags_) {}
private:
asio::ip::basic_resolver<protocol_type, executor> & resolver_;
std::string_view host_;
std::string_view service_;
flags flags_;
};
public:
[[nodiscard]] auto resolve(std::string_view host, std::string_view service)
[[nodiscard]] auto resolve(std::string_view host, std::string_view service,
flags flags_ = {})
{
return resolve_op_{resolver_, host, service};
return resolve_op_{resolver_, host, service, flags_};
}
private:
asio::ip::basic_resolver<protocol_type, executor> resolver_;
};
struct lookup : op<system::error_code, endpoint_sequence>
struct BOOST_SYMBOL_VISIBLE lookup : op<system::error_code, endpoint_sequence>
{
lookup(std::string_view host, std::string_view service,
const executor & exec = this_thread::get_executor())
: host_(host), service_(service), resolver_{exec} {}
const executor & exec = this_thread::get_executor(),
resolver::flags flags_ = {})
: host_(host), service_(service), resolver_{exec}, flags_{flags_} {}
BOOST_COBALT_IO_DECL void initiate(completion_handler<system::error_code, endpoint_sequence> h) final override;
private:
std::string_view host_;
std::string_view service_;
asio::ip::basic_resolver<protocol_type, executor> resolver_;
resolver::flags flags_;
};
}

View File

@@ -6,7 +6,7 @@
//
#include <boost/cobalt/io/acceptor.hpp>
#include <boost/cobalt/experimental/composition.hpp>
#include <boost/cobalt/composition.hpp>
namespace boost::cobalt::io
{

View File

@@ -8,9 +8,6 @@
#include <boost/cobalt/io/endpoint.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/url/parse.hpp>
#include <boost/url/url_view.hpp>
namespace boost::cobalt::detail
{

View File

@@ -6,7 +6,7 @@
//
#include <boost/cobalt/io/read.hpp>
#include <boost/cobalt/experimental/composition.hpp>
#include <boost/cobalt/composition.hpp>
#include <boost/asio/read_at.hpp>

View File

@@ -29,7 +29,6 @@ struct transformer
r.assign(rr.begin(), rr.end());
return asio::deferred.values(ec, std::move(r));
}
};
@@ -37,14 +36,14 @@ struct transformer
void resolver::resolve_op_::initiate(completion_handler<system::error_code, endpoint_sequence> h)
{
resolver_.async_resolve(
cobalt::io::ip, host_, service_,
cobalt::io::ip, host_, service_, flags_,
asio::deferred(transformer{}))(std::move(h));
}
void lookup::initiate(completion_handler<system::error_code, endpoint_sequence> h)
{
resolver_.async_resolve(
cobalt::io::ip, host_, service_,
cobalt::io::ip, host_, service_, flags_,
asio::deferred(transformer{}))(std::move(h));
}

View File

@@ -6,7 +6,7 @@
//
#include <boost/cobalt/io/write.hpp>
#include <boost/cobalt/experimental/composition.hpp>
#include <boost/cobalt/composition.hpp>
namespace boost::cobalt::io
{

View File

@@ -11,7 +11,8 @@ add_executable(boost_cobalt_main_compile EXCLUDE_FROM_ALL main_compile.cpp)
add_executable(boost_cobalt_basic_tests EXCLUDE_FROM_ALL
async_for.cpp test_main.cpp promise.cpp with.cpp op.cpp handler.cpp join.cpp race.cpp this_coro.cpp
channel.cpp generator.cpp run.cpp task.cpp gather.cpp wait_group.cpp wrappers.cpp left_race.cpp
strand.cpp fork.cpp thread.cpp any_completion_handler.cpp detached.cpp monotonic_resource.cpp sbo_resource.cpp)
strand.cpp fork.cpp thread.cpp any_completion_handler.cpp detached.cpp monotonic_resource.cpp sbo_resource.cpp
composition.cpp)
target_link_libraries(boost_cobalt_main Boost::cobalt)
target_link_libraries(boost_cobalt_main_compile Boost::cobalt)
@@ -20,7 +21,7 @@ target_link_libraries(boost_cobalt_basic_tests Boost::cobalt Boost::unit_test_f
add_test(NAME boost_cobalt_main COMMAND boost_cobalt_main)
add_test(NAME boost_cobalt_basic_tests COMMAND boost_cobalt_basic_tests)
add_executable(boost_cobalt_experimental EXCLUDE_FROM_ALL test_main.cpp experimental/context.cpp experimental/yield_context.cpp experimental/composition.cpp)
add_executable(boost_cobalt_experimental EXCLUDE_FROM_ALL test_main.cpp experimental/context.cpp experimental/yield_context.cpp)
target_link_libraries(boost_cobalt_experimental Boost::cobalt Boost::unit_test_framework Boost::context)
add_test(NAME boost_cobalt_experimental COMMAND boost_cobalt_experimental)
@@ -33,6 +34,7 @@ add_executable(boost_cobalt_io_test EXCLUDE_FROM_ALL
io/sleep.cpp
io/pipe.cpp
io/endpoint.cpp
io/lookup.cpp
)
target_link_libraries(boost_cobalt_io_test Boost::cobalt::io Boost::unit_test_framework OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(boost_cobalt_io_test Boost::cobalt::io Boost::unit_test_framework OpenSSL::SSL OpenSSL::Crypto Boost::url)
add_dependencies(tests boost_cobalt_main boost_cobalt_basic_tests boost_cobalt_static_tests boost_cobalt_experimental boost_cobalt_io_test)

View File

@@ -28,11 +28,11 @@ lib test_impl : test_main.cpp /boost/cobalt//boost_cobalt /boost/test//boost_uni
run main.cpp /boost/cobalt//boost_cobalt ;
run main_compile.cpp /boost/cobalt//boost_cobalt util.cpp concepts.cpp ;
for local src in [ glob *.cpp : main.cpp main_compile.cpp test_main.cpp concepts.cpp util.cpp ]
for local src in [ glob *.cpp : main.cpp main_compile.cpp test_main.cpp concepts.cpp util.cpp composition.cpp ]
{
run $(src) test_impl ;
}
run experimental/context.cpp experimental/composition.cpp test_impl //boost/context ;
run experimental/context.cpp test_impl //boost/context ;
run [ glob io/*.cpp ] test_impl /boost/cobalt//boost_cobalt_io /boost/cobalt//boost_cobalt ;

View File

@@ -5,9 +5,9 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/cobalt/experimental/composition.hpp>
#include <boost/cobalt/composition.hpp>
#include "../test.hpp"
#include "test.hpp"
using namespace boost::cobalt;

29
test/io/lookup.cpp Normal file
View File

@@ -0,0 +1,29 @@
//
// Copyright (c) 2025 Klemens Morgenstern (klemens.morgenstern@gmx.net)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/cobalt/io/resolver.hpp>
#include <boost/asio/buffer_registration.hpp>
#include <boost/asio/io_context.hpp>
#include "../test.hpp"
BOOST_AUTO_TEST_SUITE(io);
BOOST_AUTO_TEST_SUITE(lookup);
CO_TEST_CASE(boost_org)
{
auto ep = co_await boost::cobalt::io::lookup("boost.org", "https");
BOOST_REQUIRE(ep.size() >= 1u);
BOOST_CHECK(boost::cobalt::io::get<boost::cobalt::io::tcp>(ep[0]).port() == 443);
}
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_SUITE_END();