Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
folly
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
folly
Commits
a855776b
Commit
a855776b
authored
Oct 16, 2018
by
Kirk Shoop
Committed by
Facebook Github Bot
Oct 17, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add new operators to single header (#18)
fbshipit-source-id: 1df9cc44331327b62fb7e20f22f8f512fe4e6ecd
parent
3e05ecc2
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
644 additions
and
391 deletions
+644
-391
folly/experimental/pushmi/buildSingleHeader.cmake
folly/experimental/pushmi/buildSingleHeader.cmake
+8
-4
folly/experimental/pushmi/include/pushmi-single-header.h
folly/experimental/pushmi/include/pushmi-single-header.h
+1
-0
folly/experimental/pushmi/include/pushmi.h
folly/experimental/pushmi/include/pushmi.h
+633
-387
folly/experimental/pushmi/include/pushmi/subject.h
folly/experimental/pushmi/include/pushmi/subject.h
+2
-0
No files found.
folly/experimental/pushmi/buildSingleHeader.cmake
View file @
a855776b
...
...
@@ -18,7 +18,7 @@ function(BuildSingleHeader HeaderName)
file
(
WRITE
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/
${
HeaderName
}
.h
"
${
incls
}
"
)
endfunction
()
set
(
header_files
set
(
header_files
# keep in inclusion order
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/external/meta/include/meta/meta_fwd.hpp"
...
...
@@ -45,14 +45,18 @@ set(header_files
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/flow_single_deferred.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/trampoline.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/new_thread.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/empty.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/extension_operators.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/submit.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/subject.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/empty.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/just.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/defer.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/on.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/submit.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/tap.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/transform.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/via.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/request_via.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/share.h"
)
BuildSingleHeader
(
"pushmi"
${
header_files
}
)
\ No newline at end of file
BuildSingleHeader
(
"pushmi"
${
header_files
}
)
folly/experimental/pushmi/include/pushmi-single-header.h
View file @
a855776b
...
...
@@ -24,6 +24,7 @@
#include <future>
#include <tuple>
#include <deque>
#include <vector>
#if __cpp_lib_optional >= 201606
#include <optional>
...
...
folly/experimental/pushmi/include/pushmi.h
View file @
a855776b
...
...
@@ -24,6 +24,7 @@
#include <future>
#include <tuple>
#include <deque>
#include <vector>
#if __cpp_lib_optional >= 201606
#include <optional>
...
...
@@ -8311,43 +8312,6 @@ inline auto new_thread() {
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include <meta/meta.hpp>
//#include "../deferred.h"
//#include "../single_deferred.h"
//#include "../detail/functional.h"
namespace
pushmi
{
namespace
operators
{
template
<
class
V
>
auto
empty
()
{
return
make_single_deferred
(
constrain
(
lazy
::
SingleReceiver
<
_1
,
V
>
,
[](
auto
out
)
mutable
{
::
pushmi
::
set_done
(
out
);
})
);
}
inline
auto
empty
()
{
return
make_deferred
(
constrain
(
lazy
::
NoneReceiver
<
_1
>
,
[](
auto
out
)
mutable
{
::
pushmi
::
set_done
(
out
);
})
);
}
}
// namespace operators
}
// namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include <tuple>
//#include "../piping.h"
//#include "../boosters.h"
...
...
@@ -8624,83 +8588,487 @@ PUSHMI_INLINE_VAR constexpr detail::now_fn top{};
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../single_deferred.h"
//#include "submit.h"
//#include "extension_operators.h"
namespace
pushmi
{
namespace
operators
{
PUSHMI_TEMPLATE
(
class
V
)
(
requires
SemiMovable
<
V
>
)
auto
just
(
V
v
)
{
return
make_single_deferred
(
constrain
(
lazy
::
SingleReceiver
<
_1
,
V
>
,
[
v
=
std
::
move
(
v
)](
auto
out
)
mutable
{
::
pushmi
::
set_value
(
out
,
std
::
move
(
v
));
}
)
);
}
}
// namespace operators
}
// namespace pushmi
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../piping.h"
//#include "../executor.h"
//#include <functional>
//#include "../time_single_deferred.h"
//#include "../boosters.h"
//#include "extension_operators.h"
//#include "../trampoline.h"
//#include "../detail/opt.h"
//#include "../detail/if_constexpr.h"
namespace pushmi {
namespace detail {
namespace submit_detail {
template <PUSHMI_TYPE_CONSTRAINT(Sender) In, class ...AN>
using receiver_type_t =
pushmi::invoke_result_t<
pushmi::detail::make_receiver<property_set_index_t<properties_t<In>, is_silent<>>>,
AN...>;
struct
on_fn
{
PUSHMI_TEMPLATE
(
class
ExecutorFactory
)
(
requires
Invocable
<
ExecutorFactory
&>
)
auto
operator
()(
ExecutorFactory
ef
)
const
{
return
constrain
(
lazy
::
Sender
<
_1
>
,
[
ef
=
std
::
move
(
ef
)](
auto
in
)
{
using
In
=
decltype
(
in
);
return
::
pushmi
::
detail
::
deferred_from
<
In
,
single
<>>
(
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
constrain
(
lazy
::
SenderTo
<
In
,
_2
>
,
[
ef
](
In
&
in
,
auto
out
)
{
auto
exec
=
ef
();
::
pushmi
::
submit
(
exec
,
::
pushmi
::
now
(
exec
),
::
pushmi
::
make_single
([
in
=
in
,
out
=
std
::
move
(
out
)](
auto
)
mutable
{
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
})
);
}),
constrain
(
lazy
::
TimeSenderTo
<
In
,
_3
>
,
[
ef
](
In
&
in
,
auto
at
,
auto
out
)
{
auto
exec
=
ef
();
::
pushmi
::
submit
(
exec
,
at
,
::
pushmi
::
on_value
([
in
=
in
,
at
,
out
=
std
::
move
(
out
)](
auto
)
mutable
{
::
pushmi
::
submit
(
in
,
at
,
std
::
move
(
out
));
})
);
})
)
);
});
PUSHMI_CONCEPT_DEF(
template (class In, class ... AN)
(concept AutoSenderTo)(In, AN...),
SenderTo<In, receiver_type_t<In, AN...>>
);
PUSHMI_CONCEPT_DEF(
template (class In, class ... AN)
(concept AutoTimeSenderTo)(In, AN...),
TimeSenderTo<In, receiver_type_t<In, AN...>>
);
} // namespace submit_detail
struct submit_fn {
private:
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
template <class... AN>
struct fn {
std::tuple<AN...> args_;
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoSenderTo<In, AN...>)
In operator()(In in) {
auto out{::pushmi::detail::out_from_fn<In>()(std::move(args_))};
::pushmi::submit(in, std::move(out));
return in;
}
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoTimeSenderTo<In, AN...>)
In operator()(In in) {
auto out{::pushmi::detail::out_from_fn<In>()(std::move(args_))};
::pushmi::submit(in, ::pushmi::now(in), std::move(out));
return in;
}
};
public:
template <class... AN>
auto operator()(AN&&... an) const {
return submit_fn::fn<AN...>{{(AN&&) an...}};
}
};
}
// namespace detail
struct submit_at_fn {
private:
template <class TP, class...AN>
struct fn {
TP at_;
std::tuple<AN...> args_;
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoTimeSenderTo<In, AN...>)
In operator()(In in) {
auto out{::pushmi::detail::out_from_fn<In>()(std::move(args_))};
::pushmi::submit(in, std::move(at_), std::move(out));
return in;
}
};
public:
PUSHMI_TEMPLATE(class TP, class...AN)
(requires Regular<TP>)
auto operator()(TP at, AN... an) const {
return submit_at_fn::fn<TP, AN...>{std::move(at), {(AN&&) an...}};
}
};
namespace
operators
{
struct submit_after_fn {
private:
template <class D, class... AN>
struct fn {
D after_;
std::tuple<AN...> args_;
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoTimeSenderTo<In, AN...>)
In operator()(In in) {
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
auto out{::pushmi::detail::out_from_fn<In>()(std::move(args_))};
auto at = ::pushmi::now(in) + std::move(after_);
::pushmi::submit(in, std::move(at), std::move(out));
return in;
}
};
public:
PUSHMI_TEMPLATE(class D, class...AN)
(requires Regular<D>)
auto operator()(D after, AN... an) const {
return submit_after_fn::fn<D, AN...>{std::move(after), {(AN&&) an...}};
}
};
PUSHMI_INLINE_VAR
constexpr
detail
::
on_fn
on
{};
struct blocking_submit_fn {
private:
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
template <class... AN>
struct fn {
std::tuple<AN...> args_;
}
// namespace operators
template <bool IsTimeSender, class In>
In impl_(In in) {
bool done = false;
std::condition_variable signaled;
auto out{::pushmi::detail::out_from_fn<In>()(
std::move(args_),
on_value(constrain(pushmi::lazy::Receiver<_1, is_single<>>,
[&](auto out, auto&& v) {
using V = remove_cvref_t<decltype(v)>;
PUSHMI_IF_CONSTEXPR( ((bool)Time<V>) (
// to keep the blocking semantics, make sure that the
// nested submits block here to prevent a spurious
// completion signal
auto nest = ::pushmi::nested_trampoline();
::pushmi::submit(nest, ::pushmi::now(nest), std::move(out));
) else (
::pushmi::set_value(out, id((V&&) v));
))
done = true;
signaled.notify_all();
}
)),
on_error(constrain(pushmi::lazy::NoneReceiver<_1, _2>,
[&](auto out, auto e) noexcept {
::pushmi::set_error(out, std::move(e));
done = true;
signaled.notify_all();
}
)),
on_done(constrain(pushmi::lazy::Receiver<_1>,
[&](auto out){
::pushmi::set_done(out);
done = true;
signaled.notify_all();
}
))
)};
PUSHMI_IF_CONSTEXPR( (IsTimeSender) (
id(::pushmi::submit)(in, id(::pushmi::now)(in), std::move(out));
) else (
id(::pushmi::submit)(in, std::move(out));
))
std::mutex lock;
std::unique_lock<std::mutex> guard{lock};
signaled.wait(guard, [&]{
return done;
});
return in;
}
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoSenderTo<In, AN...>)
In operator()(In in) {
return this->impl_<false>(std::move(in));
}
PUSHMI_TEMPLATE(class In)
(requires submit_detail::AutoTimeSenderTo<In, AN...>)
In operator()(In in) {
return this->impl_<true>(std::move(in));
}
};
public:
template <class... AN>
auto operator()(AN... an) const {
return blocking_submit_fn::fn<AN...>{{(AN&&) an...}};
}
};
template <class T>
struct get_fn {
// TODO constrain this better
PUSHMI_TEMPLATE (class In)
(requires Sender<In>)
T operator()(In in) const {
pushmi::detail::opt<T> result_;
std::exception_ptr ep_;
auto out = make_single(
on_value([&](T t){ result_ = std::move(t); }),
on_error(
[&](auto e) noexcept { ep_ = std::make_exception_ptr(e); },
[&](std::exception_ptr ep) noexcept { ep_ = ep; })
);
using Out = decltype(out);
static_assert(SenderTo<In, Out, is_single<>> ||
TimeSenderTo<In, Out, is_single<>>,
"'In' does not deliver value compatible with 'T' to 'Out'");
blocking_submit_fn{}(std::move(out))(in);
if (!!ep_) { std::rethrow_exception(ep_); }
return std::move(*result_);
}
};
} // namespace detail
namespace operators {
PUSHMI_INLINE_VAR constexpr detail::submit_fn submit{};
PUSHMI_INLINE_VAR constexpr detail::submit_at_fn submit_at{};
PUSHMI_INLINE_VAR constexpr detail::submit_after_fn submit_after{};
PUSHMI_INLINE_VAR constexpr detail::blocking_submit_fn blocking_submit{};
template <class T>
PUSHMI_INLINE_VAR constexpr detail::get_fn<T> get{};
} // namespace operators
} // namespace pushmi
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include <vector>
//#include <pushmi/time_single_deferred.h>
namespace pushmi {
template<class... TN>
struct subject;
template<class T, class PS>
struct subject<T, PS> {
using properties = property_set_insert_t<property_set<is_sender<>, is_single<>>, PS>;
struct subject_shared {
bool done_ = false;
pushmi::detail::opt<T> t_;
std::exception_ptr ep_;
std::vector<any_single<T>> receivers_;
std::mutex lock_;
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void submit(Out out) {
std::unique_lock<std::mutex> guard(lock_);
if (ep_) {::pushmi::set_error(out, ep_); return;}
if (!!t_) {::pushmi::set_value(out, (const T&)t_); return;}
if (done_) {::pushmi::set_done(out); return;}
receivers_.push_back(any_single<T>{out});
}
PUSHMI_TEMPLATE(class V)
(requires SemiMovable<V>)
void value(V&& v) {
std::unique_lock<std::mutex> guard(lock_);
t_ = detail::as_const(v);
for (auto& out : receivers_) {::pushmi::set_value(out, (V&&) v);}
receivers_.clear();
}
PUSHMI_TEMPLATE(class E)
(requires SemiMovable<E>)
void error(E e) noexcept {
std::unique_lock<std::mutex> guard(lock_);
ep_ = e;
for (auto& out : receivers_) {::pushmi::set_error(out, std::move(e));}
receivers_.clear();
}
void done() {
std::unique_lock<std::mutex> guard(lock_);
done_ = true;
for (auto& out : receivers_) {::pushmi::set_done(out);}
receivers_.clear();
}
};
// need a template overload of none/deferred and the rest that stores a 'ptr' with its own lifetime management
struct subject_receiver {
using properties = property_set_insert_t<property_set<is_receiver<>, is_single<>>, PS>;
std::shared_ptr<subject_shared> s;
PUSHMI_TEMPLATE(class V)
(requires SemiMovable<V>)
void value(V&& v) {
s->value((V&&) v);
}
PUSHMI_TEMPLATE(class E)
(requires SemiMovable<E>)
void error(E e) noexcept {
s->error(std::move(e));
}
void done() {
s->done();
}
};
std::shared_ptr<subject_shared> s = std::make_shared<subject_shared>();
PUSHMI_TEMPLATE(class Out)
(requires Receiver<Out>)
void submit(Out out) {
s->submit(std::move(out));
}
auto receiver() {
return detail::out_from_fn<subject>{}(subject_receiver{s});
}
};
} // namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include <meta/meta.hpp>
//#include "../deferred.h"
//#include "../single_deferred.h"
//#include "../detail/functional.h"
namespace pushmi {
namespace operators {
template <class V>
auto empty() {
return make_single_deferred(
constrain(lazy::SingleReceiver<_1, V>, [](auto out) mutable {
::pushmi::set_done(out);
})
);
}
inline auto empty() {
return make_deferred(
constrain(lazy::NoneReceiver<_1>, [](auto out) mutable {
::pushmi::set_done(out);
})
);
}
} // namespace operators
} // namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../single_deferred.h"
//#include "submit.h"
//#include "extension_operators.h"
namespace pushmi {
namespace operators {
PUSHMI_TEMPLATE(class V)
(requires SemiMovable<V>)
auto just(V v) {
return make_single_deferred(
constrain(lazy::SingleReceiver<_1, V>,
[v = std::move(v)](auto out) mutable {
::pushmi::set_value(out, std::move(v));
}
)
);
}
} // namespace operators
} // namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../single.h"
//#include "submit.h"
//#include "extension_operators.h"
#if __cpp_deduction_guides >= 201703
#define MAKE(x) x MAKE_
#define MAKE_(...) {__VA_ARGS__}
#else
#define MAKE(x) make_ ## x
#endif
namespace pushmi {
namespace operators {
PUSHMI_TEMPLATE(class F)
(requires Invocable<F>)
auto defer(F f) {
return MAKE(single_deferred)(
constrain(lazy::Receiver<_1>,
[f = std::move(f)](auto out) mutable {
auto sender = f();
PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<decltype(sender)>) (
::pushmi::submit(sender, ::pushmi::now(id(sender)), std::move(out));
) else (
::pushmi::submit(sender, std::move(out));
));
}
)
);
}
} // namespace operators
} // namespace pushmi
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../piping.h"
//#include "../executor.h"
//#include "extension_operators.h"
namespace pushmi {
#if 0
namespace detail {
struct on_fn {
PUSHMI_TEMPLATE(class ExecutorFactory)
(requires Invocable<ExecutorFactory&>)
auto operator()(ExecutorFactory ef) const {
return constrain(lazy::Sender<_1>, [ef = std::move(ef)](auto in) {
using In = decltype(in);
return ::pushmi::detail::deferred_from<In, single<>>(
std::move(in),
::pushmi::detail::submit_transform_out<In>(
constrain(lazy::SenderTo<In, _2>, [ef](In& in, auto out) {
auto exec = ef();
::pushmi::submit(exec, ::pushmi::now(exec),
::pushmi::make_single([in = in, out = std::move(out)](auto) mutable {
::pushmi::submit(in, std::move(out));
})
);
}),
constrain(lazy::TimeSenderTo<In, _3>, [ef](In& in, auto at, auto out) {
auto exec = ef();
::pushmi::submit(exec, at,
::pushmi::on_value([in = in, at, out = std::move(out)](auto) mutable {
::pushmi::submit(in, at, std::move(out));
})
);
})
)
);
});
}
};
} // namespace detail
namespace operators {
PUSHMI_INLINE_VAR constexpr detail::on_fn on{};
} // namespace operators
#if 0
namespace detail {
template <class ExecutorFactory>
...
...
@@ -8776,303 +9144,75 @@ class fsdon {
stopped_(std::make_shared<std::atomic_bool>(false)),
out_(std::move(out)),
exec_(std::move(exec)),
upProxy_() {}
template <class T>
void value(T t) {
if (done_) {
return;
}
done_ = true;
out_.value(std::move(t));
}
template <class E>
void error(E e) {
if (done_) {
return;
}
done_ = true;
out_.error(std::move(e));
}
void stopping() {
if (done_) {
return;
}
done_ = true;
*stopped_ = true;
out_.stopping();
}
template <class Producer>
void starting(RefWrapper<Producer> up) {
upProxy_ =
producer_proxy<Producer>{std::move(up), stopped_, std::move(exec_)};
out_.starting(wrap_ref(upProxy_));
}
};
public:
start_on(executor_factory_type&& ef, in_type&& in)
: factory_(std::move(ef)), in_(std::move(in)) {}
template <class Out>
auto then(Out out) {
auto exec = factory_();
auto myout = out_on<Out, decltype(exec)>{std::move(out), exec};
exec | execute([in = in_, myout = std::move(myout)](auto) mutable {
in.then(std::move(myout));
});
}
};
public:
explicit fsdon(executor_factory_type&& ef) : factory_(std::move(ef)) {}
template <class In>
auto operator()(In in) {
return start_on<In>{std::move(factory_), std::move(in)};
}
};
} // namespace detail
namespace fsd {
template <class ExecutorFactory>
auto on(ExecutorFactory factory) {
return detail::fsdon<ExecutorFactory>{std::move(factory)};
}
} // namespace fsd
#endif
}
// namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include <functional>
//#include "../time_single_deferred.h"
//#include "../boosters.h"
//#include "extension_operators.h"
//#include "../trampoline.h"
//#include "../detail/opt.h"
//#include "../detail/if_constexpr.h"
namespace
pushmi
{
namespace
detail
{
namespace
submit_detail
{
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
)
In
,
class
...
AN
>
using
receiver_type_t
=
pushmi
::
invoke_result_t
<
pushmi
::
detail
::
make_receiver
<
property_set_index_t
<
properties_t
<
In
>
,
is_silent
<>>>
,
AN
...
>
;
PUSHMI_CONCEPT_DEF
(
template
(
class
In
,
class
...
AN
)
(
concept
AutoSenderTo
)(
In
,
AN
...),
SenderTo
<
In
,
receiver_type_t
<
In
,
AN
...>
>
);
PUSHMI_CONCEPT_DEF
(
template
(
class
In
,
class
...
AN
)
(
concept
AutoTimeSenderTo
)(
In
,
AN
...),
TimeSenderTo
<
In
,
receiver_type_t
<
In
,
AN
...>
>
);
}
// namespace submit_detail
struct
submit_fn
{
private:
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
template
<
class
...
AN
>
struct
fn
{
std
::
tuple
<
AN
...
>
args_
;
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
return
in
;
}
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoTimeSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
::
pushmi
::
now
(
in
),
std
::
move
(
out
));
return
in
;
}
};
public:
template
<
class
...
AN
>
auto
operator
()(
AN
&&
...
an
)
const
{
return
submit_fn
::
fn
<
AN
...
>
{{(
AN
&&
)
an
...}};
}
};
struct
submit_at_fn
{
private:
template
<
class
TP
,
class
...
AN
>
struct
fn
{
TP
at_
;
std
::
tuple
<
AN
...
>
args_
;
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoTimeSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
std
::
move
(
at_
),
std
::
move
(
out
));
return
in
;
}
};
public:
PUSHMI_TEMPLATE
(
class
TP
,
class
...
AN
)
(
requires
Regular
<
TP
>
)
auto
operator
()(
TP
at
,
AN
...
an
)
const
{
return
submit_at_fn
::
fn
<
TP
,
AN
...
>
{
std
::
move
(
at
),
{(
AN
&&
)
an
...}};
}
};
upProxy_() {}
struct
submit_after_fn
{
private:
template
<
class
D
,
class
...
AN
>
struct
fn
{
D
after_
;
std
::
tuple
<
AN
...
>
args_
;
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoTimeSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args_
))};
auto
at
=
::
pushmi
::
now
(
in
)
+
std
::
move
(
after_
);
::
pushmi
::
submit
(
in
,
std
::
move
(
at
),
std
::
move
(
out
));
return
in
;
}
};
public:
PUSHMI_TEMPLATE
(
class
D
,
class
...
AN
)
(
requires
Regular
<
D
>
)
auto
operator
()(
D
after
,
AN
...
an
)
const
{
return
submit_after_fn
::
fn
<
D
,
AN
...
>
{
std
::
move
(
after
),
{(
AN
&&
)
an
...}};
}
};
template <class T>
void value(T t) {
if (done_) {
return;
}
done_ = true;
out_.value(std::move(t));
}
struct
blocking_submit_fn
{
private:
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// times..
template
<
class
...
AN
>
struct
fn
{
std
::
tuple
<
AN
...
>
args_
;
template <class E>
void error(E e) {
if (done_) {
return;
}
done_ = true;
out_.error(std::move(e));
}
template
<
bool
IsTimeSender
,
class
In
>
In
impl_
(
In
in
)
{
bool
done
=
false
;
std
::
condition_variable
signaled
;
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args_
),
on_value
(
constrain
(
pushmi
::
lazy
::
Receiver
<
_1
,
is_single
<>>
,
[
&
](
auto
out
,
auto
&&
v
)
{
using
V
=
remove_cvref_t
<
decltype
(
v
)
>
;
PUSHMI_IF_CONSTEXPR
(
((
bool
)
Time
<
V
>
)
(
// to keep the blocking semantics, make sure that the
// nested submits block here to prevent a spurious
// completion signal
auto
nest
=
::
pushmi
::
nested_trampoline
();
::
pushmi
::
submit
(
nest
,
::
pushmi
::
now
(
nest
),
std
::
move
(
out
));
)
else
(
::
pushmi
::
set_value
(
out
,
id
((
V
&&
)
v
));
))
done
=
true
;
signaled
.
notify_all
();
}
)),
on_error
(
constrain
(
pushmi
::
lazy
::
NoneReceiver
<
_1
,
_2
>
,
[
&
](
auto
out
,
auto
e
)
noexcept
{
::
pushmi
::
set_error
(
out
,
std
::
move
(
e
));
done
=
true
;
signaled
.
notify_all
();
}
)),
on_done
(
constrain
(
pushmi
::
lazy
::
Receiver
<
_1
>
,
[
&
](
auto
out
){
::
pushmi
::
set_done
(
out
);
done
=
true
;
signaled
.
notify_all
();
}
))
)};
PUSHMI_IF_CONSTEXPR
(
(
IsTimeSender
)
(
id
(
::
pushmi
::
submit
)(
in
,
id
(
::
pushmi
::
now
)(
in
),
std
::
move
(
out
));
)
else
(
id
(
::
pushmi
::
submit
)(
in
,
std
::
move
(
out
));
))
std
::
mutex
lock
;
std
::
unique_lock
<
std
::
mutex
>
guard
{
lock
};
signaled
.
wait
(
guard
,
[
&
]{
return
done
;
});
return
in
;
}
void stopping() {
if (done_) {
return;
}
done_ = true;
*stopped_ = true;
out_.stopping();
}
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
return
this
->
impl_
<
false
>
(
std
::
move
(
in
));
}
PUSHMI_TEMPLATE
(
class
In
)
(
requires
submit_detail
::
AutoTimeSenderTo
<
In
,
AN
...
>
)
In
operator
()(
In
in
)
{
return
this
->
impl_
<
true
>
(
std
::
move
(
in
));
template <class Producer>
void starting(RefWrapper<Producer> up) {
upProxy_ =
producer_proxy<Producer>{std::move(up), stopped_, std::move(exec_)};
out_.starting(wrap_ref(upProxy_));
}
};
public:
start_on(executor_factory_type&& ef, in_type&& in)
: factory_(std::move(ef)), in_(std::move(in)) {}
template <class Out>
auto then(Out out) {
auto exec = factory_();
auto myout = out_on<Out, decltype(exec)>{std::move(out), exec};
exec | execute([in = in_, myout = std::move(myout)](auto) mutable {
in.then(std::move(myout));
});
}
};
public:
template
<
class
...
AN
>
auto
operator
()(
AN
...
an
)
const
{
return
blocking_submit_fn
::
fn
<
AN
...
>
{{(
AN
&&
)
an
...}};
}
};
template
<
class
T
>
struct
get_fn
{
// TODO constrain this better
PUSHMI_TEMPLATE
(
class
In
)
(
requires
Sender
<
In
>
)
T
operator
()(
In
in
)
const
{
pushmi
::
detail
::
opt
<
T
>
result_
;
std
::
exception_ptr
ep_
;
auto
out
=
make_single
(
on_value
([
&
](
T
t
){
result_
=
std
::
move
(
t
);
}),
on_error
(
[
&
](
auto
e
)
noexcept
{
ep_
=
std
::
make_exception_ptr
(
e
);
},
[
&
](
std
::
exception_ptr
ep
)
noexcept
{
ep_
=
ep
;
})
);
using
Out
=
decltype
(
out
);
static_assert
(
SenderTo
<
In
,
Out
,
is_single
<>>
||
TimeSenderTo
<
In
,
Out
,
is_single
<>>
,
"'In' does not deliver value compatible with 'T' to 'Out'"
);
blocking_submit_fn
{}(
std
::
move
(
out
))(
in
);
if
(
!!
ep_
)
{
std
::
rethrow_exception
(
ep_
);
}
return
std
::
move
(
*
result_
);
public:
explicit fsdon(executor_factory_type&& ef) : factory_(std::move(ef)) {}
template <class In>
auto operator()(In in) {
return start_on<In>{std::move(factory_), std::move(in)};
}
};
} // namespace detail
namespace
operators
{
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_fn
submit
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_at_fn
submit_at
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_after_fn
submit_after
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
blocking_submit_fn
blocking_submit
{};
template
<
class
T
>
PUSHMI_INLINE_VAR
constexpr
detail
::
get_fn
<
T
>
get
{};
}
// namespace operators
namespace fsd {
template <class ExecutorFactory>
auto on(ExecutorFactory factory) {
return detail::fsdon<ExecutorFactory>{std::move(factory)};
}
} // namespace fsd
#endif
} // namespace pushmi
// clang-format off
...
...
@@ -9507,6 +9647,112 @@ auto via(ExecutorFactory factory) {
} // namespace fsd
#endif
} // namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../single.h"
//#include "submit.h"
//#include "extension_operators.h"
//#include "via.h"
namespace pushmi {
namespace detail {
struct request_via_fn {
template<typename In>
struct semisender {
In in;
template<class... AN>
auto via(AN&&... an) {
return in | ::pushmi::operators::via((AN&&) an...);
}
};
auto operator()() const;
};
auto request_via_fn::operator()() const {
return constrain(lazy::Sender<_1>, [](auto in) {
using In = decltype(in);
return semisender<In>{in};
});
}
} // namespace detail
namespace operators {
PUSHMI_INLINE_VAR constexpr detail::request_via_fn request_via{};
} // namespace operators
PUSHMI_TEMPLATE(class To, class In)
(requires Same<To, is_sender<>> && Sender<_1>)
auto via_cast(In in) {
return in;
}
PUSHMI_TEMPLATE(class To, class In)
(requires Same<To, is_sender<>>)
auto via_cast(detail::request_via_fn::semisender<In> ss) {
return ss.in;
}
} // namespace pushmi
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
//#pragma once
// Copyright (c) 2018-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
//#include "../single.h"
//#include "submit.h"
//#include "extension_operators.h"
//#include "../subject.h"
namespace pushmi {
namespace detail {
template<class T>
struct share_fn {
auto operator()() const;
};
template<class T>
auto share_fn<T>::operator()() const {
return constrain(lazy::Sender<_1>, [](auto in) {
using In = decltype(in);
subject<T, properties_t<In>> sub;
PUSHMI_IF_CONSTEXPR( ((bool)TimeSender<In>) (
::pushmi::submit(in, ::pushmi::now(id(in)), sub.receiver());
) else (
::pushmi::submit(id(in), sub.receiver());
));
return sub;
});
}
} // namespace detail
namespace operators {
template<class T>
PUSHMI_INLINE_VAR constexpr detail::share_fn<T> share{};
} // namespace operators
} // namespace pushmi
#endif // PUSHMI_SINGLE_HEADER
folly/experimental/pushmi/include/pushmi/subject.h
View file @
a855776b
...
...
@@ -5,6 +5,8 @@
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
#include <vector>
#include <pushmi/time_single_deferred.h>
namespace
pushmi
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment