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)
...
@@ -18,7 +18,7 @@ function(BuildSingleHeader HeaderName)
file
(
WRITE
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/
${
HeaderName
}
.h
"
${
incls
}
"
)
file
(
WRITE
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/
${
HeaderName
}
.h
"
${
incls
}
"
)
endfunction
()
endfunction
()
set
(
header_files
set
(
header_files
# keep in inclusion order
# keep in inclusion order
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/external/meta/include/meta/meta_fwd.hpp"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/external/meta/include/meta/meta_fwd.hpp"
...
@@ -45,14 +45,18 @@ set(header_files
...
@@ -45,14 +45,18 @@ set(header_files
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/flow_single_deferred.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/flow_single_deferred.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/trampoline.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/trampoline.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/new_thread.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/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/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/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/tap.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/transform.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/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
}
)
BuildSingleHeader
(
"pushmi"
${
header_files
}
)
\ No newline at end of file
folly/experimental/pushmi/include/pushmi-single-header.h
View file @
a855776b
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <future>
#include <future>
#include <tuple>
#include <tuple>
#include <deque>
#include <deque>
#include <vector>
#if __cpp_lib_optional >= 201606
#if __cpp_lib_optional >= 201606
#include <optional>
#include <optional>
...
...
folly/experimental/pushmi/include/pushmi.h
View file @
a855776b
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <future>
#include <future>
#include <tuple>
#include <tuple>
#include <deque>
#include <deque>
#include <vector>
#if __cpp_lib_optional >= 201606
#if __cpp_lib_optional >= 201606
#include <optional>
#include <optional>
...
@@ -8311,43 +8312,6 @@ inline auto new_thread() {
...
@@ -8311,43 +8312,6 @@ inline auto new_thread() {
// This source code is licensed under the MIT license found in the
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
// 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 <tuple>
//#include "../piping.h"
//#include "../piping.h"
//#include "../boosters.h"
//#include "../boosters.h"
...
@@ -8624,83 +8588,487 @@ PUSHMI_INLINE_VAR constexpr detail::now_fn top{};
...
@@ -8624,83 +8588,487 @@ PUSHMI_INLINE_VAR constexpr detail::now_fn top{};
// This source code is licensed under the MIT license found in the
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
// LICENSE file in the root directory of this source tree.
//#include "../single_deferred.h"
//#include <functional>
//#include "submit.h"
//#include "../time_single_deferred.h"
//#include "extension_operators.h"
//#include "../boosters.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 "extension_operators.h"
//#include "extension_operators.h"
//#include "../trampoline.h"
//#include "../detail/opt.h"
//#include "../detail/if_constexpr.h"
namespace
pushmi
{
namespace
pushmi
{
namespace
detail
{
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_CONCEPT_DEF
(
PUSHMI_TEMPLATE
(
class
ExecutorFactory
)
template
(
class
In
,
class
...
AN
)
(
requires
Invocable
<
ExecutorFactory
&>
)
(
concept
AutoSenderTo
)(
In
,
AN
...),
auto
operator
()(
ExecutorFactory
ef
)
const
{
SenderTo
<
In
,
receiver_type_t
<
In
,
AN
...>
>
return
constrain
(
lazy
::
Sender
<
_1
>
,
[
ef
=
std
::
move
(
ef
)](
auto
in
)
{
);
using
In
=
decltype
(
in
);
PUSHMI_CONCEPT_DEF
(
return
::
pushmi
::
detail
::
deferred_from
<
In
,
single
<>>
(
template
(
class
In
,
class
...
AN
)
std
::
move
(
in
),
(
concept
AutoTimeSenderTo
)(
In
,
AN
...),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
TimeSenderTo
<
In
,
receiver_type_t
<
In
,
AN
...>
>
constrain
(
lazy
::
SenderTo
<
In
,
_2
>
,
[
ef
](
In
&
in
,
auto
out
)
{
);
auto
exec
=
ef
();
}
// namespace submit_detail
::
pushmi
::
submit
(
exec
,
::
pushmi
::
now
(
exec
),
::
pushmi
::
make_single
([
in
=
in
,
out
=
std
::
move
(
out
)](
auto
)
mutable
{
struct
submit_fn
{
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
private:
})
// TODO - only move, move-only types..
);
// if out can be copied, then submit can be called multiple
}),
// times..
constrain
(
lazy
::
TimeSenderTo
<
In
,
_3
>
,
[
ef
](
In
&
in
,
auto
at
,
auto
out
)
{
template
<
class
...
AN
>
auto
exec
=
ef
();
struct
fn
{
::
pushmi
::
submit
(
exec
,
at
,
std
::
tuple
<
AN
...
>
args_
;
::
pushmi
::
on_value
([
in
=
in
,
at
,
out
=
std
::
move
(
out
)](
auto
)
mutable
{
PUSHMI_TEMPLATE
(
class
In
)
::
pushmi
::
submit
(
in
,
at
,
std
::
move
(
out
));
(
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 {
namespace detail {
template <class ExecutorFactory>
template <class ExecutorFactory>
...
@@ -8776,303 +9144,75 @@ class fsdon {
...
@@ -8776,303 +9144,75 @@ class fsdon {
stopped_(std::make_shared<std::atomic_bool>(false)),
stopped_(std::make_shared<std::atomic_bool>(false)),
out_(std::move(out)),
out_(std::move(out)),
exec_(std::move(exec)),
exec_(std::move(exec)),
upProxy_() {}
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
...}};
}
};
struct
submit_after_fn
{
template <class T>
private:
void value(T t) {
template
<
class
D
,
class
...
AN
>
if (done_) {
struct
fn
{
return;
D
after_
;
}
std
::
tuple
<
AN
...
>
args_
;
done_ = true;
PUSHMI_TEMPLATE
(
class
In
)
out_.value(std::move(t));
(
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
...}};
}
};
struct
blocking_submit_fn
{
template <class E>
private:
void error(E e) {
// TODO - only move, move-only types..
if (done_) {
// if out can be copied, then submit can be called multiple
return;
// times..
}
template
<
class
...
AN
>
done_ = true;
struct
fn
{
out_.error(std::move(e));
std
::
tuple
<
AN
...
>
args_
;
}
template
<
bool
IsTimeSender
,
class
In
>
void stopping() {
In
impl_
(
In
in
)
{
if (done_) {
bool
done
=
false
;
return;
std
::
condition_variable
signaled
;
}
auto
out
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
done_ = true;
std
::
move
(
args_
),
*stopped_ = true;
on_value
(
constrain
(
pushmi
::
lazy
::
Receiver
<
_1
,
is_single
<>>
,
out_.stopping();
[
&
](
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
)
template <class Producer>
(
requires
submit_detail
::
AutoSenderTo
<
In
,
AN
...
>
)
void starting(RefWrapper<Producer> up) {
In
operator
()(
In
in
)
{
upProxy_ =
return
this
->
impl_
<
false
>
(
std
::
move
(
in
));
producer_proxy<Producer>{std::move(up), stopped_, std::move(exec_)};
}
out_.starting(wrap_ref(upProxy_));
PUSHMI_TEMPLATE
(
class
In
)
}
(
requires
submit_detail
::
AutoTimeSenderTo
<
In
,
AN
...
>
)
};
In
operator
()(
In
in
)
{
return
this
->
impl_
<
true
>
(
std
::
move
(
in
));
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
>
public:
struct
get_fn
{
explicit fsdon(executor_factory_type&& ef) : factory_(std::move(ef)) {}
// TODO constrain this better
PUSHMI_TEMPLATE
(
class
In
)
template <class In>
(
requires
Sender
<
In
>
)
auto operator()(In in) {
T
operator
()(
In
in
)
const
{
return start_on<In>{std::move(factory_), std::move(in)};
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 detail
namespace
operators
{
namespace fsd {
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_fn
submit
{};
template <class ExecutorFactory>
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_at_fn
submit_at
{};
auto on(ExecutorFactory factory) {
PUSHMI_INLINE_VAR
constexpr
detail
::
submit_after_fn
submit_after
{};
return detail::fsdon<ExecutorFactory>{std::move(factory)};
PUSHMI_INLINE_VAR
constexpr
detail
::
blocking_submit_fn
blocking_submit
{};
}
template
<
class
T
>
} // namespace fsd
PUSHMI_INLINE_VAR
constexpr
detail
::
get_fn
<
T
>
get
{};
#endif
}
// namespace operators
}
// namespace pushmi
}
// namespace pushmi
// clang-format off
// clang-format off
...
@@ -9507,6 +9647,112 @@ auto via(ExecutorFactory factory) {
...
@@ -9507,6 +9647,112 @@ auto via(ExecutorFactory factory) {
} // namespace fsd
} // namespace fsd
#endif
#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
}
// namespace pushmi
#endif // PUSHMI_SINGLE_HEADER
#endif // PUSHMI_SINGLE_HEADER
folly/experimental/pushmi/include/pushmi/subject.h
View file @
a855776b
...
@@ -5,6 +5,8 @@
...
@@ -5,6 +5,8 @@
// This source code is licensed under the MIT license found in the
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
// LICENSE file in the root directory of this source tree.
#include <vector>
#include <pushmi/time_single_deferred.h>
#include <pushmi/time_single_deferred.h>
namespace
pushmi
{
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