Skip to content

Commit

Permalink
feat: Add experimental support for P2300R7 (std::execution)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tradias committed Dec 8, 2023
1 parent aa691de commit 1520f39
Show file tree
Hide file tree
Showing 24 changed files with 232 additions and 35 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.14...3.24)
cmake_minimum_required(VERSION 3.14...3.27)

include("${CMAKE_CURRENT_LIST_DIR}/cmake/AsioGrpcOptionDefaults.cmake")

Expand Down Expand Up @@ -62,6 +62,8 @@ endif()
option(ASIO_GRPC_DISCOVER_TESTS "Discover tests for ctest" off)
option(ASIO_GRPC_ENABLE_CPP20_TESTS_AND_EXAMPLES
"When tests and/or example builds are enabled then also create CMake targets for C++20" on)
option(ASIO_GRPC_ENABLE_STDEXEC_TESTS "When tests builds are enabled then also create CMake targets for stdexec tests"
off)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
option(
ASIO_GRPC_ENABLE_IO_URING_EXAMPLES
Expand Down
6 changes: 6 additions & 0 deletions cmake/AsioGrpcFindPackages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ if(ASIO_GRPC_ENABLE_CPP20_TESTS_AND_EXAMPLES)
endif()
endif()

if(ASIO_GRPC_ENABLE_STDEXEC_TESTS)
set(STDEXEC_BUILD_TESTS off)
set(STDEXEC_BUILD_EXAMPLES off)
add_subdirectory(stdexec)
endif()

# Fallback to pkg-config
if(NOT ASIO_GRPC_ENABLE_PKGCONFIG_FALLBACK)
return()
Expand Down
2 changes: 1 addition & 1 deletion cmake/AsioGrpcInstallation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ install(
DESTINATION "${ASIO_GRPC_CMAKE_CONFIG_INSTALL_DIR}"
RENAME "${PROJECT_NAME}.natvis")

install(TARGETS asio-grpc asio-grpc-standalone-asio asio-grpc-unifex EXPORT ${PROJECT_NAME}Targets)
install(TARGETS asio-grpc asio-grpc-standalone-asio asio-grpc-unifex asio-grpc-stdexec EXPORT ${PROJECT_NAME}Targets)

install(
EXPORT ${PROJECT_NAME}Targets
Expand Down
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,21 @@ target_compile_definitions(asio-grpc-standalone-asio INTERFACE AGRPC_STANDALONE_
asio_grpc_create_interface_target(asio-grpc-unifex)
target_compile_definitions(asio-grpc-unifex INTERFACE AGRPC_UNIFEX)

asio_grpc_create_interface_target(asio-grpc-stdexec)
target_compile_definitions(asio-grpc-stdexec INTERFACE AGRPC_STDEXEC)
target_compile_features(asio-grpc-stdexec INTERFACE cxx_std_20)

if(ASIO_GRPC_BUILD_EXAMPLES)
target_link_libraries(asio-grpc INTERFACE Boost::headers)
target_link_libraries(asio-grpc-standalone-asio INTERFACE asio::asio)

if(TARGET unifex::unifex)
target_link_libraries(asio-grpc-unifex INTERFACE unifex::unifex)
endif()

if(TARGET STDEXEC::stdexec)
target_link_libraries(asio-grpc-stdexec INTERFACE STDEXEC::stdexec)
endif()
endif()

# asio-grpc sources
Expand Down
5 changes: 3 additions & 2 deletions src/agrpc/bind_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ class AllocatorBinder
*/
constexpr Allocator get_allocator() const noexcept { return impl_.second(); }

#ifdef AGRPC_UNIFEX
friend Allocator tag_invoke(unifex::tag_t<unifex::get_allocator>, const AllocatorBinder& binder) noexcept
#if defined(AGRPC_UNIFEX) || defined(AGRPC_STDEXEC)
friend Allocator tag_invoke(detail::exec::tag_t<detail::exec::get_allocator>,
const AllocatorBinder& binder) noexcept
{
return binder.get_allocator();
}
Expand Down
4 changes: 2 additions & 2 deletions src/agrpc/detail/asio_forward.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
#endif
#endif

#ifdef AGRPC_UNIFEX
#if defined(AGRPC_UNIFEX) || defined(AGRPC_STDEXEC)
#include <system_error>
#endif

Expand All @@ -133,7 +133,7 @@ using ErrorCode = boost::system::error_code;
using ErrorCode = std::error_code;
#endif

#ifdef AGRPC_UNIFEX
#if defined(AGRPC_UNIFEX) || defined(AGRPC_STDEXEC)
inline auto operation_aborted_error_code() { return ErrorCode{}; }
#else
inline auto operation_aborted_error_code() { return ErrorCode{asio::error::operation_aborted}; }
Expand Down
21 changes: 21 additions & 0 deletions src/agrpc/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ class BasicSender : public detail::SenderOf<typename Implementation::Signature>
return {static_cast<Receiver&&>(receiver), grpc_context_, initiation_, implementation_};
}

#ifdef AGRPC_STDEXEC
template <class Receiver>
friend detail::BasicSenderOperationState<Initiation, Implementation, detail::RemoveCrefT<Receiver>> tag_invoke(
stdexec::connect_t, const BasicSender& s, Receiver&& r)
{
return {static_cast<Receiver&&>(r), s.grpc_context_, s.initiation_, s.implementation_};
}

template <class Receiver>
friend detail::BasicSenderOperationState<Initiation, Implementation, detail::RemoveCrefT<Receiver>> tag_invoke(
stdexec::connect_t, BasicSender&& s, Receiver&& r)
{
return {static_cast<Receiver&&>(r), s.grpc_context_, s.initiation_,
static_cast<Implementation&&>(s.implementation_)};
}
#endif

private:
friend detail::BasicSenderAccess;

Expand Down Expand Up @@ -206,6 +223,10 @@ class BasicSenderOperationState
op.start(grpc_context, impl_.second(), std::move(stop_token));
}

#ifdef AGRPC_STDEXEC
friend void tag_invoke(stdexec::start_t, BasicSenderOperationState& s) noexcept { s.start(); }
#endif

private:
friend detail::BasicSender<Initiation, Implementation>;

Expand Down
2 changes: 1 addition & 1 deletion src/agrpc/detail/client_rpc_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ using ClientRPCAccess = ClientRPCContextBaseAccess;

struct ClientContextCancellationFunction
{
#if !defined(AGRPC_UNIFEX)
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC)
explicit
#endif
ClientContextCancellationFunction(grpc::ClientContext& client_context) noexcept
Expand Down
6 changes: 6 additions & 0 deletions src/agrpc/detail/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
{ \
inline namespace u \
{
#elif defined(AGRPC_STDEXEC)
#define AGRPC_NAMESPACE_BEGIN() \
namespace agrpc \
{ \
inline namespace e \
{
#else
static_assert(false,
"asio-grpc backend macro is not defined. Did you forget to link with `asio-grpc::asio-grpc`, "
Expand Down
2 changes: 2 additions & 0 deletions src/agrpc/detail/execution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <agrpc/detail/execution_asio.hpp>
#elif defined(AGRPC_UNIFEX)
#include <agrpc/detail/execution_unifex.hpp>
#elif defined(AGRPC_STDEXEC)
#include <agrpc/detail/execution_stdexec.hpp>
#endif

#endif // AGRPC_DETAIL_EXECUTION_HPP
63 changes: 63 additions & 0 deletions src/agrpc/detail/execution_stdexec.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2023 Dennis Hezel
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef AGRPC_DETAIL_EXECUTION_STDEXEC_HPP
#define AGRPC_DETAIL_EXECUTION_STDEXEC_HPP

#include <agrpc/detail/config.hpp>
#include <exec/inline_scheduler.hpp>
#include <stdexec/execution.hpp>

AGRPC_NAMESPACE_BEGIN()

namespace detail::exec
{
using ::stdexec::get_allocator;
using ::stdexec::get_scheduler;
inline const auto& get_executor = get_scheduler;
using ::stdexec::scheduler;

template <class, class = void>
inline constexpr bool scheduler_provider = false;

template <class T>
inline constexpr bool scheduler_provider<T, decltype((void)std::declval<T>().get_scheduler())> = true;

template <class T>
inline constexpr bool is_sender_v = ::stdexec::sender<T>;

using ::exec::inline_scheduler;
using ::stdexec::connect;
using ::stdexec::connect_result_t;
using ::stdexec::get_stop_token;

template <class Receiver>
void set_done(Receiver&& receiver)
{
::stdexec::set_stopped(static_cast<Receiver&&>(receiver));
}

using ::stdexec::set_error;
using ::stdexec::set_value;
using ::stdexec::start;

template <class T>
using stop_token_type_t = ::stdexec::stop_token_of_t<T>;

using ::stdexec::tag_t;
} // namespace exec

AGRPC_NAMESPACE_END

#endif // AGRPC_DETAIL_EXECUTION_STDEXEC_HPP
13 changes: 7 additions & 6 deletions src/agrpc/detail/executor_with_default.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ struct ExecutorWithDefault : Executor

AGRPC_NAMESPACE_END

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
template <class Default, class Executor>
struct agrpc::asio::traits::equality_comparable<agrpc::detail::ExecutorWithDefault<Default, Executor>>
Expand All @@ -46,7 +46,7 @@ struct agrpc::asio::traits::equality_comparable<agrpc::detail::ExecutorWithDefau
};
#endif

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
template <class Default, class Executor, class F>
struct agrpc::asio::traits::execute_member<agrpc::detail::ExecutorWithDefault<Default, Executor>, F>
Expand All @@ -55,7 +55,7 @@ struct agrpc::asio::traits::execute_member<agrpc::detail::ExecutorWithDefault<De
};
#endif

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
template <class Default, class Executor>
struct agrpc::asio::traits::require_member<agrpc::detail::ExecutorWithDefault<Default, Executor>,
Expand Down Expand Up @@ -120,7 +120,7 @@ struct agrpc::asio::traits::require_member<agrpc::detail::ExecutorWithDefault<De
};
#endif

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
template <class Default, class Executor>
struct agrpc::asio::traits::prefer_member<agrpc::detail::ExecutorWithDefault<Default, Executor>,
Expand All @@ -144,7 +144,8 @@ struct agrpc::asio::traits::prefer_member<agrpc::detail::ExecutorWithDefault<Def
};
#endif

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && \
!defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
template <class Default, class Executor, class Property>
struct agrpc::asio::traits::query_static_constexpr_member<
Expand Down Expand Up @@ -205,7 +206,7 @@ struct agrpc::asio::traits::query_static_constexpr_member<
};
#endif

#if !defined(AGRPC_UNIFEX) && !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) && \
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC) && !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) && \
!defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
template <class Default, class Executor>
struct agrpc::asio::traits::query_member<agrpc::detail::ExecutorWithDefault<Default, Executor>,
Expand Down
2 changes: 1 addition & 1 deletion src/agrpc/detail/grpc_executor_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class GrpcExecutorWorkTrackerBase : public detail::GrpcExecutorBase<Allocator>
}
};

#if !defined(AGRPC_UNIFEX)
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC)
template <bool IsBlockingNever>
struct QueryStaticBlocking
{
Expand Down
9 changes: 9 additions & 0 deletions src/agrpc/detail/sender_of.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define AGRPC_DETAIL_SENDER_OF_HPP

#include <agrpc/detail/config.hpp>
#include <agrpc/detail/execution.hpp>

#include <exception>

Expand All @@ -36,6 +37,14 @@ struct SenderOf<void(Values...)>
using error_types = Variant<std::exception_ptr>;

static constexpr bool sends_done = true;

#ifdef AGRPC_STDEXEC
using sender_concept = stdexec::sender_t;

using completion_signatures =
stdexec::completion_signatures<stdexec::set_value_t(Values...), stdexec::set_error_t(std::exception_ptr),
stdexec::set_stopped_t()>;
#endif
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/agrpc/detail/server_rpc_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ using ServerRPCAccess = ServerRPCContextBaseAccess;

struct ServerContextCancellationFunction
{
#if !defined(AGRPC_UNIFEX)
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC)
explicit
#endif
ServerContextCancellationFunction(grpc::ServerContext& server_context) noexcept
Expand Down
2 changes: 1 addition & 1 deletion src/agrpc/detail/stop_callback_lifetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ inline constexpr bool NEEDS_STOP_CALLBACK<StopToken, detail::Empty> = false;
template <class StopToken, class StopFunction, bool = detail::NEEDS_STOP_CALLBACK<StopToken, StopFunction>>
class StopCallbackLifetime
{
#ifdef AGRPC_UNIFEX
#if defined(AGRPC_UNIFEX) || defined(AGRPC_STDEXEC)
private:
using StopCallback = std::optional<typename StopToken::template callback_type<StopFunction>>;

Expand Down
4 changes: 2 additions & 2 deletions src/agrpc/detail/wait.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct AlarmCancellationFunction
{
grpc::Alarm& alarm_;

#if !defined(AGRPC_UNIFEX)
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC)
explicit
#endif
AlarmCancellationFunction(grpc::Alarm& alarm) noexcept
Expand All @@ -52,7 +52,7 @@ struct AlarmCancellationFunction
}

template <class Deadline>
#if !defined(AGRPC_UNIFEX)
#if !defined(AGRPC_UNIFEX) && !defined(AGRPC_STDEXEC)
explicit
#endif
AlarmCancellationFunction(const detail::AlarmInitFunction<Deadline>& init_function) noexcept
Expand Down
Loading

0 comments on commit 1520f39

Please sign in to comment.