@@ -28,6 +28,7 @@ import stdexec;
2828#else
2929# include " ../stdexec/__detail/__execution_fwd.hpp"
3030
31+ # include " ../stdexec/__detail/__bulk.hpp"
3132# include " ../stdexec/__detail/__connect.hpp"
3233# include " ../stdexec/__detail/__env.hpp"
3334# include " ../stdexec/__detail/__meta.hpp"
@@ -81,7 +82,9 @@ namespace experimental::execution
8182
8283 struct domain : STDEXEC ::default_domain
8384 {
84- template <sender_for<STDEXEC ::bulk_chunked_t > Sender, class Env >
85+ template <class Sender , class Env >
86+ requires sender_for<Sender, STDEXEC ::bulk_chunked_t >
87+ || sender_for<Sender, STDEXEC ::bulk_unchunked_t >
8588 static constexpr auto transform_sender (STDEXEC ::set_value_t , Sender&& sndr, Env const & env)
8689 {
8790 auto & [tag, data, child] = sndr;
@@ -91,12 +94,33 @@ namespace experimental::execution
9194 {
9295 auto sch =
9396 STDEXEC ::get_completion_scheduler<STDEXEC ::set_value_t >(STDEXEC::get_env (child), env);
94- using sender_t =
95- scheduler::template bulk_sender_t <decltype (child), decltype (shape), decltype (fun)>;
96- return sender_t {*sch.pool_ ,
97- STDEXEC ::__forward_like<Sender>(child),
98- shape,
99- STDEXEC ::__forward_like<Sender>(fun)};
97+
98+ using policy_type = STDEXEC ::__decay_t <decltype (pol.__get ())>;
99+ constexpr bool parallelize =
100+ STDEXEC ::__same_as<policy_type, STDEXEC ::parallel_policy>
101+ || STDEXEC ::__same_as<policy_type, STDEXEC ::parallel_unsequenced_policy>;
102+
103+ if constexpr (sender_for<Sender, STDEXEC ::bulk_chunked_t >)
104+ {
105+ using sender_t =
106+ scheduler::template bulk_sender_t <decltype (child), decltype (shape), decltype (fun)>;
107+ return sender_t {*sch.pool_ ,
108+ STDEXEC ::__forward_like<Sender>(child),
109+ shape,
110+ STDEXEC ::__forward_like<Sender>(fun),
111+ parallelize};
112+ }
113+ else
114+ {
115+ using fun_t = STDEXEC ::__bulk::__as_bulk_chunked_fn<STDEXEC ::__decay_t <decltype (fun)>>;
116+ using sender_t =
117+ scheduler::template bulk_sender_t <decltype (child), decltype (shape), fun_t >;
118+ return sender_t {*sch.pool_ ,
119+ STDEXEC ::__forward_like<Sender>(child),
120+ shape,
121+ fun_t {STDEXEC ::__forward_like<Sender>(fun)},
122+ parallelize};
123+ }
100124 }
101125 else
102126 {
@@ -110,9 +134,6 @@ namespace experimental::execution
110134 STDEXEC::_WITH_ENVIRONMENT_ (Env)>();
111135 }
112136 }
113-
114- template <sender_for<STDEXEC ::bulk_unchunked_t > Sender, class Env >
115- static constexpr auto transform_sender (STDEXEC ::set_value_t , Sender&& sndr, Env const & env);
116137 };
117138
118139 struct scheduler
@@ -197,6 +218,7 @@ namespace experimental::execution
197218 Receiver rcvr_;
198219 Shape shape_;
199220 Fun fun_;
221+ bool parallelize_;
200222
201223 std::atomic<std::uint32_t > finished_threads_{0 };
202224 std::atomic<std::uint32_t > thread_with_exception_{0 };
@@ -205,6 +227,11 @@ namespace experimental::execution
205227 [[nodiscard]]
206228 auto num_agents_required () const -> std::uint32_t
207229 {
230+ if (!parallelize_)
231+ {
232+ return 1 ;
233+ }
234+
208235 // With work stealing, is std::min necessary, or can we feel free to ask for more agents (tasks)
209236 // than we can actually deal with at one time?
210237 return static_cast <std::uint32_t >(
@@ -219,11 +246,16 @@ namespace experimental::execution
219246 data_);
220247 }
221248
222- explicit bulk_shared_state (DerivedPoolType& pool, Receiver rcvr, Shape shape, Fun fun)
249+ explicit bulk_shared_state (DerivedPoolType& pool,
250+ Receiver rcvr,
251+ Shape shape,
252+ Fun fun,
253+ bool parallelize)
223254 : pool_(pool)
224255 , rcvr_{static_cast <Receiver&&>(rcvr)}
225256 , shape_{shape}
226257 , fun_{fun}
258+ , parallelize_{parallelize}
227259 , thread_with_exception_{num_agents_required ()}
228260 {
229261 this ->execute_ = [](_pool_::task_base* t, std::uint32_t tid) noexcept
@@ -379,8 +411,13 @@ namespace experimental::execution
379411 STDEXEC::start (inner_op_);
380412 }
381413
382- bulk_opstate (DerivedPoolType& pool, Shape shape, Fun fun, CvSender&& sndr, Receiver rcvr)
383- : shared_state_(pool, static_cast <Receiver&&>(rcvr), shape, fun)
414+ bulk_opstate (DerivedPoolType& pool,
415+ Shape shape,
416+ Fun fun,
417+ bool parallelize,
418+ CvSender&& sndr,
419+ Receiver rcvr)
420+ : shared_state_(pool, static_cast <Receiver&&>(rcvr), shape, fun, parallelize)
384421 , inner_op_{STDEXEC::connect (static_cast <CvSender&&>(sndr), bulk_rcvr{shared_state_})}
385422 {}
386423
@@ -414,11 +451,16 @@ namespace experimental::execution
414451 using bulk_opstate_t =
415452 bulk_opstate<STDEXEC ::__copy_cvref_t <Self, Sender>, Receiver, Shape, Fun>;
416453
417- explicit bulk_sender (DerivedPoolType& pool, Sender sndr, Shape shape, Fun fun)
454+ explicit bulk_sender (DerivedPoolType& pool,
455+ Sender sndr,
456+ Shape shape,
457+ Fun fun,
458+ bool parallelize)
418459 : pool_(pool)
419460 , sndr_(std::move(sndr))
420461 , shape_(shape)
421462 , fun_(std::move(fun))
463+ , parallelize_(parallelize)
422464 {}
423465
424466 template <STDEXEC ::__decays_to<bulk_sender> Self, STDEXEC ::receiver Receiver>
@@ -436,6 +478,7 @@ namespace experimental::execution
436478 return bulk_opstate_t <Self, Receiver>{self.pool_ ,
437479 self.shape_ ,
438480 static_cast <Self&&>(self).fun_ ,
481+ self.parallelize_ ,
439482 static_cast <Self&&>(self).sndr_ ,
440483 static_cast <Receiver&&>(rcvr)};
441484 }
@@ -473,6 +516,7 @@ namespace experimental::execution
473516 Sender sndr_;
474517 Shape shape_;
475518 Fun fun_;
519+ bool parallelize_;
476520 };
477521
478522 template <STDEXEC ::sender Sender, std::integral Shape, class Fun >
0 commit comments