Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .codespellignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ copyable
pullrequest
snd
statics
Claus
389 changes: 389 additions & 0 deletions docs/modules.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ set(EXAMPLES
)

if(BEMAN_USE_MODULES)
list(APPEND EXAMPLES modules) # modules.cpp
list(APPEND EXAMPLES modules modules-and-header)
endif()

foreach(EXAMPLE ${EXAMPLES})
Expand Down
11 changes: 11 additions & 0 deletions examples/modules-and-header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// examples/modules-and-header.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <tuple>
import beman.execution;
namespace ex = beman::execution;

int main() {
auto [rc] = *ex::sync_wait(ex::just(0));
return rc;
}
4 changes: 2 additions & 2 deletions include/beman/execution/detail/affine_on.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ namespace beman::execution {
* @brief affine_on is a CPO, used to adapt a sender to complete on the scheduler
* it got started on which is derived from get_scheduler on the receiver's environment.
*/
BEMAN_EXECUTION_EXPORT using affine_on_t = beman::execution::detail::affine_on_t;
BEMAN_EXECUTION_EXPORT inline constexpr affine_on_t affine_on{};
using affine_on_t = beman::execution::detail::affine_on_t;
inline constexpr affine_on_t affine_on{};
} // namespace beman::execution

// ----------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions include/beman/execution/detail/apply_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace beman::execution {
* \brief Function used to transform a sender and its arguments for a domain.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT template <typename Domain, typename Tag, ::beman::execution::sender Sender, typename... Args>
template <typename Domain, typename Tag, ::beman::execution::sender Sender, typename... Args>
requires requires(Domain domain, Tag tag, Sender&& sender, Args&&... args) {
domain.apply_sender(Tag(), ::std::forward<Sender>(sender), ::std::forward<Args>(args)...);
}
Expand All @@ -29,7 +29,7 @@ constexpr auto apply_sender(Domain domain, Tag, Sender&& sender, Args&&... args)
* \brief Default function used to transform a second and its arguments.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT template <typename Domain, typename Tag, ::beman::execution::sender Sender, typename... Args>
template <typename Domain, typename Tag, ::beman::execution::sender Sender, typename... Args>
requires(not requires(Domain domain, Tag tag, Sender&& sender, Args&&... args) {
domain.apply_sender(Tag(), ::std::forward<Sender>(sender), ::std::forward<Args>(args)...);
}) && requires(Tag tag, Sender&& sender, Args&&... args) {
Expand Down
4 changes: 2 additions & 2 deletions include/beman/execution/detail/as_awaitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace beman::execution {
* \brief Turn an entity, e.g., a sender, into an awaitable.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT struct as_awaitable_t {
struct as_awaitable_t {
template <typename Expr, typename Promise>
auto operator()(Expr&& expr, Promise& promise) const {
if constexpr (requires { ::std::forward<Expr>(expr).as_awaitable(promise); }) {
Expand All @@ -39,7 +39,7 @@ BEMAN_EXECUTION_EXPORT struct as_awaitable_t {
}
}
};
BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::as_awaitable_t as_awaitable{};
inline constexpr ::beman::execution::as_awaitable_t as_awaitable{};
} // namespace beman::execution

// ----------------------------------------------------------------------------
Expand Down
28 changes: 17 additions & 11 deletions include/beman/execution/detail/associate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
// ----------------------------------------------------------------------------

namespace beman::execution::detail {
BEMAN_EXECUTION_EXPORT template <::beman::execution::scope_token Token,
::beman::execution::sender Sender> //-dk:TODO detail export
template <::beman::execution::scope_token Token,
::beman::execution::sender Sender> //-dk:TODO detail export
struct associate_data {
using wrap_sender = ::std::remove_cvref_t<decltype(::std::declval<Token&>().wrap(::std::declval<Sender>()))>;

Expand Down Expand Up @@ -65,7 +65,7 @@ struct associate_data {
Token token;
::std::optional<wrap_sender> sender;
};
BEMAN_EXECUTION_EXPORT template <::beman::execution::scope_token Token, ::beman::execution::sender Sender>
template <::beman::execution::scope_token Token, ::beman::execution::sender Sender>
associate_data(Token, Sender&&) -> associate_data<Token, Sender>;

struct associate_t {
Expand Down Expand Up @@ -93,10 +93,11 @@ struct impls_for<associate_t> : ::beman::execution::detail::default_impls {
typename ::std::remove_cvref_t<Data>::wrap_sender,
Receiver>> {};

static constexpr auto get_state =
[]<typename Sender, typename Receiver>(Sender&& sender, Receiver& receiver) noexcept(
::std::is_nothrow_constructible_v<::std::remove_cvref_t<Sender>, Sender>&&
get_noexcept<::std::remove_cvref_t<Sender>, Receiver>::value) {
struct get_state_impl {
template <typename Sender, typename Receiver>
auto operator()(Sender&& sender, Receiver& receiver) const
noexcept(::std::is_nothrow_constructible_v<::std::remove_cvref_t<Sender>, Sender> &&
get_noexcept<::std::remove_cvref_t<Sender>, Receiver>::value) {
auto [_, data] = ::std::forward<Sender>(sender);
auto dataParts{data.release()};

Expand Down Expand Up @@ -143,8 +144,13 @@ struct impls_for<associate_t> : ::beman::execution::detail::default_impls {
};
return dataParts ? op_state(::std::move(dataParts->first), ::std::move(dataParts->second), receiver)
: op_state(receiver);
};
static constexpr auto start = [](auto& state, auto&&) noexcept -> void { state.run(); };
}
};
static constexpr auto get_state{get_state_impl{}};
struct start_impl {
auto operator()(auto& state, auto&&) const noexcept -> void { state.run(); }
};
static constexpr auto start{start_impl{}};
};

template <typename Data, typename Env>
Expand All @@ -156,8 +162,8 @@ struct completion_signatures_for_impl<
} // namespace beman::execution::detail

namespace beman::execution {
BEMAN_EXECUTION_EXPORT using associate_t = ::beman::execution::detail::associate_t;
BEMAN_EXECUTION_EXPORT inline constexpr associate_t associate{};
using associate_t = ::beman::execution::detail::associate_t;
inline constexpr associate_t associate{};
} // namespace beman::execution

// ----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/await_result_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace beman::execution::detail {
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
* \internal
*/
BEMAN_EXECUTION_EXPORT template <typename T, typename Promise> //-dk:TODO detail export
template <typename T, typename Promise> //-dk:TODO detail export
using await_result_type =
decltype(::beman::execution::detail::get_awaiter(::std::declval<T>(), ::std::declval<Promise&>()).await_resume());
} // namespace beman::execution::detail
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/basic_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace beman::execution::detail {
* \internal
*/
//-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01)
BEMAN_EXECUTION_EXPORT template <typename Sender, typename Receiver> //-dk:TODO detail export
template <typename Sender, typename Receiver> //-dk:TODO detail export
requires ::beman::execution::detail::
//-dk:TODO why is the remove_cvref_t needed...?
valid_specialization<::beman::execution::detail::state_type, std::remove_cvref_t<Sender>, Receiver>
Expand Down
6 changes: 3 additions & 3 deletions include/beman/execution/detail/basic_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ namespace beman::execution::detail {
*/
template <typename Tag, typename Data, typename... Child>
struct basic_sender : ::beman::execution::detail::product_type<Tag, Data, Child...> {
friend struct ::beman::execution::detail::connect_t;
friend struct ::beman::execution::get_completion_signatures_t;
//-dk:TODO friend struct ::beman::execution::detail::connect_t;
//-dk:TODO friend struct ::beman::execution::get_completion_signatures_t;
using sender_concept = ::beman::execution::sender_t;
using indices_for = ::std::index_sequence_for<Child...>;

Expand All @@ -43,7 +43,7 @@ struct basic_sender : ::beman::execution::detail::product_type<Tag, Data, Child.
requires(!::beman::execution::receiver<Receiver>)
auto connect(Receiver receiver) = BEMAN_EXECUTION_DELETE("the passed receiver doesn't model receiver");

private:
//-dk:TODO private:
Comment on lines 31 to 46
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The friend declarations and private access specifier are commented out with TODO comments. This appears to be a workaround for module support. However, this effectively makes the connect member functions public, which may not be the intended API design. If these functions need to remain accessible, consider using a more permanent solution than commented-out code with TODO markers, or document why this change is necessary for module support.

Copilot uses AI. Check for mistakes.
#if __cpp_explicit_this_parameter < 302110L //-dk:TODO need to figure out how to use explicit this with forwarding
template <::beman::execution::receiver Receiver>
auto connect(Receiver receiver) & noexcept(
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/basic_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace beman::execution::detail {
* \internal
*/
//-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01)
BEMAN_EXECUTION_EXPORT template <typename Sender, typename Receiver> //-dk:TODO detail export
template <typename Sender, typename Receiver> //-dk:TODO detail export
struct basic_state {
basic_state(Sender&& sender, Receiver&& rcvr) noexcept(true)
: receiver(::std::move(rcvr)),
Expand Down
60 changes: 31 additions & 29 deletions include/beman/execution/detail/bulk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,38 +57,40 @@ struct bulk_t : ::beman::execution::sender_adaptor_closure<bulk_t> {
template <>
struct impls_for<bulk_t> : ::beman::execution::detail::default_impls {

static constexpr auto complete = []<class Index, class Shape, class Fun, class Rcvr, class Tag, class... Args>(
Index,
::beman::execution::detail::product_type<Shape, Fun>& state,
Rcvr& rcvr,
Tag,
Args&&... args) noexcept -> void
requires(!::std::same_as<Tag, set_value_t> || std::is_invocable_v<Fun, Shape, Args...>)
{
if constexpr (std::same_as<Tag, set_value_t>) {
auto& [shape, f] = state;

using s_type = std::remove_cvref_t<decltype(shape)>;

constexpr bool nothrow = noexcept(f(s_type(shape), args...));

try {
[&]() noexcept(nothrow) {
for (decltype(s_type(shape)) i = 0; i < shape; i++) {
f(s_type(i), args...);
struct complete_impl {
template <class Index, class Shape, class Fun, class Rcvr, class Tag, class... Args>
requires(!::std::same_as<Tag, set_value_t> || std::is_invocable_v<Fun, Shape, Args...>)
auto operator()(Index,
::beman::execution::detail::product_type<Shape, Fun>& state,
Rcvr& rcvr,
Tag,
Args&&... args) const noexcept -> void {
if constexpr (std::same_as<Tag, set_value_t>) {
auto& [shape, f] = state;

using s_type = std::remove_cvref_t<decltype(shape)>;

constexpr bool nothrow = noexcept(f(s_type(shape), args...));

try {
[&]() noexcept(nothrow) {
for (decltype(s_type(shape)) i = 0; i < shape; i++) {
f(s_type(i), args...);
}
Tag()(std::move(rcvr), std::forward<Args>(args)...);
}();

} catch (...) {
if constexpr (not nothrow) {
::beman::execution::set_error(std::move(rcvr), std::current_exception());
}
Tag()(std::move(rcvr), std::forward<Args>(args)...);
}();

} catch (...) {
if constexpr (not nothrow) {
::beman::execution::set_error(std::move(rcvr), std::current_exception());
}
} else {
Tag()(std::move(rcvr), std::forward<Args>(args)...);
}
} else {
Tag()(std::move(rcvr), std::forward<Args>(args)...);
}
};
static constexpr auto complete{complete_impl{}};
};

template <typename, typename, typename>
Expand Down Expand Up @@ -134,8 +136,8 @@ struct completion_signatures_for_impl<

namespace beman::execution {

BEMAN_EXECUTION_EXPORT using bulk_t = ::beman::execution::detail::bulk_t;
BEMAN_EXECUTION_EXPORT inline constexpr ::beman::execution::bulk_t bulk{};
using bulk_t = ::beman::execution::detail::bulk_t;
inline constexpr ::beman::execution::bulk_t bulk{};

} // namespace beman::execution

Expand Down
4 changes: 0 additions & 4 deletions include/beman/execution/detail/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@

// ----------------------------------------------------------------------------

#ifndef BEMAN_EXECUTION_EXPORT
#define BEMAN_EXECUTION_EXPORT
#endif

#if defined(disabled__cpp_deleted_function)
#define BEMAN_EXECUTION_DELETE(msg) delete (msg)
#else
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/completion_signatures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace beman::execution {
* any specializaion are empty. Objects may be created to return them from
* functions used for type computations like get_completion_signatures(sender, env).
*/
BEMAN_EXECUTION_EXPORT template <::beman::execution::detail::completion_signature...>
template <::beman::execution::detail::completion_signature...>
struct completion_signatures {};
} // namespace beman::execution

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace beman::execution {
* \brief Alias to access the completion signatures of a sender
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT template <typename Sender, typename Env = ::beman::execution::env<>>
template <typename Sender, typename Env = ::beman::execution::env<>>
requires ::beman::execution::sender_in<Sender, Env>
using completion_signatures_of_t =
::beman::execution::detail::call_result_t<::beman::execution::get_completion_signatures_t, Sender, Env>;
Expand Down
6 changes: 3 additions & 3 deletions include/beman/execution/detail/connect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace beman::execution::detail {
* \internal
*/
//-dk:TODO this seems to needed for MSVC++ (2026-01-30)
BEMAN_EXECUTION_EXPORT struct connect_t {
struct connect_t {
private:
template <typename Sender, typename Receiver>
static auto make_new_sender(Sender&& sender, Receiver&& receiver)
Expand Down Expand Up @@ -83,7 +83,7 @@ namespace beman::execution {
* \brief Type of the connect customization point object.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT using connect_t = beman::execution::detail::connect_t;
using connect_t = beman::execution::detail::connect_t;
/*!
* \brief Customization point object used to connect a sender and a receiver.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
Expand All @@ -92,7 +92,7 @@ BEMAN_EXECUTION_EXPORT using connect_t = beman::execution::detail::connect_t;
* `connect(sender, receiver)` returns the result of calling `sender.connect(receiver)`.
* The returned object `state` is an `operation_state` object.
*/
BEMAN_EXECUTION_EXPORT inline constexpr connect_t connect{};
inline constexpr connect_t connect{};
} // namespace beman::execution

// ----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/connect_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ struct connect_all_t {
* \internal
*/
//-dk:TODO the export below shouldn't be needed, but MSVC++ seems to require it (2026-02-01)
BEMAN_EXECUTION_EXPORT constexpr connect_all_t connect_all{}; //-dk:TODO detail export
inline constexpr connect_all_t connect_all{}; //-dk:TODO detail export
} // namespace beman::execution::detail

#include <beman/execution/detail/suppress_pop.hpp>
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/connect_result_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace beman::execution {
* \brief Type alias to determine the operation state type returned from `connect()`.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT template <typename Sender, typename Receiver>
template <typename Sender, typename Receiver>
using connect_result_t = decltype(::beman::execution::connect(::std::declval<Sender>(), ::std::declval<Receiver>()));
} // namespace beman::execution

Expand Down
17 changes: 10 additions & 7 deletions include/beman/execution/detail/continues_on.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ struct continues_on_t {
*/
template <>
struct impls_for<::beman::execution::detail::continues_on_t> : ::beman::execution::detail::default_impls {
static constexpr auto get_attrs{[](const auto& data, const auto& child) noexcept -> decltype(auto) {
return ::beman::execution::detail::join_env(
::beman::execution::detail::sched_attrs(data),
::beman::execution::detail::fwd_env(::beman::execution::get_env(child)));
}};
struct get_attrs_impl {
auto operator()(const auto& data, const auto& child) const noexcept -> decltype(auto) {
return ::beman::execution::detail::join_env(
::beman::execution::detail::sched_attrs(data),
::beman::execution::detail::fwd_env(::beman::execution::get_env(child)));
}
};
static constexpr auto get_attrs{get_attrs_impl{}};
};

/*!
Expand All @@ -87,12 +90,12 @@ auto get_domain_late(Sender&& sender, Env&&) {
#include <beman/execution/detail/suppress_pop.hpp>

namespace beman::execution {
BEMAN_EXECUTION_EXPORT using continues_on_t = ::beman::execution::detail::continues_on_t;
using continues_on_t = ::beman::execution::detail::continues_on_t;
/*!
* \brief Customization point object to create a `continues_on` sender.
* \headerfile beman/execution/execution.hpp <beman/execution/execution.hpp>
*/
BEMAN_EXECUTION_EXPORT inline constexpr continues_on_t continues_on{};
inline constexpr continues_on_t continues_on{};
} // namespace beman::execution

// ----------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion include/beman/execution/detail/counting_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// ----------------------------------------------------------------------------

namespace beman::execution {
BEMAN_EXECUTION_EXPORT class counting_scope;
class counting_scope;
}

// ----------------------------------------------------------------------------
Expand Down
Loading