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<
......
......@@ -33,10 +33,6 @@ template <class PS>
struct has_cardinality : category_query<PS, cardinality_category> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool has_cardinality_v = has_cardinality<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Cardinality, //
has_cardinality_v<PS>);
// flow affects both sender and receiver
......@@ -48,12 +44,6 @@ struct receiver_category {};
struct sender_category {};
// for executors
// time and constrained are mutually exclusive refinements of executor (time is
// a special case of constrained and may be folded in later)
struct executor_category {};
// blocking affects senders
struct blocking_category {};
......@@ -62,7 +52,7 @@ struct blocking_category {};
struct sequence_category {};
// Single trait and tag
// is_single trait and tag
template <class... TN>
struct is_single;
// Tag
......@@ -75,12 +65,8 @@ template <class PS>
struct is_single<PS> : property_query<PS, is_single<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_single_v = is_single<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Single, //
is_single_v<PS>);
// Many trait and tag
// is_many trait and tag
template <class... TN>
struct is_many;
// Tag
......@@ -93,12 +79,8 @@ template <class PS>
struct is_many<PS> : property_query<PS, is_many<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_many_v = is_many<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Many, //
is_many_v<PS>);
// Flow trait and tag
// is_flow trait and tag
template <class... TN>
struct is_flow;
// Tag
......@@ -111,10 +93,6 @@ template <class PS>
struct is_flow<PS> : property_query<PS, is_flow<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_flow_v = is_flow<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Flow, //
is_flow_v<PS>);
// Receiver trait and tag
template <class... TN>
......@@ -130,6 +108,32 @@ struct is_receiver<PS> : property_query<PS, is_receiver<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_receiver_v = is_receiver<PS>::value;
// add concepts to support receivers
//
PUSHMI_CONCEPT_DEF(
template(class R) //
(concept Receiver)(R), //
requires(R& r) //
(set_done(r)) &&
SemiMovable<std::decay_t<R>> &&
is_receiver_v<R>);
PUSHMI_CONCEPT_DEF(
template(class R, class... VN) //
(concept ReceiveValue)(R, VN...), //
requires(R& r) //
(set_value(r, std::declval<VN&&>()...)) &&
Receiver<R>&& And<MoveConstructible<VN>...>);
PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) //
(concept ReceiveError)(R, E), //
requires(R& r, E&& e)( //
set_error(r, (E &&) e)) &&
Receiver<R> && MoveConstructible<E>
);
// Sender trait and tag
template <class... TN>
struct is_sender;
......@@ -144,53 +148,28 @@ struct is_sender<PS> : property_query<PS, is_sender<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_sender_v = is_sender<PS>::value;
// Executor trait and tag
template <class... TN>
struct is_executor;
// Tag
template <>
struct is_executor<> {
using property_category = executor_category;
};
// Trait
template <class PS>
struct is_executor<PS> : property_query<PS, is_executor<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_executor_v = is_executor<PS>::value;
// add concepts to support senders
//
// Constrained trait and tag
template <class... TN>
struct is_constrained;
// Tag
template <>
struct is_constrained<> : is_executor<> {};
// Trait
template <class PS>
struct is_constrained<PS> : property_query<PS, is_constrained<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_constrained_v = is_constrained<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Constrained, //
is_constrained_v<PS>&& is_executor_v<PS>);
template(class S) //
(concept SenderImpl)(S), //
SemiMovable<S>&& has_cardinality_v<S>&&
is_sender_v<S>);
PUSHMI_CONCEPT_DEF(
template(class S) //
(concept Sender)(S), //
SenderImpl<std::decay_t<S>>);
// Time trait and tag
template <class... TN>
struct is_time;
// Tag
template <>
struct is_time<> : is_constrained<> {};
// Trait
template <class PS>
struct is_time<PS> : property_query<PS, is_time<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_time_v = is_time<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept Time, //
is_time_v<PS>&& is_constrained_v<PS>&& is_executor_v<PS>);
template(class S, class R) //
(concept SenderTo)(S, R), //
requires(S&& s, R&& r) //
(submit((S &&) s, (R &&) r)) &&
Sender<S> && Receiver<R>);
// AlwaysBlocking trait and tag
// is_always_blocking trait and tag
template <class... TN>
struct is_always_blocking;
// Tag
......@@ -204,12 +183,8 @@ struct is_always_blocking<PS> : property_query<PS, is_always_blocking<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_always_blocking_v =
is_always_blocking<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept AlwaysBlocking, //
is_always_blocking_v<PS>&& is_sender_v<PS>);
// NeverBlocking trait and tag
// is_never_blocking trait and tag
template <class... TN>
struct is_never_blocking;
// Tag
......@@ -223,12 +198,8 @@ struct is_never_blocking<PS> : property_query<PS, is_never_blocking<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_never_blocking_v =
is_never_blocking<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept NeverBlocking, //
is_never_blocking_v<PS>&& is_sender_v<PS>);
// MaybeBlocking trait and tag
// is_maybe_blocking trait and tag
template <class... TN>
struct is_maybe_blocking;
// Tag
......@@ -242,12 +213,8 @@ struct is_maybe_blocking<PS> : property_query<PS, is_maybe_blocking<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_maybe_blocking_v =
is_maybe_blocking<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept MaybeBlocking, //
is_maybe_blocking_v<PS>&& is_sender_v<PS>);
// FifoSequence trait and tag
// is_fifo_sequence trait and tag
template <class... TN>
struct is_fifo_sequence;
// Tag
......@@ -261,12 +228,8 @@ struct is_fifo_sequence<PS> : property_query<PS, is_fifo_sequence<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_fifo_sequence_v =
is_fifo_sequence<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept FifoSequence, //
is_fifo_sequence_v<PS>&& is_executor_v<PS>);
// ConcurrentSequence trait and tag
// is_concurrent_sequence trait and tag
template <class... TN>
struct is_concurrent_sequence;
// Tag
......@@ -281,46 +244,49 @@ struct is_concurrent_sequence<PS>
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_concurrent_sequence_v =
is_concurrent_sequence<PS>::value;
PUSHMI_CONCEPT_DEF(
template(class PS) //
concept ConcurrentSequence, //
is_concurrent_sequence_v<PS>&& is_executor_v<PS>);
// concepts to support execution
//
PUSHMI_CONCEPT_DEF(
template(class Exec, class... PropertyN) //
(concept Executor)(Exec, PropertyN...), //
requires(Exec& exec) //
(schedule(exec), requires_<is_sender_v<decltype(schedule(exec))>>) &&
SemiMovable<std::decay_t<Exec>> && property_query_v<Exec, PropertyN...> &&
is_executor_v<Exec>);
template(class Exec) //
(concept Executor)(Exec), //
requires(Exec& exec)( //
schedule(exec),
requires_<Sender<decltype(schedule(exec))>>) &&
SemiMovable<std::decay_t<Exec>>);
template <class Exec>
template <class Exec, class... Args>
PUSHMI_PP_CONSTRAINED_USING(
Executor<Exec>,
sender_t =,
decltype(schedule(std::declval<Exec&>())));
decltype(schedule(std::declval<Exec&>(), std::declval<Args>()...)));
PUSHMI_CONCEPT_DEF(
template(class Exec, class... PropertyN) //
(concept ExecutorProvider)(Exec, PropertyN...), //
requires(Exec& exec) //
(get_executor(exec),
template(class Exec) //
(concept ExecutorProvider)(Exec), //
requires(Exec& exec)( //
get_executor(exec),
requires_<Executor<decltype(get_executor(exec))>>) &&
SemiMovable<std::decay_t<Exec>> && property_query_v<Exec, PropertyN...>);
SemiMovable<std::decay_t<Exec>>);
template <class S>
PUSHMI_PP_CONSTRAINED_USING(
ExecutorProvider<S>,
executor_t =,
decltype(get_executor(std::declval<S&>())));
PUSHMI_CONCEPT_DEF(
template(class Exec, class... PropertyN) //
(concept Strand)(Exec, PropertyN...), //
Executor<Exec>&& property_query_v<Exec, is_fifo_sequence<>, PropertyN...>);
template(class Exec) //
(concept Strand)(Exec), //
Executor<Exec>&&
is_fifo_sequence_v<Exec>);
PUSHMI_CONCEPT_DEF(
template(class Exec) //
(concept StrandFactory)(Exec), //
requires(Exec& exec) //
(make_strand(exec), requires_<Strand<decltype(make_strand(exec))>>) &&
requires(Exec& exec)( //
make_strand(exec), requires_<Strand<decltype(make_strand(exec))>>) &&
SemiMovable<std::decay_t<Exec>>);
template <class Exec>
......@@ -336,17 +302,16 @@ PUSHMI_PP_CONSTRAINED_USING(
//
// top() returns the constraint value that will cause the item to run asap.
// So now() for time and NORMAL for priority.
//
PUSHMI_CONCEPT_DEF(
template(class Exec, class... PropertyN) //
(concept ConstrainedExecutor)(Exec, PropertyN...), //
requires(Exec& exec) //
(top(exec),
template(class Exec) //
(concept ConstrainedExecutor)(Exec), //
requires(Exec& exec)( //
top(exec),
requires_<Regular<decltype(top(exec))>>,
schedule(exec, top(exec)),
requires_<is_sender_v<decltype(schedule(exec, top(exec)))>>) &&
Executor<Exec, is_constrained<>, PropertyN...>);
requires_<Sender<decltype(schedule(exec, top(exec)))>>) &&
Executor<Exec>);
template <class Exec>
PUSHMI_PP_CONSTRAINED_USING(
......@@ -355,13 +320,36 @@ PUSHMI_PP_CONSTRAINED_USING(
decltype(top(std::declval<Exec&>())));
PUSHMI_CONCEPT_DEF(
template(class Exec, class... PropertyN) //
(concept TimeExecutor)(Exec, PropertyN...), //
requires(Exec& exec) //
(now(exec),
template(class Exec, class TP, class Duration) //
concept TimeExecutorImpl2_, //
requires(Exec& exec, TP tp, Duration d)( //
requires_<Sender<decltype(exec.schedule(tp + d))>>,
requires_<Sender<decltype(exec.schedule(d + tp))>>,
requires_<Sender<decltype(exec.schedule(tp - d))>>,
tp += d,
tp -= d));
PUSHMI_CONCEPT_DEF(
template(class Exec, class TP = decltype(now(std::declval<Exec&>()))) //
(concept TimeExecutorImpl_)(Exec, TP), //
Regular<TP> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::nanoseconds> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::microseconds> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::milliseconds> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::seconds> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::minutes> &&
TimeExecutorImpl2_<Exec, TP, std::chrono::hours> &&
TimeExecutorImpl2_<Exec, TP, decltype(TP{} - TP{})>);
PUSHMI_CONCEPT_DEF(
template(class Exec) //
(concept TimeExecutor)(Exec), //
requires(Exec& exec)( //
now(exec),
schedule(exec, now(exec)),
requires_<Regular<decltype(now(exec) + std::chrono::seconds(1))>>) &&
ConstrainedExecutor<Exec, is_time<>, PropertyN...>);
requires_<Sender<decltype(schedule(exec, now(exec)))>>) &&
ConstrainedExecutor<Exec> &&
TimeExecutorImpl_<Exec>);
template <class Exec>
PUSHMI_PP_CONSTRAINED_USING(
......@@ -369,95 +357,42 @@ PUSHMI_PP_CONSTRAINED_USING(
time_point_t =,
decltype(now(std::declval<Exec&>())));
// add concepts to support receivers
//
PUSHMI_CONCEPT_DEF(
template(class R, class... PropertyN) //
(concept Receiver)(R, PropertyN...), //
requires(R& r) //
(set_done(r)) &&
SemiMovable<std::decay_t<R>> &&
property_query_v<R, PropertyN...> &&
is_receiver_v<R> && !is_sender_v<R>
);
PUSHMI_CONCEPT_DEF(
template(class R, class... VN) //
(concept ReceiveValue)(R, VN...), //
requires(R& r) //
(set_value(r, std::declval<VN&&>()...)) &&
Receiver<R>&& And<MoveConstructible<VN>...>);
PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) //
(concept ReceiveError)(R, E), //
requires(R& r, E&& e)( //
set_error(r, (E &&) e)) &&
Receiver<R> && MoveConstructible<E>);
// add concepts to support senders
//
PUSHMI_CONCEPT_DEF(
template(class S, class... PropertyN) //
(concept SenderImpl)(S, PropertyN...), //
SemiMovable<S>&& Cardinality<S>&& property_query_v<S, PropertyN...>&&
is_sender_v<S> &&
!is_receiver_v<S>);
PUSHMI_CONCEPT_DEF(
template(class S, class... PropertyN) //
(concept Sender)(S, PropertyN...), //
SenderImpl<std::decay_t<S>, PropertyN...>);
PUSHMI_CONCEPT_DEF(
template(class S, class R, class... PropertyN) //
(concept SenderTo)(S, R, PropertyN...), //
requires(S&& s, R&& r) //
(submit((S &&) s, (R &&) r)) &&
Sender<S, PropertyN...> && Receiver<R>);
template <class S>
PUSHMI_PP_CONSTRAINED_USING(
Sender<S>,
executor_t =,
decltype(get_executor(std::declval<S&>())));
// add concepts to support cancellation and rate control
//
PUSHMI_CONCEPT_DEF(
template(class R, class... PropertyN) //
(concept FlowReceiver)(R, PropertyN...), //
Receiver<R>&& property_query_v<R, PropertyN...>&& Flow<R>);
template(class R) //
(concept FlowReceiver)(R), //
Receiver<R>&&
is_flow_v<R>);
PUSHMI_CONCEPT_DEF(
template(class R, class... VN) //
(concept FlowReceiveValue)(R, VN...), //
Flow<R>&& ReceiveValue<R, VN...>);
is_flow_v<R>&& ReceiveValue<R, VN...>);
PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) //
(concept FlowReceiveError)(R, E), //
Flow<R>&& ReceiveError<R, E>);
is_flow_v<R>&& ReceiveError<R, E>);
PUSHMI_CONCEPT_DEF(
template(class R, class Up) //
(concept FlowUpTo)(R, Up), //
requires(R& r, Up&& up) //
(set_starting(r, (Up &&) up)) &&
Flow<R>);
requires(R& r, Up&& up)( //
set_starting(r, (Up &&) up)) &&
is_flow_v<R>);
PUSHMI_CONCEPT_DEF(
template(class S, class... PropertyN) //
(concept FlowSender)(S, PropertyN...), //
Sender<S>&& property_query_v<S, PropertyN...>&& Flow<S>);
template(class S) //
(concept FlowSender)(S), //
Sender<S>&&
is_flow_v<S>);
PUSHMI_CONCEPT_DEF(
template(class S, class R, class... PropertyN) //
(concept FlowSenderTo)(S, R, PropertyN...), //
FlowSender<S>&& SenderTo<S, R>&& property_query_v<S, PropertyN...>&&
template(class S, class R) //
(concept FlowSenderTo)(S, R), //
FlowSender<S>&& SenderTo<S, R>&&
FlowReceiver<R>);
} // namespace pushmi
......
......@@ -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>) //
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