mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 08:46:44 +08:00
Base implementation of an ASIO completion token integration
* Bump the asio version to 1.41 * Move headers that require an external dependency to include/continuable/support * Ref #28 * Ref #27
This commit is contained in:
parent
0b1b284e3a
commit
1a1c7b68c6
@ -1 +1 @@
|
||||
Subproject commit 0a52abce85ab83b920cc7257d8a2703fe69bc79c
|
||||
Subproject commit 8087252a0c3c2f0baad96ddbd6554db17a846376
|
||||
@ -49,7 +49,7 @@ Continuable is a header-only library with one required header-only dependency:
|
||||
erasure wrapper to convert a \ref continuable_base into a \ref continuable.
|
||||
|
||||
Additionally GTest is required as optional dependency for the asynchronous
|
||||
unit testing macros defined in `continuable/continuable-testing.hpp`
|
||||
unit testing macros defined in `continuable/support/gtest.hpp`
|
||||
if those are used:
|
||||
|
||||
- [google/googletest](https://github.com/google/googletest) is used as
|
||||
|
||||
@ -1,15 +1,28 @@
|
||||
add_library(asio-example-deps INTERFACE)
|
||||
|
||||
target_include_directories(asio-example-deps
|
||||
INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
target_link_libraries(asio-example-deps
|
||||
INTERFACE
|
||||
asio
|
||||
continuable)
|
||||
|
||||
add_executable(example-asio
|
||||
${CMAKE_CURRENT_LIST_DIR}/example-asio.cpp)
|
||||
|
||||
target_include_directories(example-asio
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
target_link_libraries(example-asio
|
||||
PRIVATE
|
||||
asio
|
||||
continuable)
|
||||
asio-example-deps)
|
||||
|
||||
target_compile_definitions(example-asio
|
||||
PUBLIC
|
||||
-DCONTINUABLE_WITH_NO_EXCEPTIONS)
|
||||
|
||||
add_executable(example-asio-integration
|
||||
${CMAKE_CURRENT_LIST_DIR}/example-asio-integration.cpp)
|
||||
|
||||
target_link_libraries(example-asio-integration
|
||||
PRIVATE
|
||||
asio-example-deps)
|
||||
|
||||
129
examples/example-asio/example-asio-integration.cpp
Normal file
129
examples/example-asio/example-asio-integration.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#include <asio.hpp>
|
||||
|
||||
#include <continuable/continuable.hpp>
|
||||
#include <continuable/support/asio.hpp>
|
||||
|
||||
// Queries the NIST daytime service and prints the current date and time
|
||||
void daytime_service();
|
||||
|
||||
// Checks that a cancelled timer async_wait fails with
|
||||
// `asio::error::operation_aborted`
|
||||
void cancelled_async_wait();
|
||||
|
||||
// Indicates fatal error due to an unexpected failure in the continuation chain.
|
||||
void unexpected_error(cti::exception_t);
|
||||
|
||||
// Check that the failure was an aborted operation, as expected.
|
||||
void check_aborted_operation(cti::exception_t);
|
||||
|
||||
int main(int, char**) {
|
||||
daytime_service();
|
||||
cancelled_async_wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void daytime_service() {
|
||||
using asio::ip::tcp;
|
||||
|
||||
asio::io_context ioc(1);
|
||||
tcp::resolver resolver(ioc);
|
||||
tcp::socket socket(ioc);
|
||||
std::string buf;
|
||||
|
||||
resolver.async_resolve("time.nist.gov", "daytime", cti::asio_token)
|
||||
.then([&socket](tcp::resolver::results_type endpoints) {
|
||||
return asio::async_connect(socket, endpoints, cti::asio_token);
|
||||
})
|
||||
.then([&socket, &buf] {
|
||||
return asio::async_read_until(socket, asio::dynamic_buffer(buf), '\n',
|
||||
cti::asio_token);
|
||||
})
|
||||
.then([&buf](std::size_t) { puts(buf.data()); })
|
||||
.fail(&unexpected_error);
|
||||
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
void cancelled_async_wait() {
|
||||
asio::io_context ioc(1);
|
||||
asio::steady_timer t(ioc);
|
||||
|
||||
t.expires_after(std::chrono::seconds(999));
|
||||
|
||||
t.async_wait(cti::asio_token)
|
||||
.then([] {
|
||||
puts("This should never be called");
|
||||
std::terminate();
|
||||
})
|
||||
.fail(&check_aborted_operation);
|
||||
|
||||
t.cancel_one();
|
||||
ioc.run();
|
||||
}
|
||||
|
||||
void unexpected_error(cti::exception_t e) {
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
std::rethrow_exception(e);
|
||||
#else
|
||||
puts("Continuation failed with unexpected error");
|
||||
puts(e.message().data());
|
||||
std::terminate();
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_aborted_operation(cti::exception_t ex) {
|
||||
auto is_expected_error = [](auto err_val) {
|
||||
if (err_val == asio::error_code(asio::error::operation_aborted)) {
|
||||
puts("Continuation failed due to aborted async operation, as expected.");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
try {
|
||||
std::rethrow_exception(ex);
|
||||
} catch (asio::system_error const& err) {
|
||||
if (is_expected_error(err.code())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (is_expected_error(ex)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
unexpected_error(ex);
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v3.0.0
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
|
||||
154
include/continuable/detail/support/asio.hpp
Normal file
154
include/continuable/detail/support/asio.hpp
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
||||
#define CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
||||
|
||||
#include <continuable/detail/features.hpp>
|
||||
|
||||
#if defined(ASIO_STANDALONE)
|
||||
#include <asio/async_result.hpp>
|
||||
#include <asio/error_code.hpp>
|
||||
#include <asio/version.hpp>
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
#include <asio/system_error.hpp>
|
||||
#endif
|
||||
|
||||
#if (ASIO_VERSION / 100 % 1000) <= 12
|
||||
#define CTI_DETAIL_ASIO_HAS_NO_INTEGRATION
|
||||
#elif (ASIO_VERSION / 100 % 1000) <= 14
|
||||
#define CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
||||
#endif
|
||||
|
||||
#define CTI_DETAIL_ASIO_NAMESPACE_BEGIN namespace asio {
|
||||
#define CTI_DETAIL_ASIO_NAMESPACE_END }
|
||||
#else
|
||||
#include <boost/asio/async_result.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
#include <boost/system/system_error.hpp>
|
||||
#endif
|
||||
|
||||
#if (BOOST_VERSION / 100 % 1000) <= 69
|
||||
#define CTI_DETAIL_ASIO_HAS_NO_INTEGRATION
|
||||
#elif (BOOST_VERSION / 100 % 1000) <= 71
|
||||
#define CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
||||
#endif
|
||||
|
||||
#define CTI_DETAIL_ASIO_NAMESPACE_BEGIN \
|
||||
namespace boost { \
|
||||
namespace asio {
|
||||
#define CTI_DETAIL_ASIO_NAMESPACE_END \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CTI_DETAIL_ASIO_HAS_NO_INTEGRATION)
|
||||
#error "First-class ASIO support for continuable requires the form of "\
|
||||
"`async_result` with an `initiate` static member function, which was added " \
|
||||
"in standalone ASIO 1.13.0 and Boost ASIO 1.70. Older versions can be " \
|
||||
"integrated manually with `cti::promisify`."
|
||||
#endif
|
||||
|
||||
#include <continuable/detail/core/base.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
#include <exception>
|
||||
#endif
|
||||
|
||||
namespace cti {
|
||||
namespace detail {
|
||||
namespace asio {
|
||||
|
||||
#if defined(ASIO_STANDALONE)
|
||||
using error_code_t = ::asio::error_code;
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
using system_error_t = ::asio::system_error;
|
||||
#endif
|
||||
#else
|
||||
using error_code_t = ::boost::system::error_code;
|
||||
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
using system_error_t = ::boost::system::system_error;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Binds `promise` to the first argument of a continuable resolver, giving it
|
||||
// the signature of an ASIO handler.
|
||||
template <typename Promise>
|
||||
auto promise_resolver_handler(Promise&& promise) noexcept {
|
||||
return [promise = std::forward<Promise>(promise)](
|
||||
error_code_t e, auto&&... args) mutable noexcept {
|
||||
if (e) {
|
||||
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
|
||||
promise.set_exception(
|
||||
std::make_exception_ptr(system_error_t(std::move(e))));
|
||||
#else
|
||||
promise.set_exception(cti::exception_t(e.value(), e.category()));
|
||||
#endif
|
||||
} else {
|
||||
promise.set_value(std::forward<decltype(args)>(args)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Helper struct wrapping a call to `cti::make_continuable` and, if needed,
|
||||
// providing an erased, explicit `return_type` for `async_result`.
|
||||
template <typename Signature>
|
||||
struct initiate_make_continuable;
|
||||
|
||||
template <typename... Args>
|
||||
struct initiate_make_continuable<void(error_code_t, Args...)> {
|
||||
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
|
||||
using erased_return_type = cti::continuable<Args...>;
|
||||
#endif
|
||||
|
||||
template <typename Continuation>
|
||||
auto operator()(Continuation&& continuation) {
|
||||
return detail::base::attorney::create_from(
|
||||
std::forward<Continuation>(continuation), detail::identity<Args...>{},
|
||||
detail::util::ownership{});
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct initiate_make_continuable<void(error_code_t const&, Args...)>
|
||||
: initiate_make_continuable<void(error_code_t, Args...)> {};
|
||||
|
||||
} // namespace asio
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_ASIO_HPP_INCLUDED
|
||||
83
include/continuable/support/asio.hpp
Normal file
83
include/continuable/support/asio.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
/~` _ _ _|_. _ _ |_ | _
|
||||
\_,(_)| | | || ||_|(_||_)|(/_
|
||||
|
||||
https://github.com/Naios/continuable
|
||||
v4.0.0
|
||||
|
||||
Copyright(c) 2015 - 2019 Denis Blank <denis.blank at outlook dot com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_SUPPORT_ASIO_HPP_INCLUDED
|
||||
#define CONTINUABLE_SUPPORT_ASIO_HPP_INCLUDED
|
||||
|
||||
#include <continuable/continuable-base.hpp>
|
||||
#include <continuable/detail/support/asio.hpp>
|
||||
#include <continuable/detail/utility/traits.hpp>
|
||||
|
||||
namespace cti {
|
||||
|
||||
// Type used as an ASIO completion token to specify an asynchronous operation
|
||||
// should return a continuable.
|
||||
struct asio_token_t {};
|
||||
|
||||
// Special value for instance of `asio_token_t`.
|
||||
constexpr asio_token_t asio_token{};
|
||||
|
||||
} // namespace cti
|
||||
|
||||
CTI_DETAIL_ASIO_NAMESPACE_BEGIN
|
||||
|
||||
template <typename Signature>
|
||||
class async_result<cti::asio_token_t, Signature> {
|
||||
public:
|
||||
#if defined(CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION)
|
||||
using return_type = typename cti::detail::asio::initiate_make_continuable<
|
||||
Signature>::erased_return_type;
|
||||
#endif
|
||||
|
||||
template <typename Initiation, typename... Args>
|
||||
static auto initiate(Initiation initiation, cti::asio_token_t, Args... args) {
|
||||
return cti::detail::asio::initiate_make_continuable<Signature>{}(
|
||||
[initiation = std::move(initiation),
|
||||
init_args =
|
||||
std::make_tuple(std::move(args)...)](auto&& promise) mutable {
|
||||
cti::detail::traits::unpack(
|
||||
[initiation = std::move(initiation),
|
||||
handler = cti::detail::asio::promise_resolver_handler(
|
||||
std::forward<decltype(promise)>(promise))](
|
||||
auto&&... args) mutable {
|
||||
std::move(initiation)(std::move(handler),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
},
|
||||
std::move(init_args));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
CTI_DETAIL_ASIO_NAMESPACE_END
|
||||
|
||||
#undef CTI_DETAIL_ASIO_NAMESPACE_BEGIN
|
||||
#undef CTI_DETAIL_ASIO_NAMESPACE_END
|
||||
#undef CTI_DETAIL_ASIO_HAS_EXPLICIT_RET_TYPE_INTEGRATION
|
||||
|
||||
#endif // CONTINUABLE_SUPPORT_ASIO_HPP_INCLUDED
|
||||
@ -28,8 +28,8 @@
|
||||
SOFTWARE.
|
||||
**/
|
||||
|
||||
#ifndef CONTINUABLE_TESTING_HPP_INCLUDED
|
||||
#define CONTINUABLE_TESTING_HPP_INCLUDED
|
||||
#ifndef CONTINUABLE_SUPPORT_GTEST_HPP_INCLUDED
|
||||
#define CONTINUABLE_SUPPORT_GTEST_HPP_INCLUDED
|
||||
|
||||
#include <continuable/detail/other/testing.hpp>
|
||||
#include <continuable/detail/utility/traits.hpp>
|
||||
@ -169,4 +169,4 @@
|
||||
|
||||
/// \}
|
||||
|
||||
#endif // CONTINUABLE_TESTING_HPP_INCLUDED
|
||||
#endif // CONTINUABLE_SUPPORT_GTEST_HPP_INCLUDED
|
||||
@ -31,8 +31,8 @@
|
||||
#include <functional>
|
||||
|
||||
#include <continuable/continuable-base.hpp>
|
||||
#include <continuable/continuable-testing.hpp>
|
||||
#include <continuable/continuable.hpp>
|
||||
#include <continuable/support/gtest.hpp>
|
||||
#include <string>
|
||||
|
||||
using cti::detail::identity;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user