Commit 059ca1b2 authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

remove executor category properties; refactor, simplify, remove concepts.

Summary:
Now that we have `.schedule()`, We can syntactically determine what things are executors and which are not. We can also tell what kind of executor, be it constrained, or time, or neither. Therefore, we no longer need the `is_executor<>` property query. Nuke it.

In addition, all the `Sender`, `Receiver`, and `Executor` concepts, in addition to testing for the required syntac, took an arbitrary number of properties to query. Those were breaking subsumption relationships (e.g., `Sender<From, is_many<>>` doesn't subsume `Sender<From>`). Move those property queries out of the concept heirarchy and into separate algorithm requirements that test the properties directly.

Reviewed By: kirkshoop

Differential Revision: D14570712

fbshipit-source-id: 8ae0d96e5c9f00dcea3fbff4bbbe04c71bb0df07
parent 323f42e1
......@@ -84,10 +84,7 @@ using countdownmany = countdown<decltype(mi::make_receiver)>;
using countdownflowmany = countdown<decltype(mi::make_flow_receiver)>;
struct inline_time_executor {
using properties = mi::property_set<
mi::is_executor<>,
mi::is_time<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
std::chrono::system_clock::time_point at;
......@@ -116,9 +113,7 @@ struct inline_time_executor {
};
struct inline_executor {
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
using properties = mi::property_set<
......@@ -141,9 +136,7 @@ template <class CancellationFactory>
struct inline_executor_flow_single {
CancellationFactory cf;
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
CancellationFactory cf;
......@@ -225,9 +218,7 @@ using inline_executor_flow_single_entangled =
inline_executor_flow_single<entangled_cancellation_factory>;
struct inline_executor_flow_single_ignore {
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
using properties = mi::property_set<
......@@ -256,9 +247,7 @@ struct inline_executor_flow_many {
std::atomic<int>* counter = nullptr;
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
std::atomic<int>* counter = nullptr;
......@@ -322,9 +311,7 @@ struct inline_executor_flow_many {
};
struct inline_executor_flow_many_ignore {
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
using properties = mi::property_set<
......@@ -347,9 +334,7 @@ struct inline_executor_flow_many_ignore {
};
struct inline_executor_many {
using properties = mi::property_set<
mi::is_executor<>,
mi::is_fifo_sequence<>>;
using properties = mi::property_set<mi::is_fifo_sequence<>>;
struct task {
using properties = mi::property_set<
......
This diff is collapsed.
......@@ -32,7 +32,7 @@ class pool_executor {
public:
using properties =
property_set<is_executor<>, is_concurrent_sequence<>>;
property_set<is_concurrent_sequence<>>;
pool_executor() = default;
explicit pool_executor(pool &e);
......
......@@ -103,7 +103,7 @@ class any_executor {
std::enable_if_t<!std::is_same<U, any_executor>::value, U>;
public:
using properties = property_set<is_executor<>>;
using properties = property_set<>;
any_executor() = default;
any_executor(const any_executor& that) noexcept : any_executor() {
......@@ -147,7 +147,7 @@ class executor<SF> {
SF sf_;
public:
using properties = property_set<is_executor<>>;
using properties = property_set<>;
constexpr executor() = default;
constexpr explicit executor(SF sf) : sf_(std::move(sf)) {}
......@@ -167,9 +167,7 @@ class executor<Data, DSF> {
DSF sf_;
public:
using properties = property_set_insert_t<
properties_t<Data>,
property_set<is_executor<>>>;
using properties = properties_t<Data>;
constexpr executor() = default;
constexpr explicit executor(Data data) : data_(std::move(data)) {}
......@@ -257,7 +255,7 @@ struct any_executor_ref {
using wrapped_t = detail::not_any_executor_ref_t<T>;
public:
using properties = property_set<is_executor<>>;
using properties = property_set<>;
any_executor_ref() = delete;
any_executor_ref(const any_executor_ref&) = default;
......@@ -416,7 +414,7 @@ class any_constrained_executor {
std::enable_if_t<!std::is_same<U, any_constrained_executor>::value, U>;
public:
using properties = property_set<is_constrained<>>;
using properties = property_set<>;
any_constrained_executor() = default;
any_constrained_executor(const any_constrained_executor& that) noexcept
......@@ -469,7 +467,7 @@ class constrained_executor<SF, ZF> {
ZF zf_;
public:
using properties = property_set<is_constrained<>>;
using properties = property_set<>;
constexpr constrained_executor() = default;
constexpr explicit constrained_executor(SF sf) : sf_(std::move(sf)) {}
......@@ -496,9 +494,7 @@ class constrained_executor<Data, DSF, DZF> {
DZF zf_;
public:
using properties = property_set_insert_t<
properties_t<Data>,
property_set<is_constrained<>>>;
using properties = properties_t<Data>;
constexpr constrained_executor() = default;
constexpr explicit constrained_executor(Data data) : data_(std::move(data)) {}
......@@ -617,7 +613,7 @@ struct any_constrained_executor_ref {
using wrapped_t = detail::not_any_constrained_executor_ref_t<T>;
public:
using properties = property_set<is_constrained<>>;
using properties = property_set<>;
any_constrained_executor_ref() = delete;
any_constrained_executor_ref(const any_constrained_executor_ref&) = default;
......@@ -792,7 +788,7 @@ class any_time_executor {
std::enable_if_t<!std::is_same<U, any_time_executor>::value, U>;
public:
using properties = property_set<is_time<>>;
using properties = property_set<>;
any_time_executor() = default;
any_time_executor(const any_time_executor& that) noexcept : any_time_executor() {
......@@ -843,7 +839,7 @@ class time_executor<SF, NF> {
NF nf_;
public:
using properties = property_set<is_time<>>;
using properties = property_set<>;
constexpr time_executor() = default;
constexpr explicit time_executor(SF sf) : sf_(std::move(sf)) {}
......@@ -870,9 +866,7 @@ class time_executor<Data, DSF, DNF> {
DNF nf_;
public:
using properties = property_set_insert_t<
properties_t<Data>,
property_set<is_time<>>>;
using properties = properties_t<Data>;
constexpr time_executor() = default;
constexpr explicit time_executor(Data data) : data_(std::move(data)) {}
......@@ -991,7 +985,7 @@ struct any_time_executor_ref {
using wrapped_t = detail::not_any_time_executor_ref_t<T>;
public:
using properties = property_set<is_time<>>;
using properties = property_set<>;
any_time_executor_ref() = delete;
any_time_executor_ref(const any_time_executor_ref&) = default;
......
......@@ -91,7 +91,7 @@ class any_flow_many_sender {
std::swap(that.vptr_, vptr_);
}
PUSHMI_TEMPLATE (class Wrapped)
(requires FlowSender<wrapped_t<Wrapped>, is_many<>>)
(requires FlowSender<wrapped_t<Wrapped>> && is_many_v<wrapped_t<Wrapped>>)
explicit any_flow_many_sender(Wrapped obj) noexcept(insitu<Wrapped>())
: any_flow_many_sender{std::move(obj), bool_<insitu<Wrapped>()>{}} {}
~any_flow_many_sender() {
......@@ -173,12 +173,12 @@ PUSHMI_INLINE_VAR constexpr struct make_flow_many_sender_fn {
return flow_many_sender<SF>{std::move(sf)};
}
PUSHMI_TEMPLATE(class Data)
(requires True<> && Sender<Data, is_many<>, is_flow<>>)
(requires True<> && FlowSender<Data> && is_many_v<Data>)
auto operator()(Data d) const {
return flow_many_sender<Data, passDSF>{std::move(d)};
}
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_many<>, is_flow<>>)
(requires FlowSender<Data> && is_many_v<Data>)
auto operator()(Data d, DSF sf) const {
return flow_many_sender<Data, DSF>{std::move(d), std::move(sf)};
}
......@@ -194,11 +194,11 @@ PUSHMI_TEMPLATE(class SF)
flow_many_sender(SF) -> flow_many_sender<SF>;
PUSHMI_TEMPLATE(class Data)
(requires True<> && Sender<Data, is_many<>, is_flow<>>)
(requires True<> && FlowSender<Data> && is_many_v<Data>)
flow_many_sender(Data) -> flow_many_sender<Data, passDSF>;
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_many<>, is_flow<>>)
(requires FlowSender<Data> && is_many_v<Data>)
flow_many_sender(Data, DSF) -> flow_many_sender<Data, DSF>;
#endif
......
......@@ -319,7 +319,7 @@ class flow_receiver<>
PUSHMI_CONCEPT_DEF(
template (class T)
concept FlowReceiverDataArg,
Receiver<T, is_flow<>> &&
FlowReceiver<T> &&
not Invocable<T&>
);
......
......@@ -98,7 +98,7 @@ class any_flow_single_sender {
std::swap(that.vptr_, vptr_);
}
PUSHMI_TEMPLATE (class Wrapped)
(requires FlowSender<wrapped_t<Wrapped>, is_single<>>)
(requires FlowSender<wrapped_t<Wrapped>> &&is_single_v<wrapped_t<Wrapped>>)
explicit any_flow_single_sender(Wrapped obj) noexcept(insitu<Wrapped>())
: any_flow_single_sender{std::move(obj), bool_<insitu<Wrapped>()>{}} {}
~any_flow_single_sender() {
......@@ -184,12 +184,12 @@ PUSHMI_INLINE_VAR constexpr struct make_flow_single_sender_fn {
return flow_single_sender<SF>{std::move(sf)};
}
PUSHMI_TEMPLATE(class Data)
(requires True<> && Sender<Data, is_single<>, is_flow<>>)
(requires True<> && FlowSender<Data> && is_single_v<Data>)
auto operator()(Data d) const {
return flow_single_sender<Data, passDSF>{std::move(d)};
}
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_single<>, is_flow<>>)
(requires FlowSender<Data> && is_single_v<Data>)
auto operator()(Data d, DSF sf) const {
return flow_single_sender<Data, DSF>{std::move(d), std::move(sf)};
}
......@@ -205,11 +205,11 @@ PUSHMI_TEMPLATE(class SF)
flow_single_sender(SF) -> flow_single_sender<SF>;
PUSHMI_TEMPLATE(class Data)
(requires True<> && Sender<Data, is_single<>, is_flow<>>)
(requires True<> && FlowSender<Data> && is_single_v<Data>)
flow_single_sender(Data) -> flow_single_sender<Data, passDSF>;
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_single<>, is_flow<>>)
(requires FlowSender<Data> && is_single_v<Data>)
flow_single_sender(Data, DSF) -> flow_single_sender<Data, DSF>;
#endif
......
......@@ -48,14 +48,6 @@ struct is_receiver;
template <class... TN>
struct is_sender;
template <class... TN>
struct is_executor;
template <class... TN>
struct is_time;
template <class... TN>
struct is_constrained;
template <class... TN>
struct is_always_blocking;
......
......@@ -22,9 +22,7 @@ namespace pushmi {
class inline_constrained_executor_t {
public:
using properties = property_set<
is_constrained<>,
is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
template<class CV>
struct task {
......@@ -65,9 +63,7 @@ inline inline_constrained_executor_t inline_constrained_executor() {
class inline_time_executor_t {
public:
using properties = property_set<
is_time<>,
is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
template<class TP>
struct task {
......@@ -110,9 +106,7 @@ inline inline_time_executor_t inline_time_executor() {
class inline_executor_t {
public:
using properties = property_set<
is_executor<>,
is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
struct task {
using properties = property_set<
......
......@@ -91,10 +91,8 @@ class any_many_sender {
}
PUSHMI_TEMPLATE(class Wrapped)
(requires SenderTo<
wrapped_t<Wrapped>,
any_receiver<E, VN...>,
is_many<>>) //
(requires SenderTo<wrapped_t<Wrapped>, any_receiver<E, VN...>> &&
is_many_v<wrapped_t<Wrapped>>) //
explicit any_many_sender(Wrapped obj) //
noexcept(insitu<Wrapped>())
: any_many_sender{std::move(obj), bool_<insitu<Wrapped>()>{}} {}
......@@ -184,13 +182,13 @@ PUSHMI_INLINE_VAR constexpr struct make_many_sender_fn {
return many_sender<SF>{std::move(sf)};
}
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Sender<Data, is_many<>>) //
(requires True<>&& Sender<Data> && is_many_v<Data>) //
auto
operator()(Data d) const {
return many_sender<Data, passDSF>{std::move(d)};
}
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_many<>>) //
(requires Sender<Data> && is_many_v<Data>) //
auto
operator()(Data d, DSF sf) const {
return many_sender<Data, DSF>{std::move(d), std::move(sf)};
......@@ -208,12 +206,12 @@ PUSHMI_TEMPLATE(class SF)
->many_sender<SF>;
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Sender<Data, is_many<>>) //
(requires True<>&& Sender<Data> && is_many_v<Data>) //
many_sender(Data)
->many_sender<Data, passDSF>;
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_many<>>) //
(requires Sender<Data> && is_many_v<Data>) //
many_sender(Data, DSF)
->many_sender<Data, DSF>;
#endif
......
......@@ -45,7 +45,7 @@ struct new_thread_task {
};
struct new_thread_executor {
using properties = property_set<is_executor<>, is_concurrent_sequence<>>;
using properties = property_set<is_concurrent_sequence<>>;
new_thread_task schedule() {
return {};
......
......@@ -75,7 +75,7 @@ struct for_each_fn {
struct fn {
std::tuple<AN...> args_;
PUSHMI_TEMPLATE(class In)
(requires Sender<In>&& Flow<In>&& Many<In>)
(requires FlowSender<In>&& is_many_v<In>)
In operator()(In in) {
auto out{::folly::pushmi::detail::receiver_from_fn<subset<
is_sender<>,
......
......@@ -120,16 +120,22 @@ struct blocking_submit_fn {
using properties = properties_t<Exec>;
PUSHMI_TEMPLATE(class... ZN)
(requires Constrained<Exec>) //
auto top() {
PUSHMI_TEMPLATE(class Exec_ = Exec)
(requires ConstrainedExecutor<Exec_>) //
auto top() {
return ::folly::pushmi::top(ex_);
}
template<class... VN>
auto schedule(VN&&... vn) {
auto schedule() {
auto protected_scope = protect_stack{state_};
return nested_task_impl<decltype(::folly::pushmi::schedule(ex_, (VN&&)vn...))>{
state_, ::folly::pushmi::schedule(ex_, (VN&&)vn...)};
return nested_task_impl<decltype(::folly::pushmi::schedule(ex_))>{
state_, ::folly::pushmi::schedule(ex_)};
}
PUSHMI_TEMPLATE(class Exec_ = Exec)
(requires ConstrainedExecutor<Exec_>) //
auto schedule(constraint_t<Exec_> top) {
auto protected_scope = protect_stack{state_};
return nested_task_impl<sender_t<Exec_, constraint_t<Exec_>>>{
state_, ::folly::pushmi::schedule(ex_, std::move(top))};
}
};
......@@ -272,7 +278,7 @@ struct blocking_submit_fn {
receiver_impl<std::decay_t<In>>&,
lock_state*,
std::tuple<AN...>&&>> &&
not AlwaysBlocking<In>) //
not is_always_blocking_v<In>) //
void
operator()(In&& in) {
lock_state state{};
......@@ -331,8 +337,10 @@ struct get_fn {
static_assert(
SenderTo<In, Out>,
"'In' does not deliver value compatible with 'T' to 'Out'");
std::conditional_t<AlwaysBlocking<In>, submit_fn, blocking_submit_fn>{}(
std::move(out))(std::move(in));
std::conditional_t<
is_always_blocking_v<In>,
submit_fn,
blocking_submit_fn>{}(std::move(out))(std::move(in));
if (!!ep_) {
std::rethrow_exception(*ep_);
}
......
......@@ -71,8 +71,7 @@ struct transform_on<F, is_single<>, true> {
::folly::pushmi::SemiMovable<Result>,
"none of the functions supplied to transform can convert this value");
static_assert(
::folly::pushmi::Flow<Out> &&
::folly::pushmi::ReceiveValue<Out, Result>,
::folly::pushmi::FlowReceiveValue<Out, Result>,
"Result of value transform cannot be delivered to Out");
set_value(out, f_((V0 &&) v0, (VN &&) vn...));
}
......@@ -116,8 +115,7 @@ struct transform_on<F, is_many<>, true> {
::folly::pushmi::SemiMovable<Result>,
"none of the functions supplied to transform can convert this value");
static_assert(
::folly::pushmi::Flow<Out> &&
::folly::pushmi::ReceiveValue<Out, Result>,
::folly::pushmi::FlowReceiveValue<Out, Result>,
"Result of value transform cannot be delivered to Out");
set_value(out, f_((V0 &&) v0, (VN &&) vn...));
}
......
......@@ -497,7 +497,7 @@ template<>
struct construct_deduced<receiver> : make_receiver_fn {};
PUSHMI_TEMPLATE (class T, class In)
(requires SenderTo<In, std::promise<T>, is_single<>>)
(requires SenderTo<In, std::promise<T>> && is_single_v<In>)
std::future<T> future_from(In&& in) {
std::promise<T> p;
auto result = p.get_future();
......@@ -505,7 +505,7 @@ std::future<T> future_from(In&& in) {
return result;
}
PUSHMI_TEMPLATE (class In)
(requires SenderTo<In, std::promise<void>, is_single<>>)
(requires SenderTo<In, std::promise<void>> && is_single_v<In>)
std::future<void> future_from(In&& in) {
std::promise<void> p;
auto result = p.get_future();
......
......@@ -218,13 +218,13 @@ PUSHMI_INLINE_VAR constexpr struct make_single_sender_fn {
return single_sender<SF>{std::move(sf)};
}
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Sender<Data, is_single<>>) //
(requires True<>&& Sender<Data> && is_single_v<Data>) //
auto
operator()(Data d) const {
return single_sender<Data, passDSF>{std::move(d)};
}
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_single<>>) //
(requires Sender<Data> && is_single_v<Data>) //
auto
operator()(Data d, DSF sf) const {
return single_sender<Data, DSF>{std::move(d), std::move(sf)};
......@@ -242,12 +242,12 @@ PUSHMI_TEMPLATE(class SF)
->single_sender<SF>;
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Sender<Data, is_single<>>) //
(requires True<>&& Sender<Data> && is_single_v<Data>) //
single_sender(Data)
->single_sender<Data, passDSF>;
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Sender<Data, is_single<>>) //
(requires Sender<Data> && is_single_v<Data>) //
single_sender(Data, DSF)
->single_sender<Data, DSF>;
#endif
......
......@@ -210,7 +210,7 @@ class strand_executor {
std::shared_ptr<strand_queue<E, Exec>> queue_;
public:
using properties = property_set<is_executor<>, is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
strand_executor(std::shared_ptr<strand_queue<E, Exec>> queue)
: queue_(std::move(queue)) {}
......@@ -239,12 +239,12 @@ class same_strand_factory_fn {
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Provider)
(requires ExecutorProvider<Provider>&&
ConcurrentSequence<executor_t<Provider>>) //
is_concurrent_sequence_v<executor_t<Provider>>) //
auto strands(Provider ep) {
return same_strand_factory_fn<E, executor_t<Provider>>{get_executor(ep)};
}
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Exec)
(requires Executor<Exec>&& ConcurrentSequence<Exec>) //
(requires Executor<Exec>&& is_concurrent_sequence_v<Exec>) //
auto strands(Exec ex) {
return same_strand_factory_fn<E, Exec>{std::move(ex)};
}
......
......@@ -39,14 +39,14 @@ TEST(EmptySingleSender, TapAndSubmit) {
auto e = op::empty();
using E = decltype(e);
EXPECT_THAT((v::SenderTo<E, v::any_receiver<>, v::is_single<>>), Eq(true))
EXPECT_THAT((v::SenderTo<E, v::any_receiver<>> && v::is_single_v<E>), Eq(true))
<< "expected empty to return a single sender that can take an any_receiver<>";
EXPECT_THAT(
(v::SenderTo<
E,
v::any_receiver<std::exception_ptr, int>,
v::is_single<>>),
v::any_receiver<std::exception_ptr, int>> &&
v::is_single_v<E>),
Eq(true))
<< "expected empty to return a single sender that can take an any_receiver<int>";
......@@ -80,8 +80,8 @@ TEST(JustIntSingleSender, TransformAndSubmit) {
EXPECT_THAT(
(v::SenderTo<
J,
v::any_receiver<std::exception_ptr, int>,
v::is_single<>>),
v::any_receiver<std::exception_ptr, int>> &&
v::is_single_v<J>),
Eq(true))
<< "expected empty to return a single sender that can take an any_receiver<int>";
......@@ -131,7 +131,7 @@ TEST(FromIntManySender, TransformAndSubmit) {
using M = decltype(m);
EXPECT_THAT(
(v::SenderTo<M, v::any_receiver<std::exception_ptr, int>, v::is_many<>>),
(v::SenderTo<M, v::any_receiver<std::exception_ptr, int>> && v::is_many_v<M>),
Eq(true))
<< "expected empty to return a many sender that can take an any_receiver<int>";
......
......@@ -481,8 +481,7 @@ class time_source_executor {
std::shared_ptr<time_source_queue<E, time_point, NF, Exec>> queue_;
public:
using properties = property_set<is_time<>,
is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
time_source_executor(
std::shared_ptr<time_source_shared<E, time_point>> source,
......@@ -583,14 +582,16 @@ class time_source {
}
PUSHMI_TEMPLATE(class NF, class Factory)
(requires StrandFactory<Factory> && not Executor<Factory> && not ExecutorProvider<Factory>) //
(requires StrandFactory<Factory> && not Executor<Factory> &&
not ExecutorProvider<Factory>) //
auto make(NF nf, Factory ef) {
return time_source_executor_factory_fn<E, time_point, NF, Factory>{
source_, std::move(nf), std::move(ef)};
}
PUSHMI_TEMPLATE(class NF, class Provider)
(requires ExecutorProvider<Provider>&&
NeverBlocking<sender_t<executor_t<Provider>>> && not StrandFactory<Provider>) //
is_never_blocking_v<sender_t<executor_t<Provider>>> &&
not StrandFactory<Provider>) //
auto make(NF nf, Provider ep) {
auto ex = ::folly::pushmi::get_executor(ep);
auto queue =
......@@ -601,7 +602,7 @@ class time_source {
}
PUSHMI_TEMPLATE(class NF, class Exec)
(requires Executor<Exec>&&
NeverBlocking<sender_t<Exec>> && not StrandFactory<Exec>) //
is_never_blocking_v<sender_t<Exec>> && not StrandFactory<Exec>) //
auto make(NF nf, Exec ex) {
auto queue =
std::make_shared<time_source_queue<E, time_point, NF, Exec>>(
......
......@@ -67,7 +67,7 @@ struct trampoline_task {
template <class E = std::exception_ptr>
class delegator : pipeorigin {
public:
using properties = property_set<is_executor<>, is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
trampoline_task<E, ownordelegate_t> schedule() {
return {};
......@@ -77,7 +77,7 @@ class delegator : pipeorigin {
template <class E = std::exception_ptr>
class nester : pipeorigin {
public:
using properties = property_set<is_executor<>, is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
trampoline_task<E, ownornest_t> schedule() {
return {};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment