Skip to content

Commit e4095e0

Browse files
committed
remove needless hops through tag_invoke
1 parent 9f68109 commit e4095e0

29 files changed

Lines changed: 438 additions & 363 deletions

docs/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"sphinx.ext.autodoc",
3737
"sphinx.ext.autosummary",
3838
"sphinx.ext.intersphinx",
39+
"sphinx.ext.graphviz",
3940
"sphinx.ext.mathjax",
4041
"sphinx.ext.napoleon",
4142
"sphinx_copybutton",

include/exec/any_sender_of.hpp

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "../stdexec/execution.hpp"
1919
#include "../stdexec/__detail/__any_receiver_ref.hpp"
20+
#include "../stdexec/__detail/__transform_completion_signatures.hpp"
2021

2122
#include "sequence_senders.hpp"
2223

@@ -250,7 +251,8 @@ namespace exec {
250251
class _Allocator,
251252
bool _Copyable = false,
252253
std::size_t _InlineSize = 3 * sizeof(void*),
253-
std::size_t _Alignment = alignof(std::max_align_t)>
254+
std::size_t _Alignment = alignof(std::max_align_t)
255+
>
254256
struct __storage {
255257
class __t;
256258
};
@@ -259,7 +261,8 @@ namespace exec {
259261
class _Vtable,
260262
class _Allocator,
261263
std::size_t _InlineSize = 3 * sizeof(void*),
262-
std::size_t _Alignment = alignof(std::max_align_t)>
264+
std::size_t _Alignment = alignof(std::max_align_t)
265+
>
263266
struct __immovable_storage {
264267
class __t : __immovable {
265268
static constexpr std::size_t __buffer_size = std::max(_InlineSize, sizeof(void*));
@@ -377,7 +380,8 @@ namespace exec {
377380
class _Allocator,
378381
bool _Copyable,
379382
std::size_t _InlineSize,
380-
std::size_t _Alignment>
383+
std::size_t _Alignment
384+
>
381385
class __storage<_Vtable, _Allocator, _Copyable, _InlineSize, _Alignment>::__t
382386
: __if_c<_Copyable, __, __move_only> {
383387
static_assert(
@@ -396,7 +400,8 @@ namespace exec {
396400
using __vtable_t = __if_c<
397401
_Copyable,
398402
__storage_vtable<_Vtable, __with_delete, __with_move, __with_copy>,
399-
__storage_vtable<_Vtable, __with_delete, __with_move>>;
403+
__storage_vtable<_Vtable, __with_delete, __with_move>
404+
>;
400405

401406
template <class _Tp>
402407
static constexpr auto __get_vtable_of_type() noexcept -> const __vtable_t* {
@@ -407,7 +412,8 @@ namespace exec {
407412
_Vtable,
408413
__with_delete,
409414
__with_move,
410-
__with_copy>;
415+
__with_copy
416+
>;
411417
} else {
412418
return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete, __with_move>;
413419
}
@@ -584,7 +590,8 @@ namespace exec {
584590
class _VTable = __empty_vtable,
585591
class _Allocator = std::allocator<std::byte>,
586592
std::size_t _InlineSize = 3 * sizeof(void*),
587-
std::size_t _Alignment = alignof(std::max_align_t)>
593+
std::size_t _Alignment = alignof(std::max_align_t)
594+
>
588595
using __immovable_storage_t =
589596
__t<__immovable_storage<_VTable, _Allocator, _InlineSize, _Alignment>>;
590597

@@ -594,7 +601,8 @@ namespace exec {
594601
template <
595602
class _VTable,
596603
std::size_t _InlineSize = 3 * sizeof(void*),
597-
class _Allocator = std::allocator<std::byte>>
604+
class _Allocator = std::allocator<std::byte>
605+
>
598606
using __copyable_storage_t = __t<__storage<_VTable, _Allocator, true, _InlineSize>>;
599607

600608
template <class _Tag, class... _As>
@@ -747,7 +755,8 @@ namespace exec {
747755
using _FilteredQueries =
748756
__minvoke<__mremove_if<__q<__is_never_stop_token_query>>, _Queries...>;
749757
using __vtable_t = stdexec::__t<
750-
__mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>, _FilteredQueries>>;
758+
__mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>, _FilteredQueries>
759+
>;
751760

752761
struct __env_t {
753762
const __vtable_t* __vtable_;
@@ -850,7 +859,8 @@ namespace exec {
850859
STDEXEC_ATTRIBUTE(no_unique_address) _Receiver __rcvr_;
851860
stdexec::inplace_stop_source __stop_source_{};
852861
using __stop_callback = typename stdexec::stop_token_of_t<
853-
stdexec::env_of_t<_Receiver>>::template callback_type<__on_stop_t>;
862+
stdexec::env_of_t<_Receiver>
863+
>::template callback_type<__on_stop_t>;
854864
std::optional<__stop_callback> __on_stop_{};
855865
};
856866

@@ -1060,7 +1070,8 @@ namespace exec {
10601070

10611071
template <receiver_of<_Sigs> _Rcvr>
10621072
auto connect(_Rcvr __rcvr) && -> stdexec::__t<
1063-
__operation<stdexec::__id<_Rcvr>, __with_inplace_stop_token>> {
1073+
__operation<stdexec::__id<_Rcvr>, __with_inplace_stop_token>
1074+
> {
10641075
return {static_cast<__t&&>(*this), static_cast<_Rcvr&&>(__rcvr)};
10651076
}
10661077

@@ -1211,19 +1222,15 @@ namespace exec {
12111222
template <auto... _SenderQueries>
12121223
class any_sender {
12131224
using __sender_base = stdexec::__t<
1214-
__any::__sender<_Completions, queries<_SenderQueries...>, queries<_ReceiverQueries...>>>;
1225+
__any::__sender<_Completions, queries<_SenderQueries...>, queries<_ReceiverQueries...>>
1226+
>;
12151227
__sender_base __sender_;
12161228

1217-
template <class _Tag, stdexec::__decays_to<any_sender> Self, class... _As>
1218-
requires stdexec::tag_invocable<_Tag, stdexec::__copy_cvref_t<Self, __sender_base>, _As...>
1219-
friend auto tag_invoke(_Tag, Self&& __self, _As&&... __as) noexcept(
1220-
stdexec::nothrow_tag_invocable<_Tag, stdexec::__copy_cvref_t<Self, __sender_base>, _As...>) {
1221-
return stdexec::tag_invoke(
1222-
_Tag{}, static_cast<Self&&>(__self).__sender_, static_cast<_As&&>(__as)...);
1223-
}
12241229
public:
12251230
using sender_concept = stdexec::sender_t;
12261231
using completion_signatures = typename __sender_base::completion_signatures;
1232+
using __t = any_sender;
1233+
using __id = any_sender;
12271234

12281235
template <stdexec::__not_decays_to<any_sender> _Sender>
12291236
requires stdexec::sender_to<_Sender, __receiver_base>
@@ -1237,12 +1244,17 @@ namespace exec {
12371244
return static_cast<__sender_base&&>(__sender_).connect(static_cast<_Receiver&&>(__rcvr));
12381245
}
12391246

1247+
auto get_env() const noexcept -> stdexec::env_of_t<__sender_base> {
1248+
return static_cast<const __sender_base&>(__sender_).get_env();
1249+
}
1250+
12401251
template <auto... _SchedulerQueries>
12411252
class any_scheduler {
12421253
// Add the required set_value_t() completions to the schedule-sender.
12431254
using __schedule_completions = stdexec::__concat_completion_signatures<
12441255
_Completions,
1245-
stdexec::completion_signatures<stdexec::set_value_t()>>;
1256+
stdexec::completion_signatures<stdexec::set_value_t()>
1257+
>;
12461258
using __schedule_receiver = any_receiver_ref<__schedule_completions, _ReceiverQueries...>;
12471259

12481260
template <typename _Tag, typename _Sig>
@@ -1257,8 +1269,10 @@ namespace exec {
12571269

12581270
using __schedule_sender_queries = stdexec::__minvoke<
12591271
stdexec::__mremove_if<
1260-
__ret_equals_to<stdexec::get_completion_scheduler_t<stdexec::set_value_t>>>,
1261-
decltype(_SenderQueries)...>;
1272+
__ret_equals_to<stdexec::get_completion_scheduler_t<stdexec::set_value_t>>
1273+
>,
1274+
decltype(_SenderQueries)...
1275+
>;
12621276

12631277
#if STDEXEC_MSVC()
12641278
// MSVCBUG https://developercommunity.visualstudio.com/t/ICE-and-non-ICE-bug-in-NTTP-argument-w/10361081
@@ -1271,7 +1285,8 @@ namespace exec {
12711285
#else
12721286
template <class... _Queries>
12731287
using __schedule_sender_fn = typename __schedule_receiver::template any_sender<
1274-
stdexec::get_completion_scheduler<stdexec::set_value_t>.template signature<any_scheduler() noexcept>>;
1288+
stdexec::get_completion_scheduler<stdexec::set_value_t>.template signature<any_scheduler() noexcept>
1289+
>;
12751290
#endif
12761291
using __schedule_sender =
12771292
stdexec::__mapply<stdexec::__q<__schedule_sender_fn>, __schedule_sender_queries>;
@@ -1282,6 +1297,7 @@ namespace exec {
12821297
__scheduler_base __scheduler_;
12831298

12841299
public:
1300+
using scheduler_concept = stdexec::scheduler_t;
12851301
using __t = any_scheduler;
12861302
using __id = any_scheduler;
12871303

@@ -1296,11 +1312,11 @@ namespace exec {
12961312
}
12971313

12981314
template <class _Tag, class... _As>
1299-
requires stdexec::tag_invocable<_Tag, const __scheduler_base&, _As...>
1315+
requires stdexec::__env::__queryable<const __scheduler_base&, _Tag, _As...>
13001316
auto query(_Tag, _As&&... __as) const
1301-
noexcept(stdexec::nothrow_tag_invocable<_Tag, const __scheduler_base&, _As...>)
1302-
-> stdexec::tag_invoke_result_t<_Tag, const __scheduler_base&, _As...> {
1303-
return stdexec::tag_invoke(_Tag(), __scheduler_, static_cast<_As&&>(__as)...);
1317+
noexcept(stdexec::__env::__nothrow_queryable<const __scheduler_base&, _Tag, _As...>)
1318+
-> stdexec::__env::__query_result_t<const __scheduler_base&, _Tag, _As...> {
1319+
return __scheduler_.query(_Tag{}, static_cast<_As&&>(__as)...);
13041320
}
13051321

13061322
auto operator==(const any_scheduler&) const noexcept -> bool = default;

include/exec/linux/io_uring_context.hpp

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,17 +1079,15 @@ namespace exec {
10791079
public:
10801080
__context* __context_;
10811081

1082-
friend auto operator==(const __scheduler& __lhs, const __scheduler& __rhs) -> bool = default;
1082+
auto operator==(const __scheduler&) const -> bool = default;
10831083

1084-
class __schedule_env {
1085-
public:
1086-
__context* __context_;
1087-
private:
1088-
friend auto tag_invoke(
1089-
stdexec::get_completion_scheduler_t<stdexec::set_value_t>,
1090-
const __schedule_env& __env) noexcept -> __scheduler {
1091-
return __scheduler{__env.__context_};
1084+
struct __schedule_env {
1085+
[[nodiscard]] auto
1086+
query(stdexec::get_completion_scheduler_t<stdexec::set_value_t>) const noexcept -> __scheduler {
1087+
return __scheduler{__context_};
10921088
}
1089+
1090+
__context* __context_;
10931091
};
10941092

10951093
class __schedule_sender {
@@ -1164,25 +1162,22 @@ namespace exec {
11641162
return __schedule_sender{__schedule_env{__context_}};
11651163
}
11661164

1167-
friend auto tag_invoke(exec::now_t, const __scheduler&) noexcept
1168-
-> std::chrono::time_point<std::chrono::steady_clock> {
1165+
[[nodiscard]]
1166+
auto now() const noexcept -> std::chrono::time_point<std::chrono::steady_clock> {
11691167
return std::chrono::steady_clock::now();
11701168
}
11711169

1172-
friend auto tag_invoke(
1173-
exec::schedule_after_t,
1174-
const __scheduler& __sched,
1175-
std::chrono::nanoseconds __duration) -> __schedule_after_sender {
1176-
return __schedule_after_sender{.__env_ = {__sched.__context_}, .__duration_ = __duration};
1170+
[[nodiscard]]
1171+
auto schedule_after(std::chrono::nanoseconds __duration) const -> __schedule_after_sender {
1172+
return __schedule_after_sender{.__env_ = {__context_}, .__duration_ = __duration};
11771173
}
11781174

11791175
template <class _Clock, class _Duration>
1180-
friend auto tag_invoke(
1181-
exec::schedule_at_t,
1182-
const __scheduler& __sched,
1183-
const std::chrono::time_point<_Clock, _Duration>& __time_point) -> __schedule_after_sender {
1176+
[[nodiscard]]
1177+
auto schedule_at(const std::chrono::time_point<_Clock, _Duration>& __time_point) const
1178+
-> __schedule_after_sender {
11841179
auto __duration = __time_point - _Clock::now();
1185-
return __schedule_after_sender{.__env_ = {__sched.__context_}, .__duration_ = __duration};
1180+
return __schedule_after_sender{.__env_ = {__context_}, .__duration_ = __duration};
11861181
}
11871182
};
11881183

@@ -1194,6 +1189,9 @@ namespace exec {
11941189
using __io_uring::until;
11951190
using io_uring_context = __io_uring::__context;
11961191
using io_uring_scheduler = __io_uring::__scheduler;
1192+
1193+
static_assert(__timed_scheduler<io_uring_scheduler>);
1194+
11971195
} // namespace exec
11981196

11991197
# endif // if __has_include(<linux/verison.h>)

include/exec/on.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ namespace exec {
2323
using on_t [[deprecated("on_t has been moved to the stdexec:: namespace")]] = stdexec::on_t;
2424

2525
[[deprecated("on has been moved to the stdexec:: namespace")]]
26-
inline constexpr on_t const& on = stdexec::on;
26+
inline constexpr stdexec::on_t const & on = stdexec::on;
2727
} // namespace exec

include/exec/sequence/any_sequence_of.hpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,8 @@ namespace exec {
335335
using __sender_base = stdexec::__t<__any::__sequence_sender<
336336
_Completions,
337337
queries<_SenderQueries...>,
338-
queries<_ReceiverQueries...>>>;
338+
queries<_ReceiverQueries...>
339+
>>;
339340
__sender_base __sender_;
340341

341342
public:
@@ -352,11 +353,9 @@ namespace exec {
352353
: __sender_(static_cast<_Sender&&>(__sender)) {
353354
}
354355

355-
template <stdexec::same_as<__t> _Self, sequence_receiver_of<item_types> _Rcvr>
356-
friend auto tag_invoke(exec::subscribe_t, _Self&& __self, _Rcvr __rcvr)
357-
-> subscribe_result_t<__sender_base, _Rcvr> {
358-
return exec::subscribe(
359-
static_cast<__sender_base&&>(__self.__sender_), static_cast<_Rcvr&&>(__rcvr));
356+
template <sequence_receiver_of<item_types> _Rcvr>
357+
auto subscribe(_Rcvr __rcvr) && -> subscribe_result_t<__sender_base, _Rcvr> {
358+
return exec::subscribe(static_cast<__sender_base&&>(__sender_), static_cast<_Rcvr&&>(__rcvr));
360359
}
361360

362361
auto get_env() const noexcept -> stdexec::env_of_t<__sender_base> {

include/exec/sequence/transform_each.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ namespace exec {
4141
using __id = __receiver;
4242
__operation_base<_Receiver, _Adaptor>* __op_;
4343

44-
template <same_as<set_next_t> _SetNext, same_as<__t> _Self, class _Item>
44+
template <class _Item>
4545
requires __callable<_Adaptor&, _Item>
4646
&& __callable<exec::set_next_t, _Receiver&, __call_result_t<_Adaptor&, _Item>>
47-
friend auto tag_invoke(_SetNext, _Self& __self, _Item&& __item) noexcept(
48-
__nothrow_callable<_SetNext, _Receiver&, __call_result_t<_Adaptor&, _Item>>
47+
auto set_next(_Item&& __item) & noexcept(
48+
__nothrow_callable<set_next_t, _Receiver&, __call_result_t<_Adaptor&, _Item>>
4949
&& __nothrow_callable<_Adaptor&, _Item>)
5050
-> next_sender_of_t<_Receiver, __call_result_t<_Adaptor&, _Item>> {
5151
return exec::set_next(
52-
__self.__op_->__receiver_, __self.__op_->__adaptor_(static_cast<_Item&&>(__item)));
52+
__op_->__receiver_, __op_->__adaptor_(static_cast<_Item&&>(__item)));
5353
}
5454

5555
void set_value() noexcept {

0 commit comments

Comments
 (0)