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

reorganize pushmi headers

Summary:
The pushmi library has grown to the point where a little more structure would aid comprehensibility.

Also, finer-grained headers and build targets would make it easier for downstream projects to include only what they absolutely need.

Reviewed By: kirkshoop

Differential Revision: D14802895

fbshipit-source-id: 8d253f97c5d0529530cc3b7110505000f513ce83
parent 8e5c2b92
......@@ -24,7 +24,7 @@
#endif
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/detail/sender_concepts.h>
#include <folly/experimental/pushmi/sender/detail/concepts.h>
#include <folly/experimental/pushmi/traits.h>
namespace folly {
......
......@@ -27,11 +27,12 @@
#if defined(__cpp_coroutines)
#include <folly/experimental/coro/detail/ManualLifetime.h>
#endif
#include <folly/experimental/pushmi/detail/awaitable_concepts.h>
#include <folly/experimental/pushmi/detail/sender_concepts.h>
#include <folly/experimental/pushmi/extension_points.h>
#include <folly/experimental/pushmi/awaitable/concepts.h>
#include <folly/experimental/pushmi/sender/detail/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/tags.h>
#include <folly/experimental/pushmi/receiver/tags.h>
namespace folly {
namespace pushmi {
......@@ -171,8 +172,7 @@ template<typename From>
sender_awaiter(From&&) -> sender_awaiter<From>;
#endif
namespace awaitable_senders
{
namespace awaitable_senders {
// Any TypedSender that inherits from `sender` or `sender_traits` is
// automatically awaitable with the following operator co_await through the
// magic of associated namespaces. To make any other TypedSender awaitable,
......@@ -181,11 +181,10 @@ namespace awaitable_senders
PUSHMI_TEMPLATE(class From)( //
requires not lazy::Awaiter<From> && lazy::SingleTypedSender<From> //
) //
sender_awaiter<From> operator co_await(From&& from)
{
sender_awaiter<From> operator co_await(From&& from) {
return static_cast<From&&>(from);
}
}
} // namespace awaitable_senders
#endif
......
......@@ -28,12 +28,14 @@
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/new_thread.h>
#include <folly/experimental/pushmi/time_source.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/new_thread.h>
#include <folly/experimental/pushmi/executor/time_source.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
#include <folly/experimental/pushmi/entangle.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/examples/pool.h>
......
......@@ -15,9 +15,11 @@
*/
#pragma once
#include <folly/functional/Invoke.h>
#include <utility>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/traits.h>
#include <folly/functional/Invoke.h>
namespace folly {
namespace pushmi {
......@@ -35,7 +37,7 @@ PUSHMI_CONCEPT_DEF(
template (class F, class... Args)
(concept Invocable)(F, Args...),
requires(F&& f) (
::folly::pushmi::invoke((F &&) f, std::declval<Args>()...)
pushmi::invoke((F &&) f, std::declval<Args>()...)
)
);
......@@ -43,10 +45,93 @@ PUSHMI_CONCEPT_DEF(
template (class F, class... Args)
(concept NothrowInvocable)(F, Args...),
requires(F&& f) (
requires_<noexcept(::folly::pushmi::invoke((F &&) f, std::declval<Args>()...))>
requires_<noexcept(pushmi::invoke((F &&) f, std::declval<Args>()...))>
) &&
Invocable<F, Args...>
);
//
// construct_deduced
//
// For emulating CTAD on compilers that don't support it. Must be specialized.
template <template <class...> class T>
struct construct_deduced;
template <template <class...> class T, class... AN>
using deduced_type_t = invoke_result_t<construct_deduced<T>, AN...>;
//
// overload
//
// inspired by Ovrld - shown in a presentation by Nicolai Josuttis
#if __cpp_variadic_using >= 201611 && __cpp_concepts
template <SemiMovable... Fns>
requires sizeof...(Fns) > 0
struct overload_fn : Fns... {
constexpr overload_fn() = default;
constexpr explicit overload_fn(Fns... fns) requires sizeof...(Fns) == 1
: Fns(std::move(fns))... {}
constexpr overload_fn(Fns... fns) requires sizeof...(Fns) > 1
: Fns(std::move(fns))... {}
using Fns::operator()...;
};
#else
template <PUSHMI_TYPE_CONSTRAINT(SemiMovable)... Fns>
#if __cpp_concepts
requires sizeof...(Fns) > 0
#endif
struct overload_fn;
template <class Fn>
struct overload_fn<Fn> : Fn {
constexpr overload_fn() = default;
constexpr explicit overload_fn(Fn fn)
: Fn(std::move(fn)) {}
using Fn::operator();
};
#if !defined(__GNUC__) || __GNUC__ >= 8
template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> {
constexpr overload_fn() = default;
constexpr overload_fn(Fn fn, Fns... fns)
: Fn(std::move(fn)), overload_fn<Fns...>{std::move(fns)...} {}
using Fn::operator();
using overload_fn<Fns...>::operator();
};
#else
template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> {
private:
std::pair<Fn, overload_fn<Fns...>> fns_;
template <bool B>
using _which_t = std::conditional_t<B, Fn, overload_fn<Fns...>>;
public:
constexpr overload_fn() = default;
constexpr overload_fn(Fn fn, Fns... fns)
: fns_{std::move(fn), overload_fn<Fns...>{std::move(fns)...}} {}
PUSHMI_TEMPLATE (class... Args)
(requires lazy::Invocable<Fn&, Args...> ||
lazy::Invocable<overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) noexcept(noexcept(
std::declval<_which_t<Invocable<Fn&, Args...>>&>()(std::declval<Args>()...))) {
return std::get<!Invocable<Fn&, Args...>>(fns_)((Args &&) args...);
}
PUSHMI_TEMPLATE (class... Args)
(requires lazy::Invocable<const Fn&, Args...> ||
lazy::Invocable<const overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) const noexcept(noexcept(
std::declval<const _which_t<Invocable<const Fn&, Args...>>&>()(std::declval<Args>()...))) {
return std::get<!Invocable<const Fn&, Args...>>(fns_)((Args &&) args...);
}
};
#endif
#endif
template <class... Fns>
auto overload(Fns... fns) -> overload_fn<Fns...> {
return overload_fn<Fns...>{std::move(fns)...};
}
} // namespace pushmi
} // namespace folly
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <type_traits>
#include <folly/experimental/pushmi/detail/concept_def.h>
namespace folly {
namespace pushmi {
PUSHMI_CONCEPT_DEF(
template (class T)
concept Object,
requires (T* p) (
*p,
implicitly_convertible_to<const volatile void*>(p)
)
);
PUSHMI_CONCEPT_DEF(
template (class T, class... Args)
(concept Constructible)(T, Args...),
PUSHMI_PP_IS_CONSTRUCTIBLE(T, Args...)
);
PUSHMI_CONCEPT_DEF(
template (class From, class To)
concept ConvertibleTo,
requires (From (&f)()) (
static_cast<To>(f())
) && std::is_convertible<From, To>::value
);
PUSHMI_CONCEPT_DEF(
template (class T)
concept SemiMovable,
Object<T> && Constructible<T, T> && ConvertibleTo<T, T>
);
} // namespace pushmi
} // namespace folly
......@@ -15,7 +15,7 @@
*/
#pragma once
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
namespace folly {
namespace pushmi {
......
......@@ -23,7 +23,7 @@
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/strand.h>
#include <folly/experimental/pushmi/executor/strand.h>
using namespace folly::pushmi::aliases;
......
......@@ -16,7 +16,7 @@
#include <cstdio>
#include <iostream>
#include <folly/experimental/pushmi/strand.h>
#include <folly/experimental/pushmi/executor/strand.h>
#include <folly/experimental/pushmi/o/request_via.h>
#include <folly/experimental/pushmi/o/tap.h>
......
......@@ -16,7 +16,7 @@
#pragma once
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
namespace folly {
namespace pushmi {
......
......@@ -16,7 +16,10 @@
#pragma once
#include <folly/experimental/pushmi/properties.h>
#include <folly/experimental/pushmi/concepts.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/sender/tags.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <folly/Executor.h>
#include <folly/executors/CPUThreadPoolExecutor.h>
......
......@@ -23,7 +23,7 @@
#include <utility>
#include <vector>
#include <folly/experimental/pushmi/strand.h>
#include <folly/experimental/pushmi/executor/strand.h>
#include <folly/experimental/pushmi/o/just.h>
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h>
......
......@@ -15,127 +15,17 @@
*/
#pragma once
#include <functional>
#include <utility>
#include <folly/experimental/pushmi/extension_points.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/properties.h>
#include <folly/experimental/pushmi/tags.h>
#include <folly/experimental/pushmi/detail/sender_concepts.h>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/sender/detail/concepts.h>
#include <folly/experimental/pushmi/executor/primitives.h>
#include <folly/experimental/pushmi/executor/properties.h>
namespace folly {
namespace pushmi {
// add concepts to support receivers
//
/// \cond
namespace detail {
template <class R, class = void>
struct basic_receiver_traits {
};
template <class R>
struct basic_receiver_traits<R, void_t<typename R::receiver_category>> {
using receiver_category = typename R::receiver_category;
};
} // namespace detail
/// \endcond
template<typename R, typename>
struct receiver_traits
: std::conditional_t<
std::is_same<std::decay_t<R>, R>::value,
detail::basic_receiver_traits<R>,
receiver_traits<std::decay_t<R>>> {
using _not_specialized = void;
};
PUSHMI_CONCEPT_DEF(
template(class R) //
(concept Receiver)(R), //
requires(R& r)( //
set_done(r) //
) && //
SemiMovable<std::decay_t<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(
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) //
(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 R) //
(concept SenderTo)(S, R), //
requires(S&& s, R&& r) //
(pushmi::submit((S &&) s, (R &&) r)) &&
Sender<S> && Receiver<R>);
// is_always_blocking trait and tag
template <class PS>
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;
// is_never_blocking trait
template <class PS>
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;
// is_maybe_blocking trait
template <class PS>
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;
// is_fifo_sequence trait
template <class PS>
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;
// is_concurrent_sequence trait
template <class PS>
struct is_concurrent_sequence<PS>
: property_query<PS, is_concurrent_sequence<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_concurrent_sequence_v =
is_concurrent_sequence<PS>::value;
// concepts to support execution
//
......@@ -249,51 +139,5 @@ PUSHMI_PP_CONSTRAINED_USING(
time_point_t =,
decltype(now(std::declval<Exec&>())));
// add concepts to support cancellation and rate control
//
PUSHMI_CONCEPT_DEF(
template(class R) //
(concept FlowReceiver)(R), //
Receiver<R>&&
DerivedFrom<receiver_category_t<R>, flow_receiver_tag>);
PUSHMI_CONCEPT_DEF(
template(class R, class... VN) //
(concept FlowReceiveValue)(R, VN...), //
FlowReceiver<R>&& ReceiveValue<R, VN...>);
PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) //
(concept FlowReceiveError)(R, E), //
FlowReceiver<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) //
) &&
FlowReceiver<R>
);
PUSHMI_CONCEPT_DEF(
template(class S) //
(concept FlowSender)(S), //
Sender<S>&&
DerivedFrom<sender_category_t<S>, flow_sender_tag>
);
PUSHMI_CONCEPT_DEF(
template(class S, class R) //
(concept FlowSenderTo)(S, R), //
FlowSender<S> && //
SenderTo<S, R>&& //
FlowReceiver<R>
);
} // namespace pushmi
} // namespace folly
// Make all single typed senders also awaitable:
#include <folly/experimental/pushmi/detail/sender_adapter.h>
This diff is collapsed.
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <exception>
#include <functional>
#include <type_traits>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/executor/concepts.h>
#include <folly/experimental/pushmi/executor/functional.h>
#include <folly/experimental/pushmi/executor/primitives.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
#include <folly/experimental/pushmi/traits.h>
namespace folly {
namespace pushmi {
//
// define types for executors
template <class E>
class any_executor {
using insitu_t = void*[2];
union data {
void* pobj_ = nullptr;
std::aligned_union_t<0, insitu_t> buffer_;
} data_{};
template <class Wrapped>
static constexpr bool insitu() {
return sizeof(Wrapped) <= sizeof(data::buffer_) &&
std::is_nothrow_move_constructible<Wrapped>::value;
}
struct vtable {
static void s_op(data&, data*) {}
static void s_consume_op(data&&, data*) {}
static any_single_sender<E, any_executor_ref<E>> s_schedule(data&) { return {}; }
void (*op_)(data&, data*) = vtable::s_op;
void (*consume_op_)(data&, data*) = vtable::s_consume_op;
any_single_sender<E, any_executor_ref<E>> (*schedule_)(data&) = vtable::s_schedule;
};
static constexpr vtable const noop_{};
vtable const* vptr_ = &noop_;
template <class Wrapped>
any_executor(Wrapped obj, std::false_type) : any_executor() {
struct s {
static void op(data& src, data* dst) {
dst->pobj_ = new Wrapped(*static_cast<Wrapped const*>(src.pobj_));
}
static void consume_op(data&& src, data* dst) {
if (dst)
dst->pobj_ = std::exchange(src.pobj_, nullptr);
delete static_cast<Wrapped const*>(src.pobj_);
}
static any_single_sender<E, any_executor_ref<E>> schedule(data& src) {
return any_single_sender<E, any_executor_ref<E>>{::folly::pushmi::schedule(
*static_cast<Wrapped*>(src.pobj_))};
}
};
static const vtable vtbl{s::op, s::consume_op, s::schedule};
data_.pobj_ = new Wrapped(std::move(obj));
vptr_ = &vtbl;
}
template <class Wrapped>
any_executor(Wrapped obj, std::true_type) noexcept
: any_executor() {
struct s {
static void op(data& src, data* dst) {
new (dst->buffer_)
Wrapped(*static_cast<Wrapped*>((void*)src.buffer_));
}
static void consume_op(data& src, data* dst) {
if (dst)
new (dst->buffer_)
Wrapped(std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
}
static any_single_sender<E, any_executor_ref<E>> schedule(data& src) {
return any_single_sender<E, any_executor_ref<E>>{::folly::pushmi::schedule(
*static_cast<Wrapped*>((void*)src.buffer_))};
}
};
static const vtable vtbl{s::op, s::consume_op, s::schedule};
new (data_.buffer_) Wrapped(std::move(obj));
vptr_ = &vtbl;
}
template <class T, class U = std::decay_t<T>>
using wrapped_t =
std::enable_if_t<!std::is_same<U, any_executor>::value, U>;
public:
any_executor() = default;
any_executor(const any_executor& that) noexcept : any_executor() {
that.vptr_->op_(that.data_, &data_);
std::swap(that.vptr_, vptr_);
}
any_executor(any_executor&& that) noexcept : any_executor() {
that.vptr_->consume_op_(std::move(that.data_), &data_);
std::swap(that.vptr_, vptr_);
}
PUSHMI_TEMPLATE(class Wrapped)
(requires Executor<wrapped_t<Wrapped>>) //
explicit any_executor(Wrapped obj) noexcept(insitu<Wrapped>())
: any_executor{std::move(obj), bool_<insitu<Wrapped>()>{}} {}
~any_executor() {
vptr_->consume_op_(std::move(data_), nullptr);
}
any_executor& operator=(const any_executor& that) noexcept {
this->~any_executor();
new ((void*)this) any_executor(that);
return *this;
}
any_executor& operator=(any_executor&& that) noexcept {
this->~any_executor();
new ((void*)this) any_executor(std::move(that));
return *this;
}
any_single_sender<E, any_executor_ref<E>> schedule() {
return vptr_->schedule_(data_);
}
};
// Class static definitions:
template <class E>
constexpr typename any_executor<E>::vtable const
any_executor<E>::noop_;
template <class SF>
class executor<SF> {
SF sf_;
public:
constexpr executor() = default;
constexpr explicit executor(SF sf) : sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class SF_ = SF)
(requires Invocable<SF_&>) //
auto schedule() {
return sf_();
}
};
template <
PUSHMI_TYPE_CONSTRAINT(Executor) Data,
class DSF>
class executor<Data, DSF> {
Data data_;
DSF sf_;
public:
using properties = properties_t<Data>;
constexpr executor() = default;
constexpr explicit executor(Data data) : data_(std::move(data)) {}
constexpr executor(Data data, DSF sf)
: data_(std::move(data)), sf_(std::move(sf)) {}
PUSHMI_TEMPLATE(class DSF_ = DSF)
(requires Invocable<DSF_&, Data&>) //
auto schedule() {
return sf_(data_);
}
};
template <>
class executor<> : public executor<ignoreSF> {
public:
executor() = default;
};
////////////////////////////////////////////////////////////////////////////////
// make_executor
PUSHMI_INLINE_VAR constexpr struct make_executor_fn {
inline auto operator()() const {
return executor<ignoreSF>{};
}
PUSHMI_TEMPLATE(class SF)
(requires not Executor<SF>) //
auto operator()(SF sf) const {
return executor<SF>{std::move(sf)};
}
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Executor<Data>) //
auto operator()(Data d) const {
return executor<Data, passDSF>{std::move(d)};
}
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Executor<Data>) //
auto operator()(Data d, DSF sf) const {
return executor<Data, DSF>{std::move(d), std::move(sf)};
}
} const make_executor{};
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703 && PUSHMI_NOT_ON_WINDOWS
executor()->executor<ignoreSF>;
PUSHMI_TEMPLATE(class SF)
(requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not Executor<SF>)) //
executor(SF)
->executor<SF>;
PUSHMI_TEMPLATE(class Data)
(requires True<>&& Executor<Data>) //
executor(Data)
->executor<Data, passDSF>;
PUSHMI_TEMPLATE(class Data, class DSF)
(requires Executor<Data>) //
executor(Data, DSF)
->executor<Data, DSF>;
#endif
template <>
struct construct_deduced<executor> : make_executor_fn {};
template <class E>
struct any_executor_ref {
private:
using This = any_executor_ref;
void* pobj_;
struct vtable {
any_single_sender<E, any_executor_ref<E>> (*schedule_)(void*);
} const* vptr_;
template <class T, class U = std::decay_t<T>>
using wrapped_t =
std::enable_if_t<!std::is_same<U, any_executor_ref>::value, U>;
public:
any_executor_ref() = delete;
any_executor_ref(const any_executor_ref&) = default;
PUSHMI_TEMPLATE(class Wrapped)
(requires Executor<wrapped_t<Wrapped>>) //
any_executor_ref(Wrapped& w) {
struct s {
static any_single_sender<E, any_executor_ref<E>> schedule(void* pobj) {
return any_single_sender<E, any_executor_ref<E>>{
::folly::pushmi::schedule(*static_cast<Wrapped*>(pobj))};
}
};
static const vtable vtbl{s::schedule};
pobj_ = std::addressof(w);
vptr_ = &vtbl;
}
template<class... AN>
any_single_sender<E, any_executor_ref<E>> schedule() {
return vptr_->schedule_(pobj_);
}
};
////////////////////////////////////////////////////////////////////////////////
// make_any_executor_ref
template <class E = std::exception_ptr>
auto make_any_executor_ref() {
return any_executor_ref<E>{};
}
PUSHMI_TEMPLATE(class E = std::exception_ptr, class Ex)
(requires Executor<Ex> && !detail::is_v<Ex, any_executor_ref>) //
auto make_any_executor_ref(Ex& w) {
return any_executor_ref<E>{w};
}
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703 && PUSHMI_NOT_ON_WINDOWS
any_executor_ref()->any_executor_ref<std::exception_ptr>;
PUSHMI_TEMPLATE(class Ex)
(requires Executor<Ex> && !detail::is_v<Ex, any_executor_ref>) //
any_executor_ref(Ex&)
->any_executor_ref<std::exception_ptr>;
#endif
} // namespace pushmi
} // namespace folly
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <chrono>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/executor/concepts.h>
#include <folly/experimental/pushmi/executor/primitives.h>
namespace folly {
namespace pushmi {
struct systemNowF {
auto operator()() { return std::chrono::system_clock::now(); }
};
struct priorityZeroF {
auto operator()(){ return 0; }
};
struct passDNF {
PUSHMI_TEMPLATE(class Data)
(requires TimeExecutor<Data>)
auto operator()(Data& in) const noexcept {
return ::folly::pushmi::now(in);
}
};
struct passDZF {
PUSHMI_TEMPLATE(class Data)
(requires ConstrainedExecutor<Data>)
auto operator()(Data& in) const noexcept {
return ::folly::pushmi::top(in);
}
};
template <class Fn>
struct on_executor_fn : overload_fn<Fn> {
constexpr on_executor_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_executor(Fn fn) -> on_executor_fn<Fn> {
return on_executor_fn<Fn>{std::move(fn)};
}
template <class Fn>
struct on_make_strand_fn : overload_fn<Fn> {
constexpr on_make_strand_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_make_strand(Fn fn) -> on_make_strand_fn<Fn> {
return on_make_strand_fn<Fn>{std::move(fn)};
}
template <class... Fns>
struct on_schedule_fn : overload_fn<Fns...> {
constexpr on_schedule_fn() = default;
using overload_fn<Fns...>::overload_fn;
};
template <class... Fns>
auto on_schedule(Fns... fns) -> on_schedule_fn<Fns...> {
return on_schedule_fn<Fns...>{std::move(fns)...};
}
template <class Fn>
struct on_now_fn : overload_fn<Fn> {
constexpr on_now_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_now(Fn fn) -> on_now_fn<Fn> {
return on_now_fn<Fn>{std::move(fn)};
}
} // namespace pushmi
} // namespace folly
......@@ -15,7 +15,9 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <folly/experimental/pushmi/sender/properties.h>
namespace folly {
namespace pushmi {
......
......@@ -15,8 +15,10 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/executor/properties.h>
namespace folly {
namespace pushmi {
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <utility>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/lang/CustomizationPoint.h>
namespace folly {
namespace pushmi {
namespace _adl {
//
// support methods on a class reference
//
PUSHMI_TEMPLATE(class SD)
(requires //
requires(std::declval<SD&>().executor())) //
auto get_executor(SD& sd) //
noexcept(noexcept(sd.executor())) {
return sd.executor();
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(std::declval<SD&>().make_strand())) //
auto make_strand(SD& sd) //
noexcept(noexcept(sd.make_strand())) {
return sd.make_strand();
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(std::declval<SD&>().top())) //
auto top(SD& sd) //
noexcept(noexcept(sd.top())) {
return sd.top();
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(std::declval<SD&>().schedule())) //
auto schedule(SD& sd) //
noexcept(noexcept(sd.schedule())) {
return sd.schedule();
}
PUSHMI_TEMPLATE(class SD, class TP)
(requires //
requires(std::declval<SD&>().schedule(
std::declval<TP (&)(TP)>()(top(std::declval<SD&>()))))) //
auto schedule(SD& sd, TP tp) //
noexcept(noexcept(sd.schedule(std::move(tp)))) {
return sd.schedule(std::move(tp));
}
//
// support methods on a class pointer
//
PUSHMI_TEMPLATE(class SD)
(requires //
requires(get_executor(*std::declval<SD>()))) //
auto get_executor(SD&& sd) //
noexcept(noexcept(get_executor(*sd))) {
return get_executor(*sd);
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(make_strand(*std::declval<SD>()))) //
auto make_strand(SD&& sd) //
noexcept(noexcept(make_strand(*sd))) {
return make_strand(*sd);
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(top(*std::declval<SD>()))) //
auto top(SD&& sd) //
noexcept(noexcept(top(*sd))) {
return top(*sd);
}
PUSHMI_TEMPLATE(class SD)
(requires //
requires(schedule(*std::declval<SD>()))) //
auto schedule(SD&& sd) //
noexcept(noexcept(schedule(*sd))) {
return schedule(*sd);
}
PUSHMI_TEMPLATE(class SD, class TP)
(requires //
requires(schedule(
*std::declval<SD>(),
std::declval<TP (&)(TP)>()(top(std::declval<SD&>()))))) //
auto schedule(SD&& sd, TP tp) //
noexcept(noexcept(schedule(*sd, std::move(tp)))) {
return schedule(*sd, std::move(tp));
}
//
// support a nullary function as a StrandFactory
//
PUSHMI_TEMPLATE(class S)
(requires Invocable<S&>) //
auto make_strand(S& s) //
noexcept(noexcept(s())) {
return s();
}
//
// accessors for free functions in this namespace
//
struct get_executor_fn {
PUSHMI_TEMPLATE(class SD)
(requires requires(get_executor(std::declval<SD&>()))) //
auto operator()(SD& sd) const //
noexcept(noexcept(get_executor(sd))) {
return get_executor(sd);
}
};
struct make_strand_fn {
PUSHMI_TEMPLATE(class SD)
(requires requires(make_strand(std::declval<SD&>()))) //
auto operator()(SD& sd) const //
noexcept(noexcept(make_strand(sd))) {
return make_strand(sd);
}
};
struct do_schedule_fn {
PUSHMI_TEMPLATE(class SD, class... VN)
(requires //
requires(schedule(std::declval<SD&>(), std::declval<VN>()...))) //
auto operator()(SD& s, VN&&... vn) const //
noexcept(noexcept(schedule(s, (VN &&) vn...))) {
return schedule(s, (VN &&) vn...);
}
};
struct get_top_fn {
PUSHMI_TEMPLATE(class SD)
(requires //
requires(top(std::declval<SD&>()))) //
auto operator()(SD& sd) const //
noexcept(noexcept(top(sd))) {
return top(sd);
}
};
} // namespace _adl
FOLLY_DEFINE_CPO(_adl::get_executor_fn, get_executor)
FOLLY_DEFINE_CPO(_adl::make_strand_fn, make_strand)
FOLLY_DEFINE_CPO(_adl::do_schedule_fn, schedule)
FOLLY_DEFINE_CPO(_adl::get_top_fn, now)
FOLLY_DEFINE_CPO(_adl::get_top_fn, top)
} // namespace pushmi
} // namespace folly
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/experimental/pushmi/properties.h>
namespace folly {
namespace pushmi {
// sequence affects executors
struct sequence_category {};
template <class... TN>
struct is_fifo_sequence;
template <>
struct is_fifo_sequence<> {
using property_category = sequence_category;
};
template <class PS>
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;
template <class... TN>
struct is_concurrent_sequence;
template <>
struct is_concurrent_sequence<> {
using property_category = sequence_category;
};
template <class PS>
struct is_concurrent_sequence<PS>
: property_query<PS, is_concurrent_sequence<>> {};
template <class PS>
PUSHMI_INLINE_VAR constexpr bool is_concurrent_sequence_v =
is_concurrent_sequence<PS>::value;
} // namespace pushmi
} // namespace folly
......@@ -15,8 +15,10 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <queue>
......
......@@ -16,7 +16,9 @@
#pragma once
#include <folly/experimental/pushmi/detail/opt.h>
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/executor/time_executor.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <algorithm>
#include <queue>
......
......@@ -15,13 +15,16 @@
*/
#pragma once
#include <folly/experimental/pushmi/piping.h>
#include <folly/experimental/pushmi/executor.h>
#include <algorithm>
#include <chrono>
#include <deque>
#include <thread>
#include <folly/experimental/pushmi/piping.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/executor/properties.h>
#include <folly/experimental/pushmi/sender/properties.h>
namespace folly {
namespace pushmi {
......@@ -65,7 +68,7 @@ struct trampoline_task
template <class E = std::exception_ptr>
class delegator : pipeorigin {
public:
using properties = property_set<is_fifo_sequence<>>;
using properties = property_set<is_fifo_sequence<>>;
trampoline_task<E, ownordelegate_t> schedule() {
return {};
......@@ -272,13 +275,6 @@ inline detail::nester<E> nested_trampoline() {
return {};
}
// see boosters.h
struct trampolineEXF {
auto operator()() {
return trampoline();
}
};
namespace detail {
PUSHMI_TEMPLATE(class E)
......
......@@ -16,15 +16,17 @@
#pragma once
#include <chrono>
#include <cstddef>
#include <exception>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/tags.h>
#include <folly/experimental/pushmi/properties.h>
#include <folly/experimental/pushmi/detail/traits.h>
namespace folly {
namespace pushmi {
// derive from this for types that need to find operator|() overloads by ADL
struct pipeorigin {};
// Traits types:
template <class T, class = void>
......@@ -133,5 +135,26 @@ std::false_type safe_to_test_awaitable(void*);
struct sender_adl_hook;
} // namespace awaitable_senders
template<template <class...> class T>
struct construct_deduced;
template<>
struct construct_deduced<receiver>;
template<>
struct construct_deduced<flow_receiver>;
template<>
struct construct_deduced<single_sender>;
template<>
struct construct_deduced<many_sender>;
template<>
struct construct_deduced<flow_single_sender>;
template<>
struct construct_deduced<flow_many_sender>;
} // namespace pushmi
} // namespace folly
......@@ -17,8 +17,8 @@
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
namespace folly {
namespace pushmi {
......
......@@ -18,6 +18,7 @@
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/sender/properties.h>
namespace folly {
namespace pushmi {
......
......@@ -17,6 +17,7 @@
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/sender/properties.h>
namespace folly {
namespace pushmi {
......
......@@ -15,23 +15,28 @@
*/
#pragma once
#include <folly/experimental/pushmi/boosters.h>
#include <folly/experimental/pushmi/concepts.h>
#include <tuple>
#include <folly/experimental/pushmi/executor/concepts.h>
#include <folly/experimental/pushmi/executor/primitives.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/primitives.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/inline.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/flow_many_sender.h>
#include <folly/experimental/pushmi/flow_receiver.h>
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/executor/inline.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
#include <folly/experimental/pushmi/sender/flow_many_sender.h>
#include <folly/experimental/pushmi/receiver/flow_receiver.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/many_sender.h>
#include <folly/experimental/pushmi/sender/many_sender.h>
#include <folly/experimental/pushmi/piping.h>
#include <folly/experimental/pushmi/properties.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
#include <folly/experimental/pushmi/traits.h>
#include <tuple>
namespace folly {
namespace pushmi {
......
......@@ -15,11 +15,12 @@
*/
#pragma once
#include <folly/experimental/pushmi/flow_many_sender.h>
#include <folly/experimental/pushmi/many_sender.h>
#include <folly/experimental/pushmi/sender/flow_many_sender.h>
#include <folly/experimental/pushmi/sender/many_sender.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
namespace folly {
namespace pushmi {
......
......@@ -17,6 +17,7 @@
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/sender/properties.h>
namespace folly {
namespace pushmi {
......
......@@ -15,7 +15,7 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/piping.h>
......
......@@ -18,7 +18,7 @@
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
namespace folly {
namespace pushmi {
......
......@@ -15,11 +15,8 @@
*/
#pragma once
#include <folly/experimental/pushmi/boosters.h>
#include <folly/experimental/pushmi/detail/opt.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <functional>
#include <folly/experimental/pushmi/executor/concepts.h>
#include <folly/experimental/pushmi/executor/primitives.h>
namespace folly {
namespace pushmi {
......
......@@ -17,9 +17,9 @@
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/subject.h>
#include <folly/experimental/pushmi/subject/subject.h>
namespace folly {
namespace pushmi {
......
......@@ -15,12 +15,20 @@
*/
#pragma once
#include <folly/experimental/pushmi/boosters.h>
#include <atomic>
#include <condition_variable>
#include <exception>
#include <functional>
#include <mutex>
#include <folly/experimental/pushmi/executor/concepts.h>
#include <folly/experimental/pushmi/executor/primitives.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/properties.h>
#include <folly/experimental/pushmi/detail/opt.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/schedule.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <functional>
namespace folly {
namespace pushmi {
......
......@@ -15,10 +15,10 @@
*/
#pragma once
#include <folly/experimental/pushmi/flow_receiver.h>
#include <folly/experimental/pushmi/receiver/flow_receiver.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
namespace folly {
namespace pushmi {
......
......@@ -15,7 +15,7 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/executor/executor.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/piping.h>
......
......@@ -15,7 +15,6 @@
*/
#pragma once
#include <folly/experimental/pushmi/concepts.h>
#include <folly/experimental/pushmi/traits.h>
namespace folly {
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <utility>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/receiver/primitives.h>
namespace folly {
namespace pushmi {
PUSHMI_CONCEPT_DEF(
template(class R) //
(concept Receiver)(R), //
requires(R& r)( //
set_done(r) //
) && //
SemiMovable<std::decay_t<R>> &&
True<typename receiver_traits<R>::receiver_category> &&
DerivedFrom<typename receiver_traits<R>::receiver_category, receiver_tag>
);
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) //
(concept ReceiveError)(R, E), //
requires(R& r, E&& e)( //
set_error(r, (E &&) e) //
) && //
Receiver<R> && //
MoveConstructible<E>
);
template <class R>
PUSHMI_PP_CONSTRAINED_USING(
Receiver<R>,
receiver_category_t =,
typename receiver_traits<R>::receiver_category
);
// add concepts to support cancellation and rate control
//
PUSHMI_CONCEPT_DEF(
template(class R) //
(concept FlowReceiver)(R), //
Receiver<R>&&
DerivedFrom<receiver_category_t<R>, flow_receiver_tag>);
PUSHMI_CONCEPT_DEF(
template(class R, class... VN) //
(concept FlowReceiveValue)(R, VN...), //
FlowReceiver<R>&& ReceiveValue<R, VN...>);
PUSHMI_CONCEPT_DEF(
template(class R, class E = std::exception_ptr) //
(concept FlowReceiveError)(R, E), //
FlowReceiver<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) //
) &&
FlowReceiver<R>
);
} // namespace pushmi
} // namespace folly
......@@ -15,9 +15,16 @@
*/
#pragma once
#include <folly/experimental/pushmi/receiver.h>
#include <type_traits>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/functional.h>
#include <folly/experimental/pushmi/receiver/primitives.h>
#include <folly/experimental/pushmi/receiver/tags.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
namespace folly {
namespace pushmi {
......
......@@ -15,57 +15,24 @@
*/
#pragma once
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <exception>
#include <functional>
#include <utility>
#include <folly/experimental/pushmi/concepts.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/primitives.h>
namespace folly {
namespace pushmi {
template<class T>
struct construct {
PUSHMI_TEMPLATE(class... AN)
(requires Constructible<T, AN...>)
auto operator()(AN&&... an) const {
return T{std::forward<AN>(an)...};
}
struct ignoreNF {
void operator()(detail::any) {}
};
template<template <class...> class T>
struct construct_deduced;
template<>
struct construct_deduced<receiver>;
template<>
struct construct_deduced<flow_receiver>;
template<>
struct construct_deduced<single_sender>;
template<>
struct construct_deduced<many_sender>;
template<>
struct construct_deduced<flow_single_sender>;
template<>
struct construct_deduced<flow_many_sender>;
template <template <class...> class T, class... AN>
using deduced_type_t =
::folly::pushmi::invoke_result_t<construct_deduced<T>, AN...>;
struct ignoreVF {
PUSHMI_TEMPLATE(class... VN)
(requires And<ConvertibleTo<VN&&, detail::any>...>)
template<class... VN>
void operator()(VN&&...) {}
};
......@@ -80,45 +47,20 @@ struct ignoreDF {
void operator()() {}
};
struct ignoreNF {
void operator()(detail::any) {}
};
struct ignoreStrtF {
void operator()(detail::any) {}
};
struct trampolineEXF;
// see trampoline.h
// struct trampolineEXF {
// auto operator()() { return trampoline(); }
// };
struct ignoreSF {
void operator()(detail::any) {}
void operator()(detail::any, detail::any) {}
};
struct systemNowF {
auto operator()() { return std::chrono::system_clock::now(); }
};
struct priorityZeroF {
auto operator()(){ return 0; }
};
struct passDVF {
PUSHMI_TEMPLATE(class Data, class... VN)
(requires requires (
set_value(std::declval<Data&>(), std::declval<VN>()...)
) && Receiver<Data>)
(requires ReceiveValue<Data, VN...>)
void operator()(Data& out, VN&&... vn) const {
set_value(out, (VN&&) vn...);
}
};
struct passDEF {
PUSHMI_TEMPLATE(class E, class Data)
PUSHMI_TEMPLATE(class Data, class E)
(requires ReceiveError<Data, E>)
void operator()(Data& out, E&& e) const noexcept {
set_error(out, (E&&)e);
......@@ -143,109 +85,6 @@ struct passDStrtF {
}
};
struct passDEXF {
PUSHMI_TEMPLATE(class Data)
(requires Sender<Data>)
auto operator()(Data& in) const noexcept {
return get_executor(in);
}
};
struct passDSF {
template <class Data, class Out>
void operator()(Data& in, Out out) {
submit(in, std::move(out));
}
template <class Data, class TP, class Out>
void operator()(Data& in, TP at, Out out) {
submit(in, std::move(at), std::move(out));
}
};
struct passDNF {
PUSHMI_TEMPLATE(class Data)
(requires TimeExecutor<Data>)
auto operator()(Data& in) const noexcept {
return ::folly::pushmi::now(in);
}
};
struct passDZF {
PUSHMI_TEMPLATE(class Data)
(requires ConstrainedExecutor<Data>)
auto operator()(Data& in) const noexcept {
return ::folly::pushmi::top(in);
}
};
// inspired by Ovrld - shown in a presentation by Nicolai Josuttis
#if __cpp_variadic_using >= 201611 && __cpp_concepts
template <PUSHMI_TYPE_CONSTRAINT(SemiMovable)... Fns>
requires sizeof...(Fns) > 0
struct overload_fn : Fns... {
constexpr overload_fn() = default;
constexpr explicit overload_fn(Fns... fns) requires sizeof...(Fns) == 1
: Fns(std::move(fns))... {}
constexpr overload_fn(Fns... fns) requires sizeof...(Fns) > 1
: Fns(std::move(fns))... {}
using Fns::operator()...;
};
#else
template <PUSHMI_TYPE_CONSTRAINT(SemiMovable)... Fns>
#if __cpp_concepts
requires sizeof...(Fns) > 0
#endif
struct overload_fn;
template <class Fn>
struct overload_fn<Fn> : Fn {
constexpr overload_fn() = default;
constexpr explicit overload_fn(Fn fn)
: Fn(std::move(fn)) {}
using Fn::operator();
};
#if !defined(__GNUC__) || __GNUC__ >= 8
template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> : Fn, overload_fn<Fns...> {
constexpr overload_fn() = default;
constexpr overload_fn(Fn fn, Fns... fns)
: Fn(std::move(fn)), overload_fn<Fns...>{std::move(fns)...} {}
using Fn::operator();
using overload_fn<Fns...>::operator();
};
#else
template <class Fn, class... Fns>
struct overload_fn<Fn, Fns...> {
private:
std::pair<Fn, overload_fn<Fns...>> fns_;
template <bool B>
using _which_t = std::conditional_t<B, Fn, overload_fn<Fns...>>;
public:
constexpr overload_fn() = default;
constexpr overload_fn(Fn fn, Fns... fns)
: fns_{std::move(fn), overload_fn<Fns...>{std::move(fns)...}} {}
PUSHMI_TEMPLATE (class... Args)
(requires lazy::Invocable<Fn&, Args...> ||
lazy::Invocable<overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) PUSHMI_NOEXCEPT_AUTO(
std::declval<_which_t<Invocable<Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<Fn&, Args...>>(fns_)((Args &&) args...);
}
PUSHMI_TEMPLATE (class... Args)
(requires lazy::Invocable<const Fn&, Args...> ||
lazy::Invocable<const overload_fn<Fns...>&, Args...>)
decltype(auto) operator()(Args &&... args) const PUSHMI_NOEXCEPT_AUTO(
std::declval<const _which_t<Invocable<const Fn&, Args...>>&>()(std::declval<Args>()...)) {
return std::get<!Invocable<const Fn&, Args...>>(fns_)((Args &&) args...);
}
};
#endif
#endif
template <class... Fns>
auto overload(Fns... fns) -> overload_fn<Fns...> {
return overload_fn<Fns...>{std::move(fns)...};
}
template <class... Fns>
struct on_value_fn : overload_fn<Fns...> {
constexpr on_value_fn() = default;
......@@ -291,60 +130,5 @@ auto on_starting(Fns... fns) -> on_starting_fn<Fns...> {
return on_starting_fn<Fns...>{std::move(fns)...};
}
template <class Fn>
struct on_executor_fn : overload_fn<Fn> {
constexpr on_executor_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_executor(Fn fn) -> on_executor_fn<Fn> {
return on_executor_fn<Fn>{std::move(fn)};
}
template <class Fn>
struct on_make_strand_fn : overload_fn<Fn> {
constexpr on_make_strand_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_make_strand(Fn fn) -> on_make_strand_fn<Fn> {
return on_make_strand_fn<Fn>{std::move(fn)};
}
template <class... Fns>
struct on_submit_fn : overload_fn<Fns...> {
constexpr on_submit_fn() = default;
using overload_fn<Fns...>::overload_fn;
};
template <class... Fns>
auto on_submit(Fns... fns) -> on_submit_fn<Fns...> {
return on_submit_fn<Fns...>{std::move(fns)...};
}
template <class... Fns>
struct on_schedule_fn : overload_fn<Fns...> {
constexpr on_schedule_fn() = default;
using overload_fn<Fns...>::overload_fn;
};
template <class... Fns>
auto on_schedule(Fns... fns) -> on_schedule_fn<Fns...> {
return on_schedule_fn<Fns...>{std::move(fns)...};
}
template <class Fn>
struct on_now_fn : overload_fn<Fn> {
constexpr on_now_fn() = default;
using overload_fn<Fn>::overload_fn;
};
template <class Fn>
auto on_now(Fn fn) -> on_now_fn<Fn> {
return on_now_fn<Fn>{std::move(fn)};
}
} // namespace pushmi
} // namespace folly
......@@ -15,17 +15,17 @@
*/
#pragma once
#include <folly/experimental/pushmi/boosters.h>
#include <folly/experimental/pushmi/concepts.h>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/extension_points.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/properties.h>
#include <folly/experimental/pushmi/traits.h>
#include <future>
#include <type_traits>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/functional.h>
#include <folly/experimental/pushmi/receiver/primitives.h>
#include <folly/experimental/pushmi/receiver/tags.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
namespace folly {
namespace pushmi {
......@@ -522,6 +522,7 @@ std::future<T> future_from(In&& in) {
submit((In&&)in, std::move(p));
return result;
}
PUSHMI_TEMPLATE (class In)
(requires SenderTo<In, std::promise<void>> && SingleSender<In>)
std::future<void> future_from(In&& in) {
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
namespace folly {
namespace pushmi {
struct receiver_tag {
};
struct flow_receiver_tag : receiver_tag {
};
} // namespace pushmi
} // namespace folly
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/experimental/pushmi/awaitable/senders.h>
#include <folly/experimental/pushmi/sender/detail/concepts.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
namespace folly {
namespace pushmi {
// add concepts to support senders
//
PUSHMI_CONCEPT_DEF(
template(class S, class R) //
(concept SenderTo)(S, R), //
requires(S&& s, R&& r) ( //
pushmi::submit((S &&) s, (R &&) r) //
) &&
Sender<S> && Receiver<R>
);
// add concepts to support cancellation and rate control
//
PUSHMI_CONCEPT_DEF(
template(class S) //
(concept FlowSender)(S), //
Sender<S>&&
DerivedFrom<sender_category_t<S>, flow_sender_tag>
);
PUSHMI_CONCEPT_DEF(
template(class S, class R) //
(concept FlowSenderTo)(S, R), //
FlowSender<S> && //
SenderTo<S, R>&& //
FlowReceiver<R>
);
} // namespace pushmi
} // namespace folly
......@@ -20,6 +20,7 @@
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/sender/tags.h>
#include <folly/experimental/pushmi/traits.h>
namespace folly {
......
......@@ -15,11 +15,15 @@
*/
#pragma once
#include <folly/experimental/pushmi/flow_receiver.h>
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <type_traits>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/flow_receiver.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/functional.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/tags.h>
namespace folly {
namespace pushmi {
......
......@@ -15,12 +15,16 @@
*/
#pragma once
#include <folly/experimental/pushmi/flow_receiver.h>
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <tuple>
#include <type_traits>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/flow_receiver.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/functional.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/tags.h>
namespace folly {
namespace pushmi {
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <exception>
#include <utility>
#include <folly/experimental/pushmi/forwards.h>
#include <folly/experimental/pushmi/detail/functional.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/primitives.h>
namespace folly {
namespace pushmi {
struct ignoreSF {
void operator()(detail::any) {}
void operator()(detail::any, detail::any) {}
};
struct passDSF {
PUSHMI_TEMPLATE(class Data, class Out)
(requires SenderTo<Data&, Out>) //
void operator()(Data& in, Out out) {
submit(in, std::move(out));
}
// TODO Constrain me, please!
template <class Data, class TP, class Out>
void operator()(Data& in, TP at, Out out) {
submit(in, std::move(at), std::move(out));
}
};
template <class... Fns>
struct on_submit_fn : overload_fn<Fns...> {
constexpr on_submit_fn() = default;
using overload_fn<Fns...>::overload_fn;
};
template <class... Fns>
auto on_submit(Fns... fns) -> on_submit_fn<Fns...> {
return on_submit_fn<Fns...>{std::move(fns)...};
}
} // namespace pushmi
} // namespace folly
......@@ -15,11 +15,15 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <type_traits>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/functional.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/tags.h>
namespace folly {
namespace pushmi {
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <exception>
#include <type_traits>
#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/awaitable/concepts.h>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/if_constexpr.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/sender/detail/concepts.h>
#include <folly/lang/CustomizationPoint.h>
namespace folly {
namespace pushmi {
namespace _submit_adl {
template <class S, class R>
void submit(S&&, R&&) = delete;
template <class T>
constexpr typename T::value_type const _v = T::value;
PUSHMI_CONCEPT_DEF(
template(class S, class R)
concept HasMemberSubmit_,
requires (S&& from, R&& to) (
((S&&) from).submit((R&&) to),
// requires_<noexcept(((S&&) from).submit((R&&) to))>,
requires_<std::is_void<decltype(((S&&) from).submit((R&&) to))>::value>
)
);
PUSHMI_CONCEPT_DEF(
template(class S, class R)
concept HasNonMemberSubmit_,
requires (S&& from, R&& to) (
submit((S&&) from, (R&&) to),
// requires_<noexcept(submit((S&&) from, (R&&) to))>,
requires_<std::is_void<decltype(submit((S&&) from, (R&&) to))>::value>
)
);
#if defined(__cpp_coroutines)
PUSHMI_CONCEPT_DEF(
template (class A, class R)
concept IsSubmittableAwaitable_,
not detail::SenderLike_<A> && Awaitable<A> &&
ReceiveError<R, std::exception_ptr> &&
ReceiveValue<R, coro::await_result_t<A>>
);
#endif
struct _fn
{
private:
#if defined(__cpp_coroutines)
template<class A, class R>
static void _submit_awaitable_(A awaitable, R to) noexcept;
#endif
struct _impl_ {
PUSHMI_TEMPLATE(class S, class R)
(requires Sender<S> && Receiver<R>)
auto operator()(S&& from, R&& to) const
{
// Prefer a .submit() member if it exists:
PUSHMI_IF_CONSTEXPR_RETURN((HasMemberSubmit_<S, R>) (
id((S&&) from).submit((R&&) to);
return std::true_type{};
) else (
// Otherwise, dispatch to a submit() free function if it exists:
PUSHMI_IF_CONSTEXPR_RETURN((HasNonMemberSubmit_<S, R>) (
submit(id((S&&) from), (R&&) to);
return std::true_type{};
) else (
#if defined(__cpp_coroutines)
// Otherwise, if we support coroutines and S looks like an
// awaitable, dispatch to the
PUSHMI_IF_CONSTEXPR_RETURN((IsSubmittableAwaitable_<S, R>) (
_submit_awaitable_(id((S&&) from), (R&&) to);
return std::true_type{};
) else (
return std::false_type{};
))
#else
return std::false_type{};
#endif
))
))
}
};
public:
PUSHMI_TEMPLATE(class S, class R)
(requires Invocable<_impl_, S, R> && invoke_result_t<_impl_, S, R>::value)
constexpr void operator()(S&& from, R&& to) const {
(void) _impl_{}((S&&) from, (R&&) to);
}
};
#if defined(__cpp_coroutines)
struct FOLLY_MAYBE_UNUSED oneway_task
{
struct promise_type
{
oneway_task get_return_object() noexcept { return {}; }
std::experimental::suspend_never initial_suspend() noexcept { return {}; }
std::experimental::suspend_never final_suspend() noexcept { return {}; }
void return_void() noexcept {}
[[noreturn]] void unhandled_exception() noexcept { std::terminate(); }
};
};
#endif
#if defined(__cpp_coroutines)
// Make all awaitables senders:
template<class A, class R>
void _fn::_submit_awaitable_(A awaitable, R to) noexcept
{
// TRICKY: We want to make sure that if copying/moving 'awaitable' throws
// or if allocating the coroutine frame throws that we can still call
// op::set_error() on the receiver. So we pass the receiver by reference
// so that if the call to std::invoke() throws that we can catch the
// exception and pass it into 'receiver'.
#if FOLLY_HAS_EXCEPTIONS
try
{
#endif
// Create a lambda coroutine and immediately invoke it:
[](A a, R&& r) -> oneway_task
{
// Receivers should be nothrow move-constructible so we should't need to
// worry about this potentially throwing.
R rCopy(static_cast<R&&>(r));
#if FOLLY_HAS_EXCEPTIONS
try
{
#endif
PUSHMI_IF_CONSTEXPR ((std::is_void<coro::await_result_t<A>>::value) (
co_await static_cast<A&&>(a);
set_value(id(rCopy));
) else (
set_value(id(rCopy), co_await static_cast<A&&>(a));
))
set_done(rCopy);
#if FOLLY_HAS_EXCEPTIONS
}
catch (...)
{
set_error(rCopy, std::current_exception());
}
#endif
}(static_cast<A&&>(awaitable), static_cast<R&&>(to));
#if FOLLY_HAS_EXCEPTIONS
}
catch (...)
{
set_error(to, std::current_exception());
}
#endif
}
#endif
} // namespace _submit_adl
FOLLY_DEFINE_CPO(_submit_adl::_fn, submit)
} // namespace pushmi
} // namespace folly
......@@ -15,72 +15,15 @@
*/
#pragma once
#include <folly/experimental/pushmi/detail/sender_base.h>
#include <folly/experimental/pushmi/properties.h>
namespace folly {
namespace pushmi {
namespace detail {
// inherit: a class that inherits from a bunch of bases
template <class... Ts>
struct inherit : Ts... {
inherit() = default;
constexpr inherit(Ts... ts)
: Ts((Ts&&) ts)...
{}
};
template <class T>
struct inherit<T> : T {
inherit() = default;
explicit constexpr inherit(T t)
: T((T&&) t)
{}
};
template <>
struct inherit<>
{};
} // namespace detail
// derive from this for types that need to find operator|() overloads by ADL
struct pipeorigin {};
// traits & tags
struct sender_tag
: sender_base<sender_tag> {
};
namespace detail {
struct virtual_sender_tag
: virtual sender_tag {
};
} // namespace detail
struct single_sender_tag
: sender_base<single_sender_tag, detail::virtual_sender_tag> {
};
struct flow_sender_tag
: sender_base<flow_sender_tag, detail::virtual_sender_tag> {
};
struct flow_single_sender_tag
: sender_base<
flow_single_sender_tag,
detail::inherit<flow_sender_tag, single_sender_tag>> {
};
struct receiver_tag {
};
struct flow_receiver_tag : receiver_tag {
};
// blocking affects senders
struct blocking_category {};
// sequence affects senders
struct sequence_category {};
// trait & tag types
template <class... TN>
......@@ -89,6 +32,11 @@ template <>
struct is_always_blocking<> {
using property_category = blocking_category;
};
template <class PS>
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;
template <class... TN>
struct is_never_blocking;
......@@ -96,6 +44,11 @@ template <>
struct is_never_blocking<> {
using property_category = blocking_category;
};
template <class PS>
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;
template <class... TN>
struct is_maybe_blocking;
......@@ -103,20 +56,11 @@ template <>
struct is_maybe_blocking<> {
using property_category = blocking_category;
};
template <class... TN>
struct is_fifo_sequence;
template <>
struct is_fifo_sequence<> {
using property_category = sequence_category;
};
template <class... TN>
struct is_concurrent_sequence;
template <>
struct is_concurrent_sequence<> {
using property_category = sequence_category;
};
template <class PS>
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;
} // namespace pushmi
} // namespace folly
......@@ -15,11 +15,15 @@
*/
#pragma once
#include <folly/experimental/pushmi/executor.h>
#include <folly/experimental/pushmi/receiver.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <type_traits>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/receiver/receiver.h>
#include <folly/experimental/pushmi/sender/concepts.h>
#include <folly/experimental/pushmi/sender/functional.h>
#include <folly/experimental/pushmi/sender/primitives.h>
#include <folly/experimental/pushmi/sender/tags.h>
namespace folly {
namespace pushmi {
......
......@@ -19,6 +19,27 @@
namespace folly {
namespace pushmi {
namespace detail {
// inherit: a class that inherits from a bunch of bases
template <class... Ts>
struct inherit : Ts... {
inherit() = default;
constexpr inherit(Ts... ts)
: Ts((Ts&&) ts)...
{}
};
template <class T>
struct inherit<T> : T {
inherit() = default;
explicit constexpr inherit(T t)
: T((T&&) t)
{}
};
template <>
struct inherit<>
{};
} // namespace detail
namespace awaitable_senders {
struct sender_adl_hook {
};
......@@ -176,5 +197,30 @@ struct sender_base : BaseCategory {
using or_ = _or_<with_values, MoreValues...>;
};
};
// traits & tags
struct sender_tag
: sender_base<sender_tag> {
};
namespace detail {
struct virtual_sender_tag
: virtual sender_tag {
};
} // namespace detail
struct single_sender_tag
: sender_base<single_sender_tag, detail::virtual_sender_tag> {
};
struct flow_sender_tag
: sender_base<flow_sender_tag, detail::virtual_sender_tag> {
};
struct flow_single_sender_tag
: sender_base<
flow_single_sender_tag,
detail::inherit<flow_sender_tag, single_sender_tag>> {
};
} // namespace pushmi
} // namespace folly
......@@ -15,10 +15,14 @@
*/
#pragma once
#include <exception>
#include <memory>
#include <mutex>
#include <vector>
#include <folly/experimental/pushmi/concepts.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/receiver/concepts.h>
#include <folly/experimental/pushmi/traits.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
#include <folly/experimental/pushmi/detail/opt.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/o/empty.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/from.h>
......
......@@ -18,7 +18,7 @@
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/experimental/coro/detail/InlineTask.h>
#include <folly/experimental/pushmi/single_sender.h>
#include <folly/experimental/pushmi/sender/single_sender.h>
#include <folly/portability/GMock.h>
#include <folly/portability/GTest.h>
......
......@@ -21,15 +21,16 @@
#include <chrono>
using namespace std::literals;
#include <folly/experimental/pushmi/flow_many_sender.h>
#include <folly/experimental/pushmi/sender/flow_many_sender.h>
#include <folly/experimental/pushmi/o/for_each.h>
#include <folly/experimental/pushmi/o/from.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/schedule.h>
#include <folly/experimental/pushmi/entangle.h>
#include <folly/experimental/pushmi/new_thread.h>
#include <folly/experimental/pushmi/time_source.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/new_thread.h>
#include <folly/experimental/pushmi/executor/time_source.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
using namespace folly::pushmi::aliases;
......
......@@ -19,13 +19,14 @@
#include <chrono>
using namespace std::literals;
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/schedule.h>
#include <folly/experimental/pushmi/entangle.h>
#include <folly/experimental/pushmi/new_thread.h>
#include <folly/experimental/pushmi/time_source.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/new_thread.h>
#include <folly/experimental/pushmi/executor/time_source.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
#include <folly/functional/Invoke.h>
using namespace folly::pushmi::aliases;
......
......@@ -19,19 +19,20 @@
#include <chrono>
using namespace std::literals;
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/o/empty.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/just.h>
#include <folly/experimental/pushmi/o/on.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/schedule.h>
#include <folly/experimental/pushmi/o/tap.h>
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/new_thread.h>
#include <folly/experimental/pushmi/strand.h>
#include <folly/experimental/pushmi/time_source.h>
#include <folly/experimental/pushmi/executor/new_thread.h>
#include <folly/experimental/pushmi/executor/strand.h>
#include <folly/experimental/pushmi/executor/time_source.h>
using namespace folly::pushmi::aliases;
......
......@@ -19,7 +19,7 @@
#include <chrono>
using namespace std::literals;
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/o/empty.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/from.h>
......
......@@ -19,18 +19,19 @@
#include <chrono>
using namespace std::literals;
#include <folly/experimental/pushmi/flow_single_sender.h>
#include <folly/experimental/pushmi/sender/flow_single_sender.h>
#include <folly/experimental/pushmi/o/empty.h>
#include <folly/experimental/pushmi/o/extension_operators.h>
#include <folly/experimental/pushmi/o/just.h>
#include <folly/experimental/pushmi/o/on.h>
#include <folly/experimental/pushmi/o/schedule.h>
#include <folly/experimental/pushmi/o/submit.h>
#include <folly/experimental/pushmi/o/tap.h>
#include <folly/experimental/pushmi/o/transform.h>
#include <folly/experimental/pushmi/o/via.h>
#include <folly/experimental/pushmi/inline.h>
#include <folly/experimental/pushmi/trampoline.h>
#include <folly/experimental/pushmi/executor/inline.h>
#include <folly/experimental/pushmi/executor/trampoline.h>
using namespace folly::pushmi::aliases;
......
......@@ -16,9 +16,10 @@
#pragma once
#include <type_traits>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/experimental/pushmi/detail/concept_def.h>
#include <folly/experimental/pushmi/detail/traits.h>
#include <folly/experimental/pushmi/detail/functional.h>
#define PUSHMI_NOEXCEPT_AUTO(...) \
......@@ -111,35 +112,12 @@ PUSHMI_CONCEPT_DEF(
or_v<Bs...>
);
PUSHMI_CONCEPT_DEF(
template (class T)
concept Object,
requires (T* p) (
*p,
implicitly_convertible_to<const volatile void*>(p)
)
);
PUSHMI_CONCEPT_DEF(
template (class T, class... Args)
(concept Constructible)(T, Args...),
PUSHMI_PP_IS_CONSTRUCTIBLE(T, Args...)
);
PUSHMI_CONCEPT_DEF(
template (class T)
concept MoveConstructible,
Constructible<T, T>
);
PUSHMI_CONCEPT_DEF(
template (class From, class To)
concept ConvertibleTo,
requires (From (&f)()) (
static_cast<To>(f())
) && std::is_convertible<From, To>::value
);
PUSHMI_CONCEPT_DEF(
template (class A, class B)
concept DerivedFrom,
......@@ -171,12 +149,6 @@ PUSHMI_CONCEPT_DEF(
)
);
PUSHMI_CONCEPT_DEF(
template (class T)
concept SemiMovable,
Object<T> && Constructible<T, T> && ConvertibleTo<T, T>
);
PUSHMI_CONCEPT_DEF(
template (class T)
concept Movable,
......
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