Commit 432d4332 authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

replace receiver properties with receiver_traits

Summary: Types opt in to receiver-ness with pushmi::receiver_traits, analogous to sender_traits (and std::iterator_traits). Alternatively, they can simply define a nested ::receiver_concept typedef that is an alias for one of "sink" or "flow".

Reviewed By: kirkshoop

Differential Revision: D14668335

fbshipit-source-id: 230abfcffef0cd231196b5f6a7ed05e1ac86ef0c
parent 1c1fbc3c
...@@ -47,7 +47,7 @@ template <class R> ...@@ -47,7 +47,7 @@ template <class R>
struct countdown { struct countdown {
explicit countdown(std::atomic<int>& c) : counter(&c) {} explicit countdown(std::atomic<int>& c) : counter(&c) {}
using properties = mi::properties_t<decltype(R{}())>; using receiver_category = mi::receiver_category_t<folly::invoke_result_t<R>>;
std::atomic<int>* counter; std::atomic<int>* counter;
......
...@@ -27,82 +27,66 @@ ...@@ -27,82 +27,66 @@
namespace folly { namespace folly {
namespace pushmi { namespace pushmi {
// traits & tags
struct sender_tag;
struct single_sender_tag;
struct flow_sender_tag;
struct flow_single_sender_tag;
// add concepts to support receivers // add concepts to support receivers
// //
/// \cond /// \cond
namespace detail { namespace detail {
template <bool> template <class R, class = void>
struct Enable_ {}; struct basic_receiver_traits {
template <>
struct Enable_<true> {
template <class T>
using _type = T;
}; };
template <class R>
#if defined(__cpp_fold_expressions) && __cpp_fold_expressions > 0 struct basic_receiver_traits<R, void_t<typename R::receiver_category>> {
// An alias for the type in the pack if the pack has exactly one type in it. using receiver_category = typename R::receiver_category;
// Otherwise, this SFINAE's away. T cannot be an array type of an abstract type.
template<class... Ts>
using identity_t = typename Enable_<sizeof...(Ts) == 1u>::
template _type<decltype((((Ts(*)())0)(),...))>;
#else
template <class...>
struct Front_ {};
template <class T, class... Us>
struct Front_<T, Us...> {
using type = T;
}; };
// Instantiation proceeds from left to right. The use of Enable_ here avoids
// needless instantiations of Front_.
template<class...Ts>
using identity_t = typename Enable_<sizeof...(Ts) == 1u>::
template _type<Front_<Ts...>>::type;
#endif
} // namespace detail } // namespace detail
/// \endcond
// is_flow trait template<typename R, typename>
template <class PS> struct receiver_traits
struct is_flow<PS> : property_query<PS, is_flow<>> {}; : std::conditional_t<
template <class PS> std::is_same<std::decay_t<R>, R>::value,
PUSHMI_INLINE_VAR constexpr bool is_flow_v = is_flow<PS>::value; detail::basic_receiver_traits<R>,
receiver_traits<std::decay_t<R>>> {
// is_receiver trait using _not_specialized = void;
template <class PS> };
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( PUSHMI_CONCEPT_DEF(
template(class R) // template(class R) //
(concept Receiver)(R), // (concept Receiver)(R), //
requires(R& r) // requires(R& r)( //
(set_done(r)) && set_done(r) //
) && //
SemiMovable<std::decay_t<R>> && SemiMovable<std::decay_t<R>> &&
is_receiver_v<R>); True<typename receiver_traits<R>::receiver_category> &&
DerivedFrom<typename receiver_traits<R>::receiver_category, receiver_tag>
);
template <class R>
PUSHMI_PP_CONSTRAINED_USING(
Receiver<R>,
receiver_category_t =,
typename receiver_traits<R>::receiver_category
);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class R, class... VN) // template(class R, class... VN) //
(concept ReceiveValue)(R, VN...), // (concept ReceiveValue)(R, VN...), //
requires(R& r) // requires(R& r)( //
(set_value(r, std::declval<VN&&>()...)) && set_value(r, std::declval<VN&&>()...) //
Receiver<R>&& And<MoveConstructible<VN>...>); ) && //
Receiver<R> && //
And<MoveConstructible<VN>...>
);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class R, class E) // template(class R, class E) //
(concept ReceiveError)(R, E), // (concept ReceiveError)(R, E), //
requires(R& r, E&& e)( // requires(R& r, E&& e)( //
set_error(r, (E &&) e)) && set_error(r, (E &&) e) //
Receiver<R> && MoveConstructible<E> ) && //
Receiver<R> && //
MoveConstructible<E>
); );
// add concepts to support senders // add concepts to support senders
...@@ -127,6 +111,7 @@ namespace detail { ...@@ -127,6 +111,7 @@ namespace detail {
True<test_value_types<S::template value_types>> && True<test_value_types<S::template value_types>> &&
True<test_error_type<S::template error_type>> True<test_error_type<S::template error_type>>
); );
template<class, class = void> template<class, class = void>
struct basic_sender_traits { struct basic_sender_traits {
}; };
...@@ -148,7 +133,7 @@ namespace detail { ...@@ -148,7 +133,7 @@ namespace detail {
}; };
} // namespace detail } // namespace detail
template<typename S> template<typename S, typename>
struct sender_traits struct sender_traits
: std::conditional_t< : std::conditional_t<
std::is_same<std::decay_t<S>, S>::value, std::is_same<std::decay_t<S>, S>::value,
...@@ -421,36 +406,41 @@ PUSHMI_CONCEPT_DEF( ...@@ -421,36 +406,41 @@ PUSHMI_CONCEPT_DEF(
template(class R) // template(class R) //
(concept FlowReceiver)(R), // (concept FlowReceiver)(R), //
Receiver<R>&& Receiver<R>&&
is_flow_v<R>); DerivedFrom<receiver_category_t<R>, flow_receiver_tag>);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class R, class... VN) // template(class R, class... VN) //
(concept FlowReceiveValue)(R, VN...), // (concept FlowReceiveValue)(R, VN...), //
is_flow_v<R>&& ReceiveValue<R, VN...>); FlowReceiver<R>&& ReceiveValue<R, VN...>);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) // template(class R, class E = std::exception_ptr) //
(concept FlowReceiveError)(R, E), // (concept FlowReceiveError)(R, E), //
is_flow_v<R>&& ReceiveError<R, E>); FlowReceiver<R>&& ReceiveError<R, E>);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class R, class Up) // template(class R, class Up) //
(concept FlowUpTo)(R, Up), // (concept FlowUpTo)(R, Up), //
requires(R& r, Up&& up)( // requires(R& r, Up&& up)( //
set_starting(r, (Up &&) up)) && set_starting(r, (Up &&) up) //
is_flow_v<R>); ) &&
FlowReceiver<R>
);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class S) // template(class S) //
(concept FlowSender)(S), // (concept FlowSender)(S), //
Sender<S>&& Sender<S>&&
DerivedFrom<sender_category_t<S>, flow_sender_tag>); DerivedFrom<sender_category_t<S>, flow_sender_tag>
);
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class S, class R) // template(class S, class R) //
(concept FlowSenderTo)(S, R), // (concept FlowSenderTo)(S, R), //
FlowSender<S>&& SenderTo<S, R>&& FlowSender<S> && //
FlowReceiver<R>); SenderTo<S, R>&& //
FlowReceiver<R>
);
} // namespace pushmi } // namespace pushmi
} // namespace folly } // namespace folly
...@@ -31,8 +31,7 @@ class pool_executor { ...@@ -31,8 +31,7 @@ class pool_executor {
Executor::KeepAlive<CPUThreadPoolExecutor> exec_ {}; Executor::KeepAlive<CPUThreadPoolExecutor> exec_ {};
public: public:
using properties = using properties = property_set<is_concurrent_sequence<>>;
property_set<is_concurrent_sequence<>>;
pool_executor() = default; pool_executor() = default;
explicit pool_executor(pool &e); explicit pool_executor(pool &e);
......
...@@ -104,8 +104,6 @@ class any_executor { ...@@ -104,8 +104,6 @@ class any_executor {
std::enable_if_t<!std::is_same<U, any_executor>::value, U>; std::enable_if_t<!std::is_same<U, any_executor>::value, U>;
public: public:
using properties = property_set<>;
any_executor() = default; any_executor() = default;
any_executor(const any_executor& that) noexcept : any_executor() { any_executor(const any_executor& that) noexcept : any_executor() {
that.vptr_->op_(that.data_, &data_); that.vptr_->op_(that.data_, &data_);
...@@ -148,8 +146,6 @@ class executor<SF> { ...@@ -148,8 +146,6 @@ class executor<SF> {
SF sf_; SF sf_;
public: public:
using properties = property_set<>;
constexpr executor() = default; constexpr executor() = default;
constexpr explicit executor(SF sf) : sf_(std::move(sf)) {} constexpr explicit executor(SF sf) : sf_(std::move(sf)) {}
...@@ -196,20 +192,17 @@ PUSHMI_INLINE_VAR constexpr struct make_executor_fn { ...@@ -196,20 +192,17 @@ PUSHMI_INLINE_VAR constexpr struct make_executor_fn {
} }
PUSHMI_TEMPLATE(class SF) PUSHMI_TEMPLATE(class SF)
(requires not Executor<SF>) // (requires not Executor<SF>) //
auto auto operator()(SF sf) const {
operator()(SF sf) const {
return executor<SF>{std::move(sf)}; return executor<SF>{std::move(sf)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires True<>&& Executor<Data>) // (requires True<>&& Executor<Data>) //
auto auto operator()(Data d) const {
operator()(Data d) const {
return executor<Data, passDSF>{std::move(d)}; return executor<Data, passDSF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DSF) PUSHMI_TEMPLATE(class Data, class DSF)
(requires Executor<Data>) // (requires Executor<Data>) //
auto auto operator()(Data d, DSF sf) const {
operator()(Data d, DSF sf) const {
return executor<Data, DSF>{std::move(d), std::move(sf)}; return executor<Data, DSF>{std::move(d), std::move(sf)};
} }
} const make_executor{}; } const make_executor{};
...@@ -256,8 +249,6 @@ struct any_executor_ref { ...@@ -256,8 +249,6 @@ struct any_executor_ref {
using wrapped_t = detail::not_any_executor_ref_t<T>; using wrapped_t = detail::not_any_executor_ref_t<T>;
public: public:
using properties = property_set<>;
any_executor_ref() = delete; any_executor_ref() = delete;
any_executor_ref(const any_executor_ref&) = default; any_executor_ref(const any_executor_ref&) = default;
...@@ -289,7 +280,7 @@ auto make_any_executor_ref() { ...@@ -289,7 +280,7 @@ auto make_any_executor_ref() {
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped) PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped)
(requires Executor<detail::not_any_executor_ref_t<Wrapped>>) // (requires Executor<detail::not_any_executor_ref_t<Wrapped>>) //
auto make_any_executor_ref(Wrapped& w) { auto make_any_executor_ref(Wrapped& w) {
return any_executor_ref<E>{w}; return any_executor_ref<E>{w};
} }
...@@ -416,8 +407,6 @@ class any_constrained_executor { ...@@ -416,8 +407,6 @@ class any_constrained_executor {
std::enable_if_t<!std::is_same<U, any_constrained_executor>::value, U>; std::enable_if_t<!std::is_same<U, any_constrained_executor>::value, U>;
public: public:
using properties = property_set<>;
any_constrained_executor() = default; any_constrained_executor() = default;
any_constrained_executor(const any_constrained_executor& that) noexcept any_constrained_executor(const any_constrained_executor& that) noexcept
: any_constrained_executor() { : any_constrained_executor() {
...@@ -469,8 +458,6 @@ class constrained_executor<SF, ZF> { ...@@ -469,8 +458,6 @@ class constrained_executor<SF, ZF> {
ZF zf_; ZF zf_;
public: public:
using properties = property_set<>;
constexpr constrained_executor() = default; constexpr constrained_executor() = default;
constexpr explicit constrained_executor(SF sf) : sf_(std::move(sf)) {} constexpr explicit constrained_executor(SF sf) : sf_(std::move(sf)) {}
constexpr constrained_executor(SF sf, ZF zf) : sf_(std::move(sf)), zf_(std::move(zf)) {} constexpr constrained_executor(SF sf, ZF zf) : sf_(std::move(sf)), zf_(std::move(zf)) {}
...@@ -530,32 +517,27 @@ PUSHMI_INLINE_VAR constexpr struct make_constrained_executor_fn { ...@@ -530,32 +517,27 @@ PUSHMI_INLINE_VAR constexpr struct make_constrained_executor_fn {
} }
PUSHMI_TEMPLATE(class SF) PUSHMI_TEMPLATE(class SF)
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not ConstrainedExecutor<SF>)) // (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not ConstrainedExecutor<SF>)) //
auto auto operator()(SF sf) const {
operator()(SF sf) const {
return constrained_executor<SF, priorityZeroF>{std::move(sf)}; return constrained_executor<SF, priorityZeroF>{std::move(sf)};
} }
PUSHMI_TEMPLATE(class SF, class ZF) PUSHMI_TEMPLATE(class SF, class ZF)
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not ConstrainedExecutor<SF>)) // (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not ConstrainedExecutor<SF>)) //
auto auto operator()(SF sf, ZF zf) const {
operator()(SF sf, ZF zf) const {
return constrained_executor<SF, ZF>{std::move(sf), std::move(zf)}; return constrained_executor<SF, ZF>{std::move(sf), std::move(zf)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires True<>&& ConstrainedExecutor<Data>) // (requires True<>&& ConstrainedExecutor<Data>) //
auto auto operator()(Data d) const {
operator()(Data d) const {
return constrained_executor<Data, passDSF, passDZF>{std::move(d)}; return constrained_executor<Data, passDSF, passDZF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DSF) PUSHMI_TEMPLATE(class Data, class DSF)
(requires ConstrainedExecutor<Data>) // (requires ConstrainedExecutor<Data>) //
auto auto operator()(Data d, DSF sf) const {
operator()(Data d, DSF sf) const {
return constrained_executor<Data, DSF, passDZF>{std::move(d), std::move(sf)}; return constrained_executor<Data, DSF, passDZF>{std::move(d), std::move(sf)};
} }
PUSHMI_TEMPLATE(class Data, class DSF, class DZF) PUSHMI_TEMPLATE(class Data, class DSF, class DZF)
(requires ConstrainedExecutor<Data>) // (requires ConstrainedExecutor<Data>) //
auto auto operator()(Data d, DSF sf, DZF zf) const {
operator()(Data d, DSF sf, DZF zf) const {
return constrained_executor<Data, DSF, DZF>{std::move(d), std::move(sf), std::move(zf)}; return constrained_executor<Data, DSF, DZF>{std::move(d), std::move(sf), std::move(zf)};
} }
} const make_constrained_executor{}; } const make_constrained_executor{};
...@@ -615,8 +597,6 @@ struct any_constrained_executor_ref { ...@@ -615,8 +597,6 @@ struct any_constrained_executor_ref {
using wrapped_t = detail::not_any_constrained_executor_ref_t<T>; using wrapped_t = detail::not_any_constrained_executor_ref_t<T>;
public: public:
using properties = property_set<>;
any_constrained_executor_ref() = delete; any_constrained_executor_ref() = delete;
any_constrained_executor_ref(const any_constrained_executor_ref&) = default; any_constrained_executor_ref(const any_constrained_executor_ref&) = default;
...@@ -661,7 +641,7 @@ auto make_any_constrained_executor_ref() { ...@@ -661,7 +641,7 @@ auto make_any_constrained_executor_ref() {
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped) PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped)
(requires ConstrainedExecutor< (requires ConstrainedExecutor<
detail::not_any_constrained_executor_ref_t<Wrapped>>) // detail::not_any_constrained_executor_ref_t<Wrapped>>) //
auto make_any_constrained_executor_ref(Wrapped& w) { auto make_any_constrained_executor_ref(Wrapped& w) {
return any_constrained_executor_ref<E, constraint_t<Wrapped>>{w}; return any_constrained_executor_ref<E, constraint_t<Wrapped>>{w};
} }
...@@ -791,8 +771,6 @@ class any_time_executor { ...@@ -791,8 +771,6 @@ class any_time_executor {
std::enable_if_t<!std::is_same<U, any_time_executor>::value, U>; std::enable_if_t<!std::is_same<U, any_time_executor>::value, U>;
public: public:
using properties = property_set<>;
any_time_executor() = default; any_time_executor() = default;
any_time_executor(const any_time_executor& that) noexcept : any_time_executor() { any_time_executor(const any_time_executor& that) noexcept : any_time_executor() {
that.vptr_->op_(that.data_, &data_); that.vptr_->op_(that.data_, &data_);
...@@ -842,8 +820,6 @@ class time_executor<SF, NF> { ...@@ -842,8 +820,6 @@ class time_executor<SF, NF> {
NF nf_; NF nf_;
public: public:
using properties = property_set<>;
constexpr time_executor() = default; constexpr time_executor() = default;
constexpr explicit time_executor(SF sf) : sf_(std::move(sf)) {} constexpr explicit time_executor(SF sf) : sf_(std::move(sf)) {}
constexpr time_executor(SF sf, NF nf) : sf_(std::move(sf)), nf_(std::move(nf)) {} constexpr time_executor(SF sf, NF nf) : sf_(std::move(sf)), nf_(std::move(nf)) {}
...@@ -903,32 +879,27 @@ PUSHMI_INLINE_VAR constexpr struct make_time_executor_fn { ...@@ -903,32 +879,27 @@ PUSHMI_INLINE_VAR constexpr struct make_time_executor_fn {
} }
PUSHMI_TEMPLATE(class SF) PUSHMI_TEMPLATE(class SF)
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not TimeExecutor<SF>)) // (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not TimeExecutor<SF>)) //
auto auto operator()(SF sf) const {
operator()(SF sf) const {
return time_executor<SF, systemNowF>{std::move(sf)}; return time_executor<SF, systemNowF>{std::move(sf)};
} }
PUSHMI_TEMPLATE(class SF, class NF) PUSHMI_TEMPLATE(class SF, class NF)
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not TimeExecutor<SF>)) // (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not TimeExecutor<SF>)) //
auto auto operator()(SF sf, NF nf) const {
operator()(SF sf, NF nf) const {
return time_executor<SF, NF>{std::move(sf), std::move(nf)}; return time_executor<SF, NF>{std::move(sf), std::move(nf)};
} }
PUSHMI_TEMPLATE(class Data) PUSHMI_TEMPLATE(class Data)
(requires True<>&& TimeExecutor<Data>) // (requires True<>&& TimeExecutor<Data>) //
auto auto operator()(Data d) const {
operator()(Data d) const {
return time_executor<Data, passDSF, passDNF>{std::move(d)}; return time_executor<Data, passDSF, passDNF>{std::move(d)};
} }
PUSHMI_TEMPLATE(class Data, class DSF) PUSHMI_TEMPLATE(class Data, class DSF)
(requires TimeExecutor<Data>) // (requires TimeExecutor<Data>) //
auto auto operator()(Data d, DSF sf) const {
operator()(Data d, DSF sf) const {
return time_executor<Data, DSF, passDNF>{std::move(d), std::move(sf)}; return time_executor<Data, DSF, passDNF>{std::move(d), std::move(sf)};
} }
PUSHMI_TEMPLATE(class Data, class DSF, class DNF) PUSHMI_TEMPLATE(class Data, class DSF, class DNF)
(requires TimeExecutor<Data>) // (requires TimeExecutor<Data>) //
auto auto operator()(Data d, DSF sf, DNF nf) const {
operator()(Data d, DSF sf, DNF nf) const {
return time_executor<Data, DSF, DNF>{std::move(d), std::move(sf), std::move(nf)}; return time_executor<Data, DSF, DNF>{std::move(d), std::move(sf), std::move(nf)};
} }
} const make_time_executor{}; } const make_time_executor{};
...@@ -967,7 +938,6 @@ PUSHMI_TEMPLATE(class Data, class DSF, class DNF) ...@@ -967,7 +938,6 @@ PUSHMI_TEMPLATE(class Data, class DSF, class DNF)
template <> template <>
struct construct_deduced<time_executor> : make_time_executor_fn {}; struct construct_deduced<time_executor> : make_time_executor_fn {};
namespace detail { namespace detail {
template <class T> template <class T>
using not_any_time_executor_ref_t = not_is_t<T, any_time_executor_ref>; using not_any_time_executor_ref_t = not_is_t<T, any_time_executor_ref>;
...@@ -988,8 +958,6 @@ struct any_time_executor_ref { ...@@ -988,8 +958,6 @@ struct any_time_executor_ref {
using wrapped_t = detail::not_any_time_executor_ref_t<T>; using wrapped_t = detail::not_any_time_executor_ref_t<T>;
public: public:
using properties = property_set<>;
any_time_executor_ref() = delete; any_time_executor_ref() = delete;
any_time_executor_ref(const any_time_executor_ref&) = default; any_time_executor_ref(const any_time_executor_ref&) = default;
...@@ -1064,7 +1032,7 @@ auto make_any_time_executor_ref() { ...@@ -1064,7 +1032,7 @@ auto make_any_time_executor_ref() {
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped) PUSHMI_TEMPLATE(class E = std::exception_ptr, class Wrapped)
(requires TimeExecutor<detail::not_any_time_executor_ref_t<Wrapped>>) // (requires TimeExecutor<detail::not_any_time_executor_ref_t<Wrapped>>) //
auto make_any_time_executor_ref(Wrapped& w) { auto make_any_time_executor_ref(Wrapped& w) {
return any_time_executor_ref<E, time_point_t<Wrapped>>{w}; return any_time_executor_ref<E, time_point_t<Wrapped>>{w};
} }
...@@ -1078,7 +1046,7 @@ any_time_executor_ref() ...@@ -1078,7 +1046,7 @@ any_time_executor_ref()
PUSHMI_TEMPLATE(class Wrapped) PUSHMI_TEMPLATE(class Wrapped)
(requires TimeExecutor<detail::not_any_time_executor_ref_t<Wrapped>>) // (requires TimeExecutor<detail::not_any_time_executor_ref_t<Wrapped>>) //
any_time_executor_ref(Wrapped&) any_time_executor_ref(Wrapped&)
->any_time_executor_ref<std::exception_ptr, time_point_t<Wrapped>>; ->any_time_executor_ref<std::exception_ptr, time_point_t<Wrapped>>;
#endif #endif
......
...@@ -84,8 +84,6 @@ class any_flow_many_sender ...@@ -84,8 +84,6 @@ class any_flow_many_sender
using wrapped_t = using wrapped_t =
std::enable_if_t<!std::is_same<U, any_flow_many_sender>::value, U>; std::enable_if_t<!std::is_same<U, any_flow_many_sender>::value, U>;
public: public:
using properties = property_set<>;
any_flow_many_sender() = default; any_flow_many_sender() = default;
any_flow_many_sender(any_flow_many_sender&& that) noexcept any_flow_many_sender(any_flow_many_sender&& that) noexcept
: any_flow_many_sender() { : any_flow_many_sender() {
...@@ -122,7 +120,6 @@ class flow_many_sender<SF> { ...@@ -122,7 +120,6 @@ class flow_many_sender<SF> {
public: public:
using sender_category = flow_sender_tag; using sender_category = flow_sender_tag;
using properties = property_set<>;
constexpr flow_many_sender() = default; constexpr flow_many_sender() = default;
constexpr explicit flow_many_sender(SF sf) constexpr explicit flow_many_sender(SF sf)
......
...@@ -104,7 +104,7 @@ class any_flow_receiver { ...@@ -104,7 +104,7 @@ class any_flow_receiver {
using wrapped_t = using wrapped_t =
std::enable_if_t<!std::is_same<U, any_flow_receiver>::value, U>; std::enable_if_t<!std::is_same<U, any_flow_receiver>::value, U>;
public: public:
using properties = property_set<is_receiver<>, is_flow<>>; using receiver_category = flow_receiver_tag;
any_flow_receiver() = default; any_flow_receiver() = default;
any_flow_receiver(any_flow_receiver&& that) noexcept : any_flow_receiver() { any_flow_receiver(any_flow_receiver&& that) noexcept : any_flow_receiver() {
...@@ -171,7 +171,7 @@ class flow_receiver<VF, EF, DF, StrtF> { ...@@ -171,7 +171,7 @@ class flow_receiver<VF, EF, DF, StrtF> {
StrtF strtf_; StrtF strtf_;
public: public:
using properties = property_set<is_receiver<>, is_flow<>>; using receiver_category = flow_receiver_tag;
static_assert( static_assert(
!detail::is_v<VF, on_error_fn>, !detail::is_v<VF, on_error_fn>,
...@@ -255,11 +255,11 @@ class flow_receiver<Data, DVF, DEF, DDF, DStrtF> { ...@@ -255,11 +255,11 @@ class flow_receiver<Data, DVF, DEF, DDF, DStrtF> {
DStrtF strtf_; DStrtF strtf_;
public: public:
using properties = properties_t<Data>;
static_assert( static_assert(
FlowReceiverDataArg<Data>, FlowReceiverDataArg<Data>,
"Data must be a flow receiver"); "Data must be a flow receiver");
using receiver_category = flow_receiver_tag;
using properties = properties_t<Data>;
static_assert( static_assert(
!detail::is_v<DVF, on_error_fn>, !detail::is_v<DVF, on_error_fn>,
......
...@@ -91,8 +91,6 @@ class any_flow_single_sender ...@@ -91,8 +91,6 @@ class any_flow_single_sender
using wrapped_t = using wrapped_t =
std::enable_if_t<!std::is_same<U, any_flow_single_sender>::value, U>; std::enable_if_t<!std::is_same<U, any_flow_single_sender>::value, U>;
public: public:
using properties = property_set<>;
any_flow_single_sender() = default; any_flow_single_sender() = default;
any_flow_single_sender(any_flow_single_sender&& that) noexcept any_flow_single_sender(any_flow_single_sender&& that) noexcept
: any_flow_single_sender() { : any_flow_single_sender() {
...@@ -132,7 +130,6 @@ class flow_single_sender<SF> { ...@@ -132,7 +130,6 @@ class flow_single_sender<SF> {
public: public:
using sender_category = flow_single_sender_tag; using sender_category = flow_single_sender_tag;
using properties = property_set<>;
constexpr flow_single_sender() = default; constexpr flow_single_sender() = default;
constexpr explicit flow_single_sender(SF sf) constexpr explicit flow_single_sender(SF sf)
......
...@@ -25,6 +25,14 @@ ...@@ -25,6 +25,14 @@
namespace folly { namespace folly {
namespace pushmi { namespace pushmi {
// Traits types:
template< class, class = void >
struct sender_traits;
template< class, class = void >
struct receiver_traits;
// implementation types // implementation types
template <PUSHMI_TYPE_CONSTRAINT(SemiMovable)... TN> template <PUSHMI_TYPE_CONSTRAINT(SemiMovable)... TN>
......
...@@ -84,8 +84,6 @@ class any_many_sender ...@@ -84,8 +84,6 @@ class any_many_sender
std::enable_if_t<!std::is_same<U, any_many_sender>::value, U>; std::enable_if_t<!std::is_same<U, any_many_sender>::value, U>;
public: public:
using properties = property_set<>;
any_many_sender() = default; any_many_sender() = default;
any_many_sender(any_many_sender&& that) noexcept : any_many_sender() { any_many_sender(any_many_sender&& that) noexcept : any_many_sender() {
that.vptr_->op_(that.data_, &data_); that.vptr_->op_(that.data_, &data_);
...@@ -121,8 +119,6 @@ class many_sender<SF> : public sender_tag { ...@@ -121,8 +119,6 @@ class many_sender<SF> : public sender_tag {
SF sf_; SF sf_;
public: public:
using properties = property_set<>;
constexpr many_sender() = default; constexpr many_sender() = default;
constexpr explicit many_sender(SF sf) : sf_(std::move(sf)) {} constexpr explicit many_sender(SF sf) : sf_(std::move(sf)) {}
......
...@@ -38,8 +38,7 @@ struct for_each_fn { ...@@ -38,8 +38,7 @@ struct for_each_fn {
struct Pull { struct Pull {
Out out_; Out out_;
explicit Pull(Out out) : out_(std::move(out)) {} explicit Pull(Out out) : out_(std::move(out)) {}
using properties = using receiver_category = flow_receiver_tag;
property_set_insert_t<properties_t<Out>, property_set<is_flow<>>>;
folly::Function<void(std::ptrdiff_t)> pull; folly::Function<void(std::ptrdiff_t)> pull;
template <class... VN> template <class... VN>
void value(VN&&... vn) { void value(VN&&... vn) {
......
...@@ -93,7 +93,7 @@ struct flow_from_producer { ...@@ -93,7 +93,7 @@ struct flow_from_producer {
template <class Producer> template <class Producer>
struct flow_from_done { struct flow_from_done {
using properties = property_set<is_receiver<>>; using receiver_category = flow_receiver_tag;
explicit flow_from_done(std::shared_ptr<Producer> p) : p_(std::move(p)) {} explicit flow_from_done(std::shared_ptr<Producer> p) : p_(std::move(p)) {}
std::shared_ptr<Producer> p_; std::shared_ptr<Producer> p_;
...@@ -114,7 +114,7 @@ struct flow_from_done { ...@@ -114,7 +114,7 @@ struct flow_from_done {
template <class Producer> template <class Producer>
struct flow_from_up { struct flow_from_up {
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
explicit flow_from_up(std::shared_ptr<Producer> p_) : p(std::move(p_)) {} explicit flow_from_up(std::shared_ptr<Producer> p_) : p(std::move(p_)) {}
std::shared_ptr<Producer> p; std::shared_ptr<Producer> p;
...@@ -125,7 +125,8 @@ struct flow_from_up { ...@@ -125,7 +125,8 @@ struct flow_from_up {
} }
// submit work to exec // submit work to exec
::folly::pushmi::submit( ::folly::pushmi::submit(
::folly::pushmi::schedule(p->exec), make_receiver([p = p, requested](auto) { ::folly::pushmi::schedule(p->exec),
make_receiver([p = p, requested](auto) {
auto remaining = requested; auto remaining = requested;
// this loop is structured to work when there is // this loop is structured to work when there is
// re-entrancy out.value in the loop may call up.value. // re-entrancy out.value in the loop may call up.value.
...@@ -134,7 +135,7 @@ struct flow_from_up { ...@@ -134,7 +135,7 @@ struct flow_from_up {
// out.value is called. // out.value is called.
while (remaining-- > 0 && !p->stop && p->c != p->end) { while (remaining-- > 0 && !p->stop && p->c != p->end) {
auto i = (p->c)++; auto i = (p->c)++;
set_value(p->out, ::folly::pushmi::detail::as_const(*i)); set_value(p->out, folly::as_const(*i));
} }
if (p->c == p->end) { if (p->c == p->end) {
set_done(p->out); set_done(p->out);
...@@ -146,13 +147,15 @@ struct flow_from_up { ...@@ -146,13 +147,15 @@ struct flow_from_up {
void error(E) noexcept { void error(E) noexcept {
p->stop.store(true); p->stop.store(true);
::folly::pushmi::submit( ::folly::pushmi::submit(
::folly::pushmi::schedule(p->exec), flow_from_done<Producer>{p}); ::folly::pushmi::schedule(p->exec),
flow_from_done<Producer>{p});
} }
void done() { void done() {
p->stop.store(true); p->stop.store(true);
::folly::pushmi::submit( ::folly::pushmi::submit(
::folly::pushmi::schedule(p->exec), flow_from_done<Producer>{p}); ::folly::pushmi::schedule(p->exec),
flow_from_done<Producer>{p});
} }
}; };
...@@ -160,7 +163,7 @@ PUSHMI_INLINE_VAR constexpr struct flow_from_fn { ...@@ -160,7 +163,7 @@ PUSHMI_INLINE_VAR constexpr struct flow_from_fn {
private: private:
template <class Producer> template <class Producer>
struct receiver_impl : pipeorigin { struct receiver_impl : pipeorigin {
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
explicit receiver_impl(std::shared_ptr<Producer> p) : p_(std::move(p)) {} explicit receiver_impl(std::shared_ptr<Producer> p) : p_(std::move(p)) {}
std::shared_ptr<Producer> p_; std::shared_ptr<Producer> p_;
......
...@@ -42,15 +42,12 @@ struct submit_fn { ...@@ -42,15 +42,12 @@ struct submit_fn {
struct fn : pipeorigin { struct fn : pipeorigin {
explicit fn(AN&&... an) : args_((AN &&) an...) {} explicit fn(AN&&... an) : args_((AN &&) an...) {}
std::tuple<AN...> args_; std::tuple<AN...> args_;
PUSHMI_TEMPLATE(class In) PUSHMI_TEMPLATE(class In)( //
(requires // requires submit_detail::AutoSenderTo<In&&, AN...>) //
submit_detail::AutoSenderTo<In&&, AN...>) // void operator()(In&& in) {
void using maker_t = receiver_from_fn<std::decay_t<In>>;
operator()(In&& in) {
using maker_t = ::folly::pushmi::detail::receiver_from_fn<std::decay_t<In>>;
using receiver_t = invoke_result_t<maker_t, std::tuple<AN...>&&>; using receiver_t = invoke_result_t<maker_t, std::tuple<AN...>&&>;
receiver_t out{ receiver_t out{maker_t{}(std::move(args_))}; (void)out;
maker_t{}(std::move(args_))};
::folly::pushmi::submit((In &&) in, std::move(out)); ::folly::pushmi::submit((In &&) in, std::move(out));
} }
}; };
...@@ -148,8 +145,6 @@ struct blocking_submit_fn { ...@@ -148,8 +145,6 @@ struct blocking_submit_fn {
lock_state* state_; lock_state* state_;
Task t_; Task t_;
using properties = properties_t<Task>;
PUSHMI_TEMPLATE(class Out) PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>) // (requires Receiver<Out>) //
void submit(Out out) && { void submit(Out out) && {
...@@ -168,7 +163,7 @@ struct blocking_submit_fn { ...@@ -168,7 +163,7 @@ struct blocking_submit_fn {
lock_state* state_; lock_state* state_;
Out out_; Out out_;
using properties = properties_t<Out>; using receiver_category = receiver_category_t<Out>;
template <class V> template <class V>
void value(V&& v) { void value(V&& v) {
......
...@@ -29,20 +29,20 @@ struct tap_ { ...@@ -29,20 +29,20 @@ struct tap_ {
Out out; Out out;
// side effect has no effect on the properties. // side effect has no effect on the properties.
using properties = properties_t<Out>; using receiver_category = receiver_category_t<Out>;
PUSHMI_TEMPLATE(class... VN) PUSHMI_TEMPLATE(class... VN)
(requires ReceiveValue<SideEffects&, const std::remove_reference_t<VN>&...>&& (requires ReceiveValue<SideEffects&, const std::remove_reference_t<VN>&...>&&
ReceiveValue<Out&, VN...>) // ReceiveValue<Out&, VN...>) //
void value(VN&&... vn) { void value(VN&&... vn) {
set_value(sideEffects, as_const(vn)...); set_value(sideEffects, folly::as_const(vn)...);
set_value(out, (VN &&) vn...); set_value(out, (VN &&) vn...);
} }
PUSHMI_TEMPLATE(class E) PUSHMI_TEMPLATE(class E)
(requires ReceiveError<SideEffects&, const std::remove_reference_t<E>&>&& (requires ReceiveError<SideEffects&, const std::remove_reference_t<E>&>&&
ReceiveError<Out&, E>) // ReceiveError<Out&, E>) //
void error(E&& e) noexcept { void error(E&& e) noexcept {
set_error(sideEffects, as_const(e)); set_error(sideEffects, folly::as_const(e));
set_error(out, (E&&) e); set_error(out, (E&&) e);
} }
void done() { void done() {
...@@ -51,8 +51,7 @@ struct tap_ { ...@@ -51,8 +51,7 @@ struct tap_ {
} }
PUSHMI_TEMPLATE(class Up) PUSHMI_TEMPLATE(class Up)
(requires FlowReceiver<SideEffects>&& FlowReceiver<Out>) // (requires FlowReceiver<SideEffects>&& FlowReceiver<Out>) //
void starting( void starting(Up&& up) {
Up&& up) {
// up is not made const because sideEffects is allowed to call methods on up // up is not made const because sideEffects is allowed to call methods on up
set_starting(sideEffects, up); set_starting(sideEffects, up);
set_starting(out, (Up &&) up); set_starting(out, (Up &&) up);
...@@ -105,8 +104,8 @@ struct tap_fn { ...@@ -105,8 +104,8 @@ struct tap_fn {
using receiver_t = using receiver_t =
invoke_result_t<receiver_from_fn<std::decay_t<In>>, tap_t<Out>>; invoke_result_t<receiver_from_fn<std::decay_t<In>>, tap_t<Out>>;
PUSHMI_TEMPLATE(class Data, class Out) PUSHMI_TEMPLATE(class Data, class Out)
(requires Receiver<std::decay_t<Out>> (requires Receiver<std::decay_t<Out>> &&
&& SenderTo<In, Out>&& SenderTo<In, Out>&&
SenderTo<In, receiver_t<Out>>) // SenderTo<In, receiver_t<Out>>) //
auto operator()(Data&& in, Out&& out) const { auto operator()(Data&& in, Out&& out) const {
auto gang{receiver_from_fn<std::decay_t<In>>()( auto gang{receiver_from_fn<std::decay_t<In>>()(
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
namespace folly { namespace folly {
namespace pushmi { namespace pushmi {
namespace detail { namespace detail {
template <class Exec> template <class Exec>
...@@ -36,13 +35,14 @@ struct via_fn_base { ...@@ -36,13 +35,14 @@ struct via_fn_base {
template <class Exec, class Out> template <class Exec, class Out>
struct via_fn_data : via_fn_base<Exec> { struct via_fn_data : via_fn_base<Exec> {
via_fn_data(Out out, Exec exec) via_fn_data(Out out, Exec exec)
: via_fn_base<Exec>(std::move(exec)), out_(std::make_shared<Out>(std::move(out))) {} : via_fn_base<Exec>(std::move(exec))
, out_(std::make_shared<Out>(std::move(out))) {}
using properties = properties_t<Out>; using receiver_category = receiver_category_t<Out>;
template <class CPO, class... AN> template <class CPO, class... AN>
struct impl { struct impl {
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
const CPO& fn_; const CPO& fn_;
std::tuple<Out&, AN...> an_; std::tuple<Out&, AN...> an_;
std::shared_ptr<Out> out_; std::shared_ptr<Out> out_;
...@@ -109,22 +109,23 @@ struct via_fn { ...@@ -109,22 +109,23 @@ struct via_fn {
template <class In, class Factory> template <class In, class Factory>
struct submit_impl { struct submit_impl {
Factory ef_; Factory ef_;
PUSHMI_TEMPLATE(class SIn, class Out) PUSHMI_TEMPLATE(class SIn, class Out)
(requires Receiver<Out>) // (requires Receiver<Out>) //
void void operator()(SIn&& in, Out out) const {
operator()(SIn&& in, Out out) const {
auto exec = ::folly::pushmi::make_strand(ef_); auto exec = ::folly::pushmi::make_strand(ef_);
::folly::pushmi::submit((In &&) in, ::folly::pushmi::submit((In &&) in,
make_via_fn_data(std::move(out), std::move(exec))); make_via_fn_data(std::move(out), std::move(exec)));
} }
}; };
template <class Factory> template <class Factory>
struct adapt_impl { struct adapt_impl {
Factory ef_; Factory ef_;
PUSHMI_TEMPLATE(class In) PUSHMI_TEMPLATE(class In)
(requires Sender<In>) // (requires Sender<In>) //
auto auto operator()(In&& in) const {
operator()(In&& in) const {
return ::folly::pushmi::detail::sender_from( return ::folly::pushmi::detail::sender_from(
(In&&)in, (In&&)in,
submit_impl<In&&, Factory>{ef_}); submit_impl<In&&, Factory>{ef_});
......
...@@ -113,14 +113,13 @@ concept PropertySet, ...@@ -113,14 +113,13 @@ concept PropertySet,
// customization point for a type with properties // customization point for a type with properties
template <class T, class Void=void> template <class T, class = void>
struct member_properties { struct member_properties {
using properties = property_set<>; using properties = property_set<>;
}; };
template <class T> template <class T>
struct member_properties< struct member_properties<T, void_t<typename T::properties>> {
T, void_t<typename T::properties>> {
using properties = typename T::properties; using properties = typename T::properties;
}; };
...@@ -132,7 +131,7 @@ template <class T, class Void> ...@@ -132,7 +131,7 @@ template <class T, class Void>
struct property_set_traits : std::conditional_t< struct property_set_traits : std::conditional_t<
std::is_same<T, std::decay_t<T>>::value, std::is_same<T, std::decay_t<T>>::value,
member_properties<T>, member_properties<T>,
property_set_traits<std::decay_t<T>, Void>> property_set_traits<std::decay_t<T>>>
{}; {};
template <class T, class Target, class Void> template <class T, class Target, class Void>
...@@ -143,13 +142,14 @@ PUSHMI_INLINE_VAR constexpr bool property_set_traits_disable_v = ...@@ -143,13 +142,14 @@ PUSHMI_INLINE_VAR constexpr bool property_set_traits_disable_v =
property_set_traits_disable<T, Target>::value; property_set_traits_disable<T, Target>::value;
template <class T> template <class T>
using properties_t = std::enable_if_t< using properties_t =
std::enable_if_t<
PropertySet<__properties_t<property_set_traits<T>>>, PropertySet<__properties_t<property_set_traits<T>>>,
__properties_t<property_set_traits<T>>>; __properties_t<property_set_traits<T>>>;
PUSHMI_CONCEPT_DEF( PUSHMI_CONCEPT_DEF(
template(class T) template(class T)
concept Properties, concept Properties,
PropertySet<__properties_t<property_set_traits<T>>> PropertySet<__properties_t<property_set_traits<T>>>
); );
......
...@@ -117,7 +117,7 @@ class any_receiver { ...@@ -117,7 +117,7 @@ class any_receiver {
} }
public: public:
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
any_receiver() = default; any_receiver() = default;
any_receiver(any_receiver&& that) noexcept : any_receiver() { any_receiver(any_receiver&& that) noexcept : any_receiver() {
...@@ -191,7 +191,7 @@ class receiver<VF, EF, DF> { ...@@ -191,7 +191,7 @@ class receiver<VF, EF, DF> {
"error function must be noexcept and support std::exception_ptr"); "error function must be noexcept and support std::exception_ptr");
public: public:
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
receiver() = default; receiver() = default;
constexpr explicit receiver(VF vf) : receiver(std::move(vf), EF{}, DF{}) {} constexpr explicit receiver(VF vf) : receiver(std::move(vf), EF{}, DF{}) {}
...@@ -268,7 +268,7 @@ class receiver<Data, DVF, DEF, DDF> { ...@@ -268,7 +268,7 @@ class receiver<Data, DVF, DEF, DDF> {
"error function must be noexcept and support std::exception_ptr"); "error function must be noexcept and support std::exception_ptr");
public: public:
using properties = properties_t<Data>; using receiver_category = receiver_tag;
constexpr explicit receiver(Data d) constexpr explicit receiver(Data d)
: receiver(std::move(d), DVF{}, DEF{}, DDF{}) {} : receiver(std::move(d), DVF{}, DEF{}, DDF{}) {}
......
...@@ -121,8 +121,6 @@ class any_single_sender ...@@ -121,8 +121,6 @@ class any_single_sender
using wrapped_t = using wrapped_t =
std::enable_if_t<!std::is_same<U, any_single_sender>::value, U>; std::enable_if_t<!std::is_same<U, any_single_sender>::value, U>;
public: public:
using properties = property_set<>;
any_single_sender() = default; any_single_sender() = default;
any_single_sender(any_single_sender&& that) noexcept : any_single_sender() { any_single_sender(any_single_sender&& that) noexcept : any_single_sender() {
that.vptr_->op_(that.data_, &data_); that.vptr_->op_(that.data_, &data_);
...@@ -160,7 +158,6 @@ class single_sender<SF> { ...@@ -160,7 +158,6 @@ class single_sender<SF> {
public: public:
using sender_category = single_sender_tag; using sender_category = single_sender_tag;
using properties = property_set<>;
constexpr single_sender() = default; constexpr single_sender() = default;
constexpr explicit single_sender(SF sf) : sf_(std::move(sf)) {} constexpr explicit single_sender(SF sf) : sf_(std::move(sf)) {}
...@@ -182,7 +179,6 @@ class single_sender<Data, DSF> { ...@@ -182,7 +179,6 @@ class single_sender<Data, DSF> {
public: public:
using sender_category = single_sender_tag; using sender_category = single_sender_tag;
using properties = properties_t<Data>;
static_assert( static_assert(
SingleSender<Data>, SingleSender<Data>,
......
...@@ -135,7 +135,7 @@ class strand_queue : public strand_queue_base<E> { ...@@ -135,7 +135,7 @@ class strand_queue : public strand_queue_base<E> {
auto what{std::move(this->front().what)}; auto what{std::move(this->front().what)};
this->items_.pop(); this->items_.pop();
guard.unlock(); guard.unlock();
set_error(what, detail::as_const(e)); set_error(what, folly::as_const(e));
guard.lock(); guard.lock();
} }
} }
...@@ -161,7 +161,7 @@ struct strand_queue_receiver : std::shared_ptr<strand_queue<E, Exec>> { ...@@ -161,7 +161,7 @@ struct strand_queue_receiver : std::shared_ptr<strand_queue<E, Exec>> {
~strand_queue_receiver() {} ~strand_queue_receiver() {}
explicit strand_queue_receiver(std::shared_ptr<strand_queue<E, Exec>> that) explicit strand_queue_receiver(std::shared_ptr<strand_queue<E, Exec>> that)
: std::shared_ptr<strand_queue<E, Exec>>(that) {} : std::shared_ptr<strand_queue<E, Exec>>(that) {}
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
}; };
template <class E, class Exec> template <class E, class Exec>
...@@ -184,9 +184,7 @@ class strand_task ...@@ -184,9 +184,7 @@ class strand_task
std::shared_ptr<strand_queue<E, Exec>> queue_; std::shared_ptr<strand_queue<E, Exec>> queue_;
public: public:
using properties = using properties = property_set<is_never_blocking<>>;
property_set<
property_set_index_t<properties_t<sender_t<Exec>>, is_never_blocking<>>>;
strand_task(std::shared_ptr<strand_queue<E, Exec>> queue) strand_task(std::shared_ptr<strand_queue<E, Exec>> queue)
: queue_(std::move(queue)) {} : queue_(std::move(queue)) {}
......
...@@ -30,8 +30,6 @@ struct subject; ...@@ -30,8 +30,6 @@ struct subject;
template <class PS, class... TN> template <class PS, class... TN>
struct subject<PS, TN...> : single_sender_tag::with_values<TN...> { struct subject<PS, TN...> : single_sender_tag::with_values<TN...> {
using properties = property_set<>;
struct subject_shared : single_sender_tag::with_values<TN...> { struct subject_shared : single_sender_tag::with_values<TN...> {
using receiver_t = any_receiver<std::exception_ptr, TN...>; using receiver_t = any_receiver<std::exception_ptr, TN...>;
bool done_ = false; bool done_ = false;
...@@ -104,7 +102,7 @@ struct subject<PS, TN...> : single_sender_tag::with_values<TN...> { ...@@ -104,7 +102,7 @@ struct subject<PS, TN...> : single_sender_tag::with_values<TN...> {
}; };
struct subject_receiver { struct subject_receiver {
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
std::shared_ptr<subject_shared> s; std::shared_ptr<subject_shared> s;
......
...@@ -67,11 +67,11 @@ struct flow_single_sender_tag ...@@ -67,11 +67,11 @@ struct flow_single_sender_tag
detail::inherit<flow_sender_tag, single_sender_tag>> { detail::inherit<flow_sender_tag, single_sender_tag>> {
}; };
struct flow_category {}; struct receiver_tag {
};
// sender and receiver are mutually exclusive
struct receiver_category {}; struct flow_receiver_tag : receiver_tag {
};
// blocking affects senders // blocking affects senders
...@@ -83,20 +83,6 @@ struct sequence_category {}; ...@@ -83,20 +83,6 @@ struct sequence_category {};
// trait & tag types // trait & tag types
template <class... TN>
struct is_flow;
template <>
struct is_flow<> {
using property_category = flow_category;
};
template <class... TN>
struct is_receiver;
template <>
struct is_receiver<> {
using property_category = receiver_category;
};
template <class... TN> template <class... TN>
struct is_always_blocking; struct is_always_blocking;
template <> template <>
......
...@@ -198,7 +198,7 @@ class time_source_queue : public time_source_queue_base<E, TP> { ...@@ -198,7 +198,7 @@ class time_source_queue : public time_source_queue_base<E, TP> {
this->heap_.pop(); this->heap_.pop();
--s->items_; --s->items_;
guard.unlock(); guard.unlock();
set_error(what, detail::as_const(e)); set_error(what, folly::as_const(e));
guard.lock(); guard.lock();
} }
this->dispatching_ = false; this->dispatching_ = false;
...@@ -231,7 +231,7 @@ struct time_source_queue_receiver ...@@ -231,7 +231,7 @@ struct time_source_queue_receiver
std::shared_ptr<time_source_queue<E, TP, NF, Exec>> that) std::shared_ptr<time_source_queue<E, TP, NF, Exec>> that)
: std::shared_ptr<time_source_queue<E, TP, NF, Exec>>(that), : std::shared_ptr<time_source_queue<E, TP, NF, Exec>>(that),
source_(that->source_.lock()) {} source_(that->source_.lock()) {}
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
std::shared_ptr<time_source_shared<E, TP>> source_; std::shared_ptr<time_source_shared<E, TP>> source_;
}; };
...@@ -451,8 +451,7 @@ class time_source_task ...@@ -451,8 +451,7 @@ class time_source_task
std::shared_ptr<time_source_queue<E, time_point, NF, Exec>> queue_; std::shared_ptr<time_source_queue<E, time_point, NF, Exec>> queue_;
public: public:
using properties = property_set_insert_t<properties_t<sender_t<Exec>>, property_set< using properties = property_set<is_never_blocking<>>;
is_never_blocking<>>>;
time_source_task( time_source_task(
time_point tp, time_point tp,
......
...@@ -17,7 +17,10 @@ ...@@ -17,7 +17,10 @@
#include <type_traits> #include <type_traits>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/experimental/pushmi/detail/concept_def.h> #include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/functional.h>
#define PUSHMI_NOEXCEPT_AUTO(...) \ #define PUSHMI_NOEXCEPT_AUTO(...) \
noexcept(noexcept(static_cast<decltype((__VA_ARGS__))>(__VA_ARGS__)))\ noexcept(noexcept(static_cast<decltype((__VA_ARGS__))>(__VA_ARGS__)))\
...@@ -216,13 +219,28 @@ constexpr bool is_v = is_<T, C>::value; ...@@ -216,13 +219,28 @@ constexpr bool is_v = is_<T, C>::value;
template <bool B, class T = void> template <bool B, class T = void>
using requires_ = std::enable_if_t<B, T>; using requires_ = std::enable_if_t<B, T>;
PUSHMI_INLINE_VAR constexpr struct as_const_fn { template <bool>
struct Enable_ {};
template <>
struct Enable_<true> {
template <class T> template <class T>
constexpr const T& operator()(T& t) const noexcept { using _type = T;
return t; };
}
} const as_const{};
template <class...>
struct Front_ {};
template <class T, class... Us>
struct Front_<T, Us...> {
using type = T;
};
// An alias for the type in the pack if the pack has exactly one type in it.
// Otherwise, this SFINAE's away. T cannot be an array type of an abstract type.
// Instantiation proceeds from left to right. The use of Enable_ here avoids
// needless instantiations of Front_.
template<class...Ts>
using identity_t = typename Enable_<sizeof...(Ts) == 1u>::
template _type<Front_<Ts...>>::type;
} // namespace detail } // namespace detail
} // namespace pushmi } // namespace pushmi
......
...@@ -118,7 +118,7 @@ class trampoline { ...@@ -118,7 +118,7 @@ class trampoline {
template<class SingleReceiver> template<class SingleReceiver>
struct delegate_impl { struct delegate_impl {
using properties = property_set<is_receiver<>>; using receiver_category = receiver_tag;
std::decay_t<SingleReceiver> out_; std::decay_t<SingleReceiver> out_;
void value(){ void value(){
delegator<E> that; delegator<E> that;
......
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