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
0f0583e4
Commit
0f0583e4
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 many, many_deferred and from
fbshipit-source-id: 71a8c1998a0688e268a2a9a33aa601931e93e8c6
parent
7b28fc97
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1624 additions
and
68 deletions
+1624
-68
folly/experimental/pushmi/buildSingleHeader.cmake
folly/experimental/pushmi/buildSingleHeader.cmake
+3
-0
folly/experimental/pushmi/include/pushmi.h
folly/experimental/pushmi/include/pushmi.h
+759
-34
folly/experimental/pushmi/include/pushmi/boosters.h
folly/experimental/pushmi/include/pushmi/boosters.h
+3
-0
folly/experimental/pushmi/include/pushmi/forwards.h
folly/experimental/pushmi/include/pushmi/forwards.h
+6
-0
folly/experimental/pushmi/include/pushmi/many.h
folly/experimental/pushmi/include/pushmi/many.h
+422
-0
folly/experimental/pushmi/include/pushmi/many_deferred.h
folly/experimental/pushmi/include/pushmi/many_deferred.h
+204
-0
folly/experimental/pushmi/include/pushmi/o/extension_operators.h
...xperimental/pushmi/include/pushmi/o/extension_operators.h
+43
-10
folly/experimental/pushmi/include/pushmi/o/from.h
folly/experimental/pushmi/include/pushmi/o/from.h
+46
-0
folly/experimental/pushmi/include/pushmi/o/transform.h
folly/experimental/pushmi/include/pushmi/o/transform.h
+35
-24
folly/experimental/pushmi/test/CompileTest.cpp
folly/experimental/pushmi/test/CompileTest.cpp
+70
-0
folly/experimental/pushmi/test/PushmiTest.cpp
folly/experimental/pushmi/test/PushmiTest.cpp
+33
-0
No files found.
folly/experimental/pushmi/buildSingleHeader.cmake
View file @
0f0583e4
...
@@ -41,12 +41,15 @@ set(header_files
...
@@ -41,12 +41,15 @@ set(header_files
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/executor.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/executor.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/flow_single.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/flow_single.h"
"
${
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/many.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/many_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/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/o/submit.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/subject.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/empty.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/from.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/error.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/error.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/defer.h"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/include/pushmi/o/defer.h"
...
...
folly/experimental/pushmi/include/pushmi.h
View file @
0f0583e4
...
@@ -1268,9 +1268,15 @@ class deferred;
...
@@ -1268,9 +1268,15 @@ class deferred;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
single
;
class
single
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
many
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
single_deferred
;
class
single_deferred
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
many_deferred
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
time_single_deferred
;
class
time_single_deferred
;
...
@@ -2378,6 +2384,9 @@ struct construct_deduced<none>;
...
@@ -2378,6 +2384,9 @@ struct construct_deduced<none>;
template
<
>
template
<
>
struct
construct_deduced
<
single
>
;
struct
construct_deduced
<
single
>
;
template
<
>
struct
construct_deduced
<
many
>
;
template
<
>
template
<
>
struct
construct_deduced
<
flow_single
>
;
struct
construct_deduced
<
flow_single
>
;
...
@@ -4889,6 +4898,632 @@ using any_flow_single_deferred = flow_single_deferred<V, PE, E>;
...
@@ -4889,6 +4898,632 @@ using any_flow_single_deferred = flow_single_deferred<V, PE, E>;
// 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 <future>
//#include "none.h"
namespace
pushmi
{
template
<
class
V
,
class
E
>
class
many
<
V
,
E
>
{
bool
done_
=
false
;
union
data
{
void
*
pobj_
=
nullptr
;
char
buffer_
[
sizeof
(
std
::
promise
<
int
>
)];
// can hold a std::promise in-situ
}
data_
{};
template
<
class
Wrapped
>
static
constexpr
bool
insitu
()
noexcept
{
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
std
::
is_nothrow_move_constructible
<
Wrapped
>::
value
;
}
struct
vtable
{
static
void
s_op
(
data
&
,
data
*
)
{}
static
void
s_done
(
data
&
)
{}
static
void
s_error
(
data
&
,
E
)
noexcept
{
std
::
terminate
();
}
static
void
s_rnext
(
data
&
,
V
&&
)
{}
static
void
s_lnext
(
data
&
,
V
&
)
{}
void
(
*
op_
)(
data
&
,
data
*
)
=
vtable
::
s_op
;
void
(
*
done_
)(
data
&
)
=
vtable
::
s_done
;
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
vtable
::
s_error
;
void
(
*
rnext_
)(
data
&
,
V
&&
)
=
vtable
::
s_rnext
;
void
(
*
lnext_
)(
data
&
,
V
&
)
=
vtable
::
s_lnext
;
};
static
constexpr
vtable
const
noop_
{};
vtable
const
*
vptr_
=
&
noop_
;
template
<
class
T
,
class
U
=
std
::
decay_t
<
T
>
>
using
wrapped_t
=
std
::
enable_if_t
<!
std
::
is_same
<
U
,
many
>::
value
,
U
>
;
template
<
class
Wrapped
>
static
void
check
()
{
static_assert
(
Invocable
<
decltype
(
::
pushmi
::
set_next
),
Wrapped
,
V
>
,
"Wrapped many must support nexts of type V"
);
static_assert
(
NothrowInvocable
<
decltype
(
::
pushmi
::
set_error
),
Wrapped
,
std
::
exception_ptr
>
,
"Wrapped many must support std::exception_ptr and be noexcept"
);
static_assert
(
NothrowInvocable
<
decltype
(
::
pushmi
::
set_error
),
Wrapped
,
E
>
,
"Wrapped many must support E and be noexcept"
);
}
template
<
class
Wrapped
>
many
(
Wrapped
obj
,
std
::
false_type
)
:
many
()
{
struct
s
{
static
void
op
(
data
&
src
,
data
*
dst
)
{
if
(
dst
)
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
static
void
done
(
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
}
static
void
error
(
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
std
::
move
(
e
));
}
static
void
rnext
(
data
&
src
,
V
&&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
(
V
&&
)
v
);
}
static
void
lnext
(
data
&
src
,
V
&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
v
);
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
done
,
s
::
error
,
s
::
rnext
,
s
::
lnext
};
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
template
<
class
Wrapped
>
many
(
Wrapped
obj
,
std
::
true_type
)
noexcept
:
many
()
{
struct
s
{
static
void
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
void
done
(
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
}
static
void
error
(
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
std
::
move
(
e
));
}
static
void
rnext
(
data
&
src
,
V
&&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
(
V
&&
)
v
);
}
static
void
lnext
(
data
&
src
,
V
&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
v
);
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
done
,
s
::
error
,
s
::
rnext
,
s
::
lnext
};
new
((
void
*
)
data_
.
buffer_
)
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
many
()
=
default
;
many
(
many
&&
that
)
noexcept
:
many
()
{
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
PUSHMI_TEMPLATE
(
class
Wrapped
)
(
requires
ManyReceiver
<
wrapped_t
<
Wrapped
>
,
V
,
E
>
)
explicit
many
(
Wrapped
obj
)
noexcept
(
insitu
<
Wrapped
>
())
:
many
{
std
::
move
(
obj
),
bool_
<
insitu
<
Wrapped
>
()
>
{}}
{
check
<
Wrapped
>
();
}
~
many
()
{
vptr_
->
op_
(
data_
,
nullptr
);
}
many
&
operator
=
(
many
&&
that
)
noexcept
{
this
->~
many
();
new
((
void
*
)
this
)
many
(
std
::
move
(
that
));
return
*
this
;
}
PUSHMI_TEMPLATE
(
class
T
)
(
requires
ConvertibleTo
<
T
&&
,
V
&&>
)
void
next
(
T
&&
t
)
{
if
(
!
done_
)
{
vptr_
->
rnext_
(
data_
,
(
T
&&
)
t
);
}
}
PUSHMI_TEMPLATE
(
class
T
)
(
requires
ConvertibleTo
<
T
&
,
V
&>
)
void
next
(
T
&
t
)
{
if
(
!
done_
)
{
vptr_
->
lnext_
(
data_
,
t
);
}
}
void
error
(
E
e
)
noexcept
{
if
(
!
done_
)
{
done_
=
true
;
vptr_
->
error_
(
data_
,
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
vptr_
->
done_
(
data_
);
}
}
};
// Class static definitions:
template
<
class
V
,
class
E
>
constexpr
typename
many
<
V
,
E
>::
vtable
const
many
<
V
,
E
>::
noop_
;
template
<
class
NF
,
class
EF
,
class
DF
>
#if __cpp_concepts
requires
Invocable
<
DF
&>
#endif
class
many
<
NF
,
EF
,
DF
>
{
bool
done_
=
false
;
NF
nf_
;
EF
ef_
;
DF
df_
;
static_assert
(
!
detail
::
is_v
<
NF
,
on_error_fn
>
,
"the first parameter is the next implementation, but on_error{} was passed"
);
static_assert
(
!
detail
::
is_v
<
EF
,
on_next_fn
>
,
"the second parameter is the error implementation, but on_next{} was passed"
);
static_assert
(
NothrowInvocable
<
EF
&
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
many
()
=
default
;
constexpr
explicit
many
(
NF
nf
)
:
many
(
std
::
move
(
nf
),
EF
{},
DF
{})
{}
constexpr
explicit
many
(
EF
ef
)
:
many
(
NF
{},
std
::
move
(
ef
),
DF
{})
{}
constexpr
explicit
many
(
DF
df
)
:
many
(
NF
{},
EF
{},
std
::
move
(
df
))
{}
constexpr
many
(
EF
ef
,
DF
df
)
:
done_
(
false
),
nf_
(),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
constexpr
many
(
NF
nf
,
EF
ef
,
DF
df
=
DF
{})
:
done_
(
false
),
nf_
(
std
::
move
(
nf
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
PUSHMI_TEMPLATE
(
class
V
)
(
requires
Invocable
<
NF
&
,
V
>
)
void
next
(
V
&&
v
)
{
if
(
done_
)
{
return
;}
nf_
((
V
&&
)
v
);
}
PUSHMI_TEMPLATE
(
class
E
)
(
requires
Invocable
<
EF
&
,
E
>
)
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
EF
&
,
E
>
,
"error function must be noexcept"
);
if
(
!
done_
)
{
done_
=
true
;
ef_
(
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
df_
();
}
}
};
template
<
PUSHMI_TYPE_CONSTRAINT
(
Receiver
)
Data
,
class
DNF
,
class
DEF
,
class
DDF
>
#if __cpp_concepts
requires
Invocable
<
DDF
&
,
Data
&>
#endif
class
many
<
Data
,
DNF
,
DEF
,
DDF
>
{
bool
done_
=
false
;
Data
data_
;
DNF
nf_
;
DEF
ef_
;
DDF
df_
;
static_assert
(
!
detail
::
is_v
<
DNF
,
on_error_fn
>
,
"the first parameter is the next implementation, but on_error{} was passed"
);
static_assert
(
!
detail
::
is_v
<
DEF
,
on_next_fn
>
,
"the second parameter is the error implementation, but on_next{} was passed"
);
static_assert
(
NothrowInvocable
<
DEF
,
Data
&
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
constexpr
explicit
many
(
Data
d
)
:
many
(
std
::
move
(
d
),
DNF
{},
DEF
{},
DDF
{})
{}
constexpr
many
(
Data
d
,
DDF
df
)
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(),
ef_
(),
df_
(
df
)
{}
constexpr
many
(
Data
d
,
DEF
ef
,
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(),
ef_
(
ef
),
df_
(
df
)
{}
constexpr
many
(
Data
d
,
DNF
nf
,
DEF
ef
=
DEF
{},
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(
nf
),
ef_
(
ef
),
df_
(
df
)
{}
PUSHMI_TEMPLATE
(
class
V
)
(
requires
Invocable
<
DNF
&
,
Data
&
,
V
>
)
void
next
(
V
&&
v
)
{
if
(
!
done_
)
{
nf_
(
data_
,
(
V
&&
)
v
);
}
}
PUSHMI_TEMPLATE
(
class
E
)
(
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
)
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
DEF
&
,
Data
&
,
E
>
,
"error function must be noexcept"
);
if
(
!
done_
)
{
done_
=
true
;
ef_
(
data_
,
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
df_
(
data_
);
}
}
};
template
<
>
class
many
<>
:
public
many
<
ignoreNF
,
abortEF
,
ignoreDF
>
{
public:
many
()
=
default
;
};
////////////////////////////////////////////////////////////////////////////////
// make_many
PUSHMI_INLINE_VAR
constexpr
struct
make_many_fn
{
inline
auto
operator
()()
const
{
return
many
<>
{};
}
PUSHMI_TEMPLATE
(
class
NF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
NF
&>
)))
auto
operator
()(
NF
nf
)
const
{
return
many
<
NF
,
abortEF
,
ignoreDF
>
{
std
::
move
(
nf
)};
}
template
<
class
...
EFN
>
auto
operator
()(
on_error_fn
<
EFN
...
>
ef
)
const
{
return
many
<
ignoreNF
,
on_error_fn
<
EFN
...
>
,
ignoreDF
>
{
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
DF
>
)))
auto
operator
()(
DF
df
)
const
{
return
many
<
ignoreNF
,
abortEF
,
DF
>
{
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
EF
&>
)))
auto
operator
()(
NF
nf
,
EF
ef
)
const
{
return
many
<
NF
,
EF
,
ignoreDF
>
{
std
::
move
(
nf
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
EF
>
)))
auto
operator
()(
EF
ef
,
DF
df
)
const
{
return
many
<
ignoreNF
,
EF
,
DF
>
{
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
)))
auto
operator
()(
NF
nf
,
EF
ef
,
DF
df
)
const
{
return
many
<
NF
,
EF
,
DF
>
{
std
::
move
(
nf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
))
auto
operator
()(
Data
d
)
const
{
return
many
<
Data
,
passDNXF
,
passDEF
,
passDDF
>
{
std
::
move
(
d
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DNF
&
,
Data
&>
)))
auto
operator
()(
Data
d
,
DNF
nf
)
const
{
return
many
<
Data
,
DNF
,
passDEF
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
...
DEFN
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
))
auto
operator
()(
Data
d
,
on_error_fn
<
DEFN
...
>
ef
)
const
{
return
many
<
Data
,
passDNXF
,
on_error_fn
<
DEFN
...
>
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DDF
df
)
const
{
return
many
<
Data
,
passDNXF
,
passDEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DEF
&
,
Data
&>
)))
auto
operator
()(
Data
d
,
DNF
nf
,
DEF
ef
)
const
{
return
many
<
Data
,
DNF
,
DEF
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DEF
ef
,
DDF
df
)
const
{
return
many
<
Data
,
passDNXF
,
DEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DNF
nf
,
DEF
ef
,
DDF
df
)
const
{
return
many
<
Data
,
DNF
,
DEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
}
const
make_many
{};
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703
many
()
->
many
<>
;
PUSHMI_TEMPLATE
(
class
NF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
NF
&>
)))
many
(
NF
)
->
many
<
NF
,
abortEF
,
ignoreDF
>
;
template
<
class
...
EFN
>
many
(
on_error_fn
<
EFN
...
>
)
->
many
<
ignoreNF
,
on_error_fn
<
EFN
...
>
,
ignoreDF
>
;
PUSHMI_TEMPLATE
(
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
DF
>
)))
many
(
DF
)
->
many
<
ignoreNF
,
abortEF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
EF
&>
)))
many
(
NF
,
EF
)
->
many
<
NF
,
EF
,
ignoreDF
>
;
PUSHMI_TEMPLATE
(
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
EF
>
)))
many
(
EF
,
DF
)
->
many
<
ignoreNF
,
EF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
)))
many
(
NF
,
EF
,
DF
)
->
many
<
NF
,
EF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
))
many
(
Data
d
)
->
many
<
Data
,
passDNXF
,
passDEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DNF
&
,
Data
&>
)))
many
(
Data
d
,
DNF
nf
)
->
many
<
Data
,
DNF
,
passDEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
...
DEFN
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
))
many
(
Data
d
,
on_error_fn
<
DEFN
...
>
)
->
many
<
Data
,
passDNXF
,
on_error_fn
<
DEFN
...
>
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DDF
)
->
many
<
Data
,
passDNXF
,
passDEF
,
DDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DEF
&
,
Data
&>
)))
many
(
Data
d
,
DNF
nf
,
DEF
ef
)
->
many
<
Data
,
DNF
,
DEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DEF
,
DDF
)
->
many
<
Data
,
passDNXF
,
DEF
,
DDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DNF
nf
,
DEF
ef
,
DDF
df
)
->
many
<
Data
,
DNF
,
DEF
,
DDF
>
;
#endif
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
using
any_many
=
many
<
V
,
E
>
;
template
<
>
struct
construct_deduced
<
many
>
{
template
<
class
...
AN
>
auto
operator
()(
AN
&&
...
an
)
const
->
decltype
(
pushmi
::
make_many
((
AN
&&
)
an
...))
{
return
pushmi
::
make_many
((
AN
&&
)
an
...);
}
};
// template <class V, class E = std::exception_ptr, class Wrapped>
// requires ManyReceiver<Wrapped, V, E> && !detail::is_v<Wrapped, none>
// auto erase_cast(Wrapped w) {
// return many<V, E>{std::move(w)};
// }
}
// 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 "many.h"
namespace
pushmi
{
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
class
any_many_deferred
{
union
data
{
void
*
pobj_
=
nullptr
;
char
buffer_
[
sizeof
(
V
)];
// can hold a V in-situ
}
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_submit
(
data
&
,
many
<
V
,
E
>
)
{}
void
(
*
op_
)(
data
&
,
data
*
)
=
vtable
::
s_op
;
void
(
*
submit_
)(
data
&
,
many
<
V
,
E
>
)
=
vtable
::
s_submit
;
};
static
constexpr
vtable
const
noop_
{};
vtable
const
*
vptr_
=
&
noop_
;
template
<
class
Wrapped
>
any_many_deferred
(
Wrapped
obj
,
std
::
false_type
)
:
any_many_deferred
()
{
struct
s
{
static
void
op
(
data
&
src
,
data
*
dst
)
{
if
(
dst
)
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
static
void
submit
(
data
&
src
,
many
<
V
,
E
>
out
)
{
::
pushmi
::
submit
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
std
::
move
(
out
));
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
submit
};
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
template
<
class
Wrapped
>
any_many_deferred
(
Wrapped
obj
,
std
::
true_type
)
noexcept
:
any_many_deferred
()
{
struct
s
{
static
void
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
void
submit
(
data
&
src
,
many
<
V
,
E
>
out
)
{
::
pushmi
::
submit
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
std
::
move
(
out
));
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
submit
};
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_many_deferred
>::
value
,
U
>
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
any_many_deferred
()
=
default
;
any_many_deferred
(
any_many_deferred
&&
that
)
noexcept
:
any_many_deferred
()
{
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
PUSHMI_TEMPLATE
(
class
Wrapped
)
(
requires
SenderTo
<
wrapped_t
<
Wrapped
>
,
many
<
V
,
E
>
,
is_many
<>>
)
explicit
any_many_deferred
(
Wrapped
obj
)
noexcept
(
insitu
<
Wrapped
>
())
:
any_many_deferred
{
std
::
move
(
obj
),
bool_
<
insitu
<
Wrapped
>
()
>
{}}
{}
~
any_many_deferred
()
{
vptr_
->
op_
(
data_
,
nullptr
);
}
any_many_deferred
&
operator
=
(
any_many_deferred
&&
that
)
noexcept
{
this
->~
any_many_deferred
();
new
((
void
*
)
this
)
any_many_deferred
(
std
::
move
(
that
));
return
*
this
;
}
void
submit
(
many
<
V
,
E
>
out
)
{
vptr_
->
submit_
(
data_
,
std
::
move
(
out
));
}
};
// Class static definitions:
template
<
class
V
,
class
E
>
constexpr
typename
any_many_deferred
<
V
,
E
>::
vtable
const
any_many_deferred
<
V
,
E
>::
noop_
;
template
<
class
SF
>
class
many_deferred
<
SF
>
{
SF
sf_
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
constexpr
many_deferred
()
=
default
;
constexpr
explicit
many_deferred
(
SF
sf
)
:
sf_
(
std
::
move
(
sf
))
{}
PUSHMI_TEMPLATE
(
class
Out
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Out
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
SF
&
,
Out
>
))
void
submit
(
Out
out
)
{
sf_
(
std
::
move
(
out
));
}
};
namespace
detail
{
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
<
is_many
<
>
>
)
Data
,
class
DSF
>
class
many_deferred_2
{
Data
data_
;
DSF
sf_
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
constexpr
many_deferred_2
()
=
default
;
constexpr
explicit
many_deferred_2
(
Data
data
)
:
data_
(
std
::
move
(
data
))
{}
constexpr
many_deferred_2
(
Data
data
,
DSF
sf
)
:
data_
(
std
::
move
(
data
)),
sf_
(
std
::
move
(
sf
))
{}
PUSHMI_TEMPLATE
(
class
Out
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Out
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DSF
&
,
Data
&
,
Out
>
))
void
submit
(
Out
out
)
{
sf_
(
data_
,
std
::
move
(
out
));
}
};
template
<
class
A
,
class
B
>
using
many_deferred_base
=
std
::
conditional_t
<
(
bool
)
Sender
<
A
,
is_many
<>>
,
many_deferred_2
<
A
,
B
>
,
any_many_deferred
<
A
,
B
>>
;
}
// namespace detail
template
<
class
A
,
class
B
>
struct
many_deferred
<
A
,
B
>
:
detail
::
many_deferred_base
<
A
,
B
>
{
constexpr
many_deferred
()
=
default
;
using
detail
::
many_deferred_base
<
A
,
B
>::
many_deferred_base
;
};
////////////////////////////////////////////////////////////////////////////////
// make_many_deferred
PUSHMI_INLINE_VAR
constexpr
struct
make_many_deferred_fn
{
inline
auto
operator
()()
const
{
return
many_deferred
<
ignoreSF
>
{};
}
PUSHMI_TEMPLATE
(
class
SF
)
(
requires
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
&&
not
Sender
<
SF
>
))
auto
operator
()(
SF
sf
)
const
{
return
many_deferred
<
SF
>
{
std
::
move
(
sf
)};
}
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
True
<>
&&
Sender
<
Data
,
is_many
<>>
)
auto
operator
()(
Data
d
)
const
{
return
many_deferred
<
Data
,
passDSF
>
{
std
::
move
(
d
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DSF
)
(
requires
Sender
<
Data
,
is_many
<>>
)
auto
operator
()(
Data
d
,
DSF
sf
)
const
{
return
many_deferred
<
Data
,
DSF
>
{
std
::
move
(
d
),
std
::
move
(
sf
)};
}
}
const
make_many_deferred
{};
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703
many_deferred
()
->
many_deferred
<
ignoreSF
>
;
PUSHMI_TEMPLATE
(
class
SF
)
(
requires
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
&&
not
Sender
<
SF
>
))
many_deferred
(
SF
)
->
many_deferred
<
SF
>
;
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
True
<>
&&
Sender
<
Data
,
is_many
<>>
)
many_deferred
(
Data
)
->
many_deferred
<
Data
,
passDSF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DSF
)
(
requires
Sender
<
Data
,
is_many
<>>
)
many_deferred
(
Data
,
DSF
)
->
many_deferred
<
Data
,
DSF
>
;
#endif
// template <
// class V,
// class E = std::exception_ptr,
// SenderTo<many<V, E>, is_many<>> Wrapped>
// auto erase_cast(Wrapped w) {
// return many_deferred<V, E>{std::move(w)};
// }
}
// 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 <algorithm>
//#include <algorithm>
//#include <chrono>
//#include <chrono>
//#include <deque>
//#include <deque>
...
@@ -5207,6 +5842,8 @@ inline auto new_thread() {
...
@@ -5207,6 +5842,8 @@ inline auto new_thread() {
//#include "../single.h"
//#include "../single.h"
//#include "../deferred.h"
//#include "../deferred.h"
//#include "../single_deferred.h"
//#include "../single_deferred.h"
//#include "../many.h"
//#include "../many_deferred.h"
//#include "../time_single_deferred.h"
//#include "../time_single_deferred.h"
//#include "../flow_single.h"
//#include "../flow_single.h"
//#include "../flow_single_deferred.h"
//#include "../flow_single_deferred.h"
...
@@ -5248,6 +5885,8 @@ struct make_receiver<is_none<>, void> : construct_deduced<none> {};
...
@@ -5248,6 +5885,8 @@ struct make_receiver<is_none<>, void> : construct_deduced<none> {};
template
<
>
template
<
>
struct
make_receiver
<
is_single
<>
,
void
>
:
construct_deduced
<
single
>
{};
struct
make_receiver
<
is_single
<>
,
void
>
:
construct_deduced
<
single
>
{};
template
<
>
template
<
>
struct
make_receiver
<
is_many
<>
,
void
>
:
construct_deduced
<
many
>
{};
template
<
>
struct
make_receiver
<
is_single
<>
,
is_flow
<>>
:
construct_deduced
<
flow_single
>
{};
struct
make_receiver
<
is_single
<>
,
is_flow
<>>
:
construct_deduced
<
flow_single
>
{};
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
)
In
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
)
In
>
...
@@ -5325,18 +5964,23 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
...
@@ -5325,18 +5964,23 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
);
);
}
}
PUSHMI_TEMPLATE
(
class
In
,
class
Out
)
PUSHMI_TEMPLATE
(
class
In
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
)
auto
deferred_from_maker
()
{
auto
deferred_from_maker
()
{
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
TimeSenderTo
<
In
,
Out
,
is_single
<>>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_flow
<>
,
is_single
<>>
)
(
return
make_flow_single_deferred
;
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_time
<>
,
is_single
<>>
)
(
return
make_time_single_deferred
;
return
make_time_single_deferred
;
)
else
(
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
SenderTo
<
In
,
Out
,
is_single
<>>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_single
<>>
)
(
return
make_single_deferred
;
return
make_single_deferred
;
)
else
(
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
SenderTo
<
In
,
Out
>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_many
<>
>
)
(
return
make
_deferred
;
return
make_many
_deferred
;
)
else
(
)
else
(
return
make_deferred
;
))
))
))
))
))
))
))
...
@@ -5345,13 +5989,25 @@ auto deferred_from_maker() {
...
@@ -5345,13 +5989,25 @@ auto deferred_from_maker() {
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
auto
deferred_from
(
FN
&&
...
fn
)
{
auto
deferred_from
(
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
,
Out
>
()((
FN
&&
)
fn
...);
return
deferred_from_maker
<
In
>
()((
FN
&&
)
fn
...);
}
}
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
,
Out
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
return
deferred_from_maker
<
In
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
}
PUSHMI_TEMPLATE
(
class
In
,
class
...
FN
)
(
requires
Sender
<
In
>
)
auto
deferred_from
(
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
>
()((
FN
&&
)
fn
...);
}
PUSHMI_TEMPLATE
(
class
In
,
class
...
FN
)
(
requires
Sender
<
In
>
)
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
}
}
PUSHMI_TEMPLATE
(
PUSHMI_TEMPLATE
(
...
@@ -5409,6 +6065,17 @@ struct set_done_fn {
...
@@ -5409,6 +6065,17 @@ struct set_done_fn {
}
}
};
};
struct
set_next_fn
{
template
<
class
V
>
auto
operator
()(
V
&&
v
)
const
{
return
constrain
(
lazy
::
Receiver
<
_1
,
is_many
<>>
,
[
v
=
(
V
&&
)
v
](
auto
out
)
mutable
{
::
pushmi
::
set_next
(
out
,
(
V
&&
)
v
);
}
);
}
};
struct
set_starting_fn
{
struct
set_starting_fn
{
PUSHMI_TEMPLATE
(
class
Up
)
PUSHMI_TEMPLATE
(
class
Up
)
(
requires
Receiver
<
Up
>
)
(
requires
Receiver
<
Up
>
)
...
@@ -5459,6 +6126,7 @@ namespace extension_operators {
...
@@ -5459,6 +6126,7 @@ namespace extension_operators {
PUSHMI_INLINE_VAR
constexpr
detail
::
set_done_fn
set_done
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_done_fn
set_done
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_error_fn
set_error
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_error_fn
set_error
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_value_fn
set_value
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_value_fn
set_value
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_next_fn
set_next
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_starting_fn
set_starting
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_starting_fn
set_starting
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
do_submit_fn
submit
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
do_submit_fn
submit
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
now_fn
now
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
now_fn
now
{};
...
@@ -5833,6 +6501,52 @@ inline auto empty() {
...
@@ -5833,6 +6501,52 @@ inline auto empty() {
}
}
}
// namespace operators
}
// 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 "../many_deferred.h"
//#include "extension_operators.h"
//#include "submit.h"
namespace
pushmi
{
namespace
operators
{
PUSHMI_TEMPLATE
(
class
O
,
class
S
)
(
requires
ConvertibleTo
<
typename
std
::
iterator_traits
<
O
>::
iterator_category
,
std
::
forward_iterator_tag
>
&&
ConvertibleTo
<
typename
std
::
iterator_traits
<
S
>::
iterator_category
,
std
::
forward_iterator_tag
>
)
auto
from
(
O
begin
,
S
end
)
{
return
make_many_deferred
(
constrain
(
lazy
::
ManyReceiver
<
_1
,
typename
std
::
iterator_traits
<
O
>::
value_type
>
,
[
begin
=
std
::
move
(
begin
),
end
=
std
::
move
(
end
)](
auto
out
)
{
auto
c
=
begin
;
for
(;
c
!=
end
;
++
c
)
{
::
pushmi
::
set_next
(
out
,
*
c
);
}
::
pushmi
::
set_done
(
out
);
}));
}
PUSHMI_TEMPLATE
(
class
R
)
(
requires
requires
(
std
::
begin
(
std
::
declval
<
R
&&>
()),
std
::
end
(
std
::
declval
<
R
&&>
())
))
auto
from
(
R
&&
range
)
{
return
from
(
std
::
begin
(
range
),
std
::
end
(
range
));
}
}
// namespace operators
}
// namespace pushmi
}
// namespace pushmi
// clang-format off
// clang-format off
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
// clang format does not support the '<>' in the lambda syntax yet.. []<>()->{}
...
@@ -6285,6 +6999,7 @@ PUSHMI_INLINE_VAR constexpr detail::tap_fn tap{};
...
@@ -6285,6 +6999,7 @@ PUSHMI_INLINE_VAR constexpr detail::tap_fn tap{};
// LICENSE file in the root directory of this source tree.
// LICENSE file in the root directory of this source tree.
//#include "../single.h"
//#include "../single.h"
//#include "../many.h"
//#include "submit.h"
//#include "submit.h"
//#include "extension_operators.h"
//#include "extension_operators.h"
...
@@ -6292,13 +7007,19 @@ namespace pushmi {
...
@@ -6292,13 +7007,19 @@ namespace pushmi {
namespace
detail
{
namespace
detail
{
// extracted this to workaround cuda compiler failure to compute the static_asserts in the nested lambda context
template
<
class
F
,
class
Tag
>
struct
transform_on
;
template
<
class
F
>
template
<
class
F
>
struct
transform_on
_value
{
struct
transform_on
<
F
,
is_single
<>>
{
F
f_
;
F
f_
;
transform_on
_value
()
=
default
;
transform_on
()
=
default
;
constexpr
explicit
transform_on
_value
(
F
f
)
constexpr
explicit
transform_on
(
F
f
)
:
f_
(
std
::
move
(
f
))
{}
:
f_
(
std
::
move
(
f
))
{}
template
<
class
Out
>
auto
operator
()(
Out
out
)
const
{
return
make_single
(
std
::
move
(
out
),
on_value
(
*
this
));
}
template
<
class
Out
,
class
V
>
template
<
class
Out
,
class
V
>
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
...
@@ -6310,6 +7031,27 @@ struct transform_on_value {
...
@@ -6310,6 +7031,27 @@ struct transform_on_value {
}
}
};
};
template
<
class
F
>
struct
transform_on
<
F
,
is_many
<>>
{
F
f_
;
transform_on
()
=
default
;
constexpr
explicit
transform_on
(
F
f
)
:
f_
(
std
::
move
(
f
))
{}
template
<
class
Out
>
auto
operator
()(
Out
out
)
const
{
return
make_many
(
std
::
move
(
out
),
on_next
(
*
this
));
}
template
<
class
Out
,
class
V
>
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
static_assert
(
::
pushmi
::
SemiMovable
<
Result
>
,
"none of the functions supplied to transform can convert this value"
);
static_assert
(
::
pushmi
::
ManyReceiver
<
Out
,
Result
>
,
"Result of value transform cannot be delivered to Out"
);
::
pushmi
::
set_next
(
out
,
f_
((
V
&&
)
v
));
}
};
struct
transform_fn
{
struct
transform_fn
{
template
<
class
...
FN
>
template
<
class
...
FN
>
auto
operator
()(
FN
...
fn
)
const
;
auto
operator
()(
FN
...
fn
)
const
;
...
@@ -6322,28 +7064,11 @@ auto transform_fn::operator()(FN... fn) const {
...
@@ -6322,28 +7064,11 @@ auto transform_fn::operator()(FN... fn) const {
using
In
=
decltype
(
in
);
using
In
=
decltype
(
in
);
// copy 'f' to allow multiple calls to connect to multiple 'in'
// copy 'f' to allow multiple calls to connect to multiple 'in'
using
F
=
decltype
(
f
);
using
F
=
decltype
(
f
);
return
::
pushmi
::
detail
::
deferred_from
<
In
,
::
pushmi
::
single
<>>
(
using
Cardinality
=
property_set_index_t
<
properties_t
<
In
>
,
is_silent
<>>
;
return
::
pushmi
::
detail
::
deferred_from
<
In
>
(
std
::
move
(
in
),
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
constrain
(
::
pushmi
::
lazy
::
Receiver
<::
pushmi
::
_1
>
,
[
f
](
auto
out
)
{
transform_on
<
F
,
Cardinality
>
{
f
}
using
Out
=
decltype
(
out
);
return
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
out
),
// copy 'f' to allow multiple calls to submit
::
pushmi
::
on_value
(
transform_on_value
<
F
>
(
f
)
// [f](Out& out, auto&& v) {
// using V = decltype(v);
// using Result = decltype(f((V&&) v));
// static_assert(::pushmi::SemiMovable<Result>,
// "none of the functions supplied to transform can convert this value");
// static_assert(::pushmi::SingleReceiver<Out, Result>,
// "Result of value transform cannot be delivered to Out");
// ::pushmi::set_value(out, f((V&&) v));
// }
)
);
})
)
)
);
);
});
});
...
...
folly/experimental/pushmi/include/pushmi/boosters.h
View file @
0f0583e4
...
@@ -34,6 +34,9 @@ struct construct_deduced<none>;
...
@@ -34,6 +34,9 @@ struct construct_deduced<none>;
template
<
>
template
<
>
struct
construct_deduced
<
single
>
;
struct
construct_deduced
<
single
>
;
template
<
>
struct
construct_deduced
<
many
>
;
template
<
>
template
<
>
struct
construct_deduced
<
flow_single
>
;
struct
construct_deduced
<
flow_single
>
;
...
...
folly/experimental/pushmi/include/pushmi/forwards.h
View file @
0f0583e4
...
@@ -56,9 +56,15 @@ class deferred;
...
@@ -56,9 +56,15 @@ class deferred;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
single
;
class
single
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
many
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
single_deferred
;
class
single_deferred
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
many_deferred
;
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
SemiMovable
)...
TN
>
class
time_single_deferred
;
class
time_single_deferred
;
...
...
folly/experimental/pushmi/include/pushmi/many.h
0 → 100644
View file @
0f0583e4
#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 <future>
#include "none.h"
namespace
pushmi
{
template
<
class
V
,
class
E
>
class
many
<
V
,
E
>
{
bool
done_
=
false
;
union
data
{
void
*
pobj_
=
nullptr
;
char
buffer_
[
sizeof
(
std
::
promise
<
int
>
)];
// can hold a std::promise in-situ
}
data_
{};
template
<
class
Wrapped
>
static
constexpr
bool
insitu
()
noexcept
{
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
std
::
is_nothrow_move_constructible
<
Wrapped
>::
value
;
}
struct
vtable
{
static
void
s_op
(
data
&
,
data
*
)
{}
static
void
s_done
(
data
&
)
{}
static
void
s_error
(
data
&
,
E
)
noexcept
{
std
::
terminate
();
}
static
void
s_rnext
(
data
&
,
V
&&
)
{}
static
void
s_lnext
(
data
&
,
V
&
)
{}
void
(
*
op_
)(
data
&
,
data
*
)
=
vtable
::
s_op
;
void
(
*
done_
)(
data
&
)
=
vtable
::
s_done
;
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
vtable
::
s_error
;
void
(
*
rnext_
)(
data
&
,
V
&&
)
=
vtable
::
s_rnext
;
void
(
*
lnext_
)(
data
&
,
V
&
)
=
vtable
::
s_lnext
;
};
static
constexpr
vtable
const
noop_
{};
vtable
const
*
vptr_
=
&
noop_
;
template
<
class
T
,
class
U
=
std
::
decay_t
<
T
>
>
using
wrapped_t
=
std
::
enable_if_t
<!
std
::
is_same
<
U
,
many
>::
value
,
U
>
;
template
<
class
Wrapped
>
static
void
check
()
{
static_assert
(
Invocable
<
decltype
(
::
pushmi
::
set_next
),
Wrapped
,
V
>
,
"Wrapped many must support nexts of type V"
);
static_assert
(
NothrowInvocable
<
decltype
(
::
pushmi
::
set_error
),
Wrapped
,
std
::
exception_ptr
>
,
"Wrapped many must support std::exception_ptr and be noexcept"
);
static_assert
(
NothrowInvocable
<
decltype
(
::
pushmi
::
set_error
),
Wrapped
,
E
>
,
"Wrapped many must support E and be noexcept"
);
}
template
<
class
Wrapped
>
many
(
Wrapped
obj
,
std
::
false_type
)
:
many
()
{
struct
s
{
static
void
op
(
data
&
src
,
data
*
dst
)
{
if
(
dst
)
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
static
void
done
(
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
}
static
void
error
(
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
std
::
move
(
e
));
}
static
void
rnext
(
data
&
src
,
V
&&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
(
V
&&
)
v
);
}
static
void
lnext
(
data
&
src
,
V
&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
v
);
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
done
,
s
::
error
,
s
::
rnext
,
s
::
lnext
};
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
template
<
class
Wrapped
>
many
(
Wrapped
obj
,
std
::
true_type
)
noexcept
:
many
()
{
struct
s
{
static
void
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
void
done
(
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
}
static
void
error
(
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
std
::
move
(
e
));
}
static
void
rnext
(
data
&
src
,
V
&&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
(
V
&&
)
v
);
}
static
void
lnext
(
data
&
src
,
V
&
v
)
{
::
pushmi
::
set_next
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
v
);
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
done
,
s
::
error
,
s
::
rnext
,
s
::
lnext
};
new
((
void
*
)
data_
.
buffer_
)
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
many
()
=
default
;
many
(
many
&&
that
)
noexcept
:
many
()
{
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
PUSHMI_TEMPLATE
(
class
Wrapped
)
(
requires
ManyReceiver
<
wrapped_t
<
Wrapped
>
,
V
,
E
>
)
explicit
many
(
Wrapped
obj
)
noexcept
(
insitu
<
Wrapped
>
())
:
many
{
std
::
move
(
obj
),
bool_
<
insitu
<
Wrapped
>
()
>
{}}
{
check
<
Wrapped
>
();
}
~
many
()
{
vptr_
->
op_
(
data_
,
nullptr
);
}
many
&
operator
=
(
many
&&
that
)
noexcept
{
this
->~
many
();
new
((
void
*
)
this
)
many
(
std
::
move
(
that
));
return
*
this
;
}
PUSHMI_TEMPLATE
(
class
T
)
(
requires
ConvertibleTo
<
T
&&
,
V
&&>
)
void
next
(
T
&&
t
)
{
if
(
!
done_
)
{
vptr_
->
rnext_
(
data_
,
(
T
&&
)
t
);
}
}
PUSHMI_TEMPLATE
(
class
T
)
(
requires
ConvertibleTo
<
T
&
,
V
&>
)
void
next
(
T
&
t
)
{
if
(
!
done_
)
{
vptr_
->
lnext_
(
data_
,
t
);
}
}
void
error
(
E
e
)
noexcept
{
if
(
!
done_
)
{
done_
=
true
;
vptr_
->
error_
(
data_
,
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
vptr_
->
done_
(
data_
);
}
}
};
// Class static definitions:
template
<
class
V
,
class
E
>
constexpr
typename
many
<
V
,
E
>::
vtable
const
many
<
V
,
E
>::
noop_
;
template
<
class
NF
,
class
EF
,
class
DF
>
#if __cpp_concepts
requires
Invocable
<
DF
&>
#endif
class
many
<
NF
,
EF
,
DF
>
{
bool
done_
=
false
;
NF
nf_
;
EF
ef_
;
DF
df_
;
static_assert
(
!
detail
::
is_v
<
NF
,
on_error_fn
>
,
"the first parameter is the next implementation, but on_error{} was passed"
);
static_assert
(
!
detail
::
is_v
<
EF
,
on_next_fn
>
,
"the second parameter is the error implementation, but on_next{} was passed"
);
static_assert
(
NothrowInvocable
<
EF
&
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
many
()
=
default
;
constexpr
explicit
many
(
NF
nf
)
:
many
(
std
::
move
(
nf
),
EF
{},
DF
{})
{}
constexpr
explicit
many
(
EF
ef
)
:
many
(
NF
{},
std
::
move
(
ef
),
DF
{})
{}
constexpr
explicit
many
(
DF
df
)
:
many
(
NF
{},
EF
{},
std
::
move
(
df
))
{}
constexpr
many
(
EF
ef
,
DF
df
)
:
done_
(
false
),
nf_
(),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
constexpr
many
(
NF
nf
,
EF
ef
,
DF
df
=
DF
{})
:
done_
(
false
),
nf_
(
std
::
move
(
nf
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
PUSHMI_TEMPLATE
(
class
V
)
(
requires
Invocable
<
NF
&
,
V
>
)
void
next
(
V
&&
v
)
{
if
(
done_
)
{
return
;}
nf_
((
V
&&
)
v
);
}
PUSHMI_TEMPLATE
(
class
E
)
(
requires
Invocable
<
EF
&
,
E
>
)
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
EF
&
,
E
>
,
"error function must be noexcept"
);
if
(
!
done_
)
{
done_
=
true
;
ef_
(
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
df_
();
}
}
};
template
<
PUSHMI_TYPE_CONSTRAINT
(
Receiver
)
Data
,
class
DNF
,
class
DEF
,
class
DDF
>
#if __cpp_concepts
requires
Invocable
<
DDF
&
,
Data
&>
#endif
class
many
<
Data
,
DNF
,
DEF
,
DDF
>
{
bool
done_
=
false
;
Data
data_
;
DNF
nf_
;
DEF
ef_
;
DDF
df_
;
static_assert
(
!
detail
::
is_v
<
DNF
,
on_error_fn
>
,
"the first parameter is the next implementation, but on_error{} was passed"
);
static_assert
(
!
detail
::
is_v
<
DEF
,
on_next_fn
>
,
"the second parameter is the error implementation, but on_next{} was passed"
);
static_assert
(
NothrowInvocable
<
DEF
,
Data
&
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
public:
using
properties
=
property_set
<
is_receiver
<>
,
is_many
<>>
;
constexpr
explicit
many
(
Data
d
)
:
many
(
std
::
move
(
d
),
DNF
{},
DEF
{},
DDF
{})
{}
constexpr
many
(
Data
d
,
DDF
df
)
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(),
ef_
(),
df_
(
df
)
{}
constexpr
many
(
Data
d
,
DEF
ef
,
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(),
ef_
(
ef
),
df_
(
df
)
{}
constexpr
many
(
Data
d
,
DNF
nf
,
DEF
ef
=
DEF
{},
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
nf_
(
nf
),
ef_
(
ef
),
df_
(
df
)
{}
PUSHMI_TEMPLATE
(
class
V
)
(
requires
Invocable
<
DNF
&
,
Data
&
,
V
>
)
void
next
(
V
&&
v
)
{
if
(
!
done_
)
{
nf_
(
data_
,
(
V
&&
)
v
);
}
}
PUSHMI_TEMPLATE
(
class
E
)
(
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
)
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
DEF
&
,
Data
&
,
E
>
,
"error function must be noexcept"
);
if
(
!
done_
)
{
done_
=
true
;
ef_
(
data_
,
std
::
move
(
e
));
}
}
void
done
()
{
if
(
!
done_
)
{
done_
=
true
;
df_
(
data_
);
}
}
};
template
<
>
class
many
<>
:
public
many
<
ignoreNF
,
abortEF
,
ignoreDF
>
{
public:
many
()
=
default
;
};
////////////////////////////////////////////////////////////////////////////////
// make_many
PUSHMI_INLINE_VAR
constexpr
struct
make_many_fn
{
inline
auto
operator
()()
const
{
return
many
<>
{};
}
PUSHMI_TEMPLATE
(
class
NF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
NF
&>
)))
auto
operator
()(
NF
nf
)
const
{
return
many
<
NF
,
abortEF
,
ignoreDF
>
{
std
::
move
(
nf
)};
}
template
<
class
...
EFN
>
auto
operator
()(
on_error_fn
<
EFN
...
>
ef
)
const
{
return
many
<
ignoreNF
,
on_error_fn
<
EFN
...
>
,
ignoreDF
>
{
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
DF
>
)))
auto
operator
()(
DF
df
)
const
{
return
many
<
ignoreNF
,
abortEF
,
DF
>
{
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
EF
&>
)))
auto
operator
()(
NF
nf
,
EF
ef
)
const
{
return
many
<
NF
,
EF
,
ignoreDF
>
{
std
::
move
(
nf
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
EF
>
)))
auto
operator
()(
EF
ef
,
DF
df
)
const
{
return
many
<
ignoreNF
,
EF
,
DF
>
{
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
)))
auto
operator
()(
NF
nf
,
EF
ef
,
DF
df
)
const
{
return
many
<
NF
,
EF
,
DF
>
{
std
::
move
(
nf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
))
auto
operator
()(
Data
d
)
const
{
return
many
<
Data
,
passDNXF
,
passDEF
,
passDDF
>
{
std
::
move
(
d
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DNF
&
,
Data
&>
)))
auto
operator
()(
Data
d
,
DNF
nf
)
const
{
return
many
<
Data
,
DNF
,
passDEF
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
...
DEFN
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
))
auto
operator
()(
Data
d
,
on_error_fn
<
DEFN
...
>
ef
)
const
{
return
many
<
Data
,
passDNXF
,
on_error_fn
<
DEFN
...
>
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DDF
df
)
const
{
return
many
<
Data
,
passDNXF
,
passDEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DEF
&
,
Data
&>
)))
auto
operator
()(
Data
d
,
DNF
nf
,
DEF
ef
)
const
{
return
many
<
Data
,
DNF
,
DEF
,
passDDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
),
std
::
move
(
ef
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DEF
ef
,
DDF
df
)
const
{
return
many
<
Data
,
passDNXF
,
DEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
auto
operator
()(
Data
d
,
DNF
nf
,
DEF
ef
,
DDF
df
)
const
{
return
many
<
Data
,
DNF
,
DEF
,
DDF
>
{
std
::
move
(
d
),
std
::
move
(
nf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
}
const
make_many
{};
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703
many
()
->
many
<>
;
PUSHMI_TEMPLATE
(
class
NF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
NF
&>
)))
many
(
NF
)
->
many
<
NF
,
abortEF
,
ignoreDF
>
;
template
<
class
...
EFN
>
many
(
on_error_fn
<
EFN
...
>
)
->
many
<
ignoreNF
,
on_error_fn
<
EFN
...
>
,
ignoreDF
>
;
PUSHMI_TEMPLATE
(
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
DF
>
)))
many
(
DF
)
->
many
<
ignoreNF
,
abortEF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
PUSHMI_AND
not
defer
::
Invocable
<
EF
&>
)))
many
(
NF
,
EF
)
->
many
<
NF
,
EF
,
ignoreDF
>
;
PUSHMI_TEMPLATE
(
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
EF
>
)))
many
(
EF
,
DF
)
->
many
<
ignoreNF
,
EF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
NF
,
class
EF
,
class
DF
)
(
requires
PUSHMI_EXP
(
defer
::
Invocable
<
DF
&>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Receiver
<
NF
>
)))
many
(
NF
,
EF
,
DF
)
->
many
<
NF
,
EF
,
DF
>
;
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
))
many
(
Data
d
)
->
many
<
Data
,
passDNXF
,
passDEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DNF
&
,
Data
&>
)))
many
(
Data
d
,
DNF
nf
)
->
many
<
Data
,
DNF
,
passDEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
...
DEFN
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
))
many
(
Data
d
,
on_error_fn
<
DEFN
...
>
)
->
many
<
Data
,
passDNXF
,
on_error_fn
<
DEFN
...
>
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
True
<>
PUSHMI_AND
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DDF
)
->
many
<
Data
,
passDNXF
,
passDEF
,
DDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_BROKEN_SUBSUMPTION
(
PUSHMI_AND
not
defer
::
Invocable
<
DEF
&
,
Data
&>
)))
many
(
Data
d
,
DNF
nf
,
DEF
ef
)
->
many
<
Data
,
DNF
,
DEF
,
passDDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DEF
,
DDF
)
->
many
<
Data
,
passDNXF
,
DEF
,
DDF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DNF
,
class
DEF
,
class
DDF
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Data
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DDF
&
,
Data
&>
))
many
(
Data
d
,
DNF
nf
,
DEF
ef
,
DDF
df
)
->
many
<
Data
,
DNF
,
DEF
,
DDF
>
;
#endif
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
using
any_many
=
many
<
V
,
E
>
;
template
<
>
struct
construct_deduced
<
many
>
{
template
<
class
...
AN
>
auto
operator
()(
AN
&&
...
an
)
const
->
decltype
(
pushmi
::
make_many
((
AN
&&
)
an
...))
{
return
pushmi
::
make_many
((
AN
&&
)
an
...);
}
};
// template <class V, class E = std::exception_ptr, class Wrapped>
// requires ManyReceiver<Wrapped, V, E> && !detail::is_v<Wrapped, none>
// auto erase_cast(Wrapped w) {
// return many<V, E>{std::move(w)};
// }
}
// namespace pushmi
folly/experimental/pushmi/include/pushmi/many_deferred.h
0 → 100644
View file @
0f0583e4
#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 "many.h"
namespace
pushmi
{
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
class
any_many_deferred
{
union
data
{
void
*
pobj_
=
nullptr
;
char
buffer_
[
sizeof
(
V
)];
// can hold a V in-situ
}
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_submit
(
data
&
,
many
<
V
,
E
>
)
{}
void
(
*
op_
)(
data
&
,
data
*
)
=
vtable
::
s_op
;
void
(
*
submit_
)(
data
&
,
many
<
V
,
E
>
)
=
vtable
::
s_submit
;
};
static
constexpr
vtable
const
noop_
{};
vtable
const
*
vptr_
=
&
noop_
;
template
<
class
Wrapped
>
any_many_deferred
(
Wrapped
obj
,
std
::
false_type
)
:
any_many_deferred
()
{
struct
s
{
static
void
op
(
data
&
src
,
data
*
dst
)
{
if
(
dst
)
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
static
void
submit
(
data
&
src
,
many
<
V
,
E
>
out
)
{
::
pushmi
::
submit
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
),
std
::
move
(
out
));
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
submit
};
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
vtbl
;
}
template
<
class
Wrapped
>
any_many_deferred
(
Wrapped
obj
,
std
::
true_type
)
noexcept
:
any_many_deferred
()
{
struct
s
{
static
void
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
void
submit
(
data
&
src
,
many
<
V
,
E
>
out
)
{
::
pushmi
::
submit
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
std
::
move
(
out
));
}
};
static
const
vtable
vtbl
{
s
::
op
,
s
::
submit
};
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_many_deferred
>::
value
,
U
>
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
any_many_deferred
()
=
default
;
any_many_deferred
(
any_many_deferred
&&
that
)
noexcept
:
any_many_deferred
()
{
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
PUSHMI_TEMPLATE
(
class
Wrapped
)
(
requires
SenderTo
<
wrapped_t
<
Wrapped
>
,
many
<
V
,
E
>
,
is_many
<>>
)
explicit
any_many_deferred
(
Wrapped
obj
)
noexcept
(
insitu
<
Wrapped
>
())
:
any_many_deferred
{
std
::
move
(
obj
),
bool_
<
insitu
<
Wrapped
>
()
>
{}}
{}
~
any_many_deferred
()
{
vptr_
->
op_
(
data_
,
nullptr
);
}
any_many_deferred
&
operator
=
(
any_many_deferred
&&
that
)
noexcept
{
this
->~
any_many_deferred
();
new
((
void
*
)
this
)
any_many_deferred
(
std
::
move
(
that
));
return
*
this
;
}
void
submit
(
many
<
V
,
E
>
out
)
{
vptr_
->
submit_
(
data_
,
std
::
move
(
out
));
}
};
// Class static definitions:
template
<
class
V
,
class
E
>
constexpr
typename
any_many_deferred
<
V
,
E
>::
vtable
const
any_many_deferred
<
V
,
E
>::
noop_
;
template
<
class
SF
>
class
many_deferred
<
SF
>
{
SF
sf_
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
constexpr
many_deferred
()
=
default
;
constexpr
explicit
many_deferred
(
SF
sf
)
:
sf_
(
std
::
move
(
sf
))
{}
PUSHMI_TEMPLATE
(
class
Out
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Out
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
SF
&
,
Out
>
))
void
submit
(
Out
out
)
{
sf_
(
std
::
move
(
out
));
}
};
namespace
detail
{
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
<
is_many
<
>
>
)
Data
,
class
DSF
>
class
many_deferred_2
{
Data
data_
;
DSF
sf_
;
public:
using
properties
=
property_set
<
is_sender
<>
,
is_many
<>>
;
constexpr
many_deferred_2
()
=
default
;
constexpr
explicit
many_deferred_2
(
Data
data
)
:
data_
(
std
::
move
(
data
))
{}
constexpr
many_deferred_2
(
Data
data
,
DSF
sf
)
:
data_
(
std
::
move
(
data
)),
sf_
(
std
::
move
(
sf
))
{}
PUSHMI_TEMPLATE
(
class
Out
)
(
requires
PUSHMI_EXP
(
defer
::
Receiver
<
Out
,
is_many
<>>
PUSHMI_AND
defer
::
Invocable
<
DSF
&
,
Data
&
,
Out
>
))
void
submit
(
Out
out
)
{
sf_
(
data_
,
std
::
move
(
out
));
}
};
template
<
class
A
,
class
B
>
using
many_deferred_base
=
std
::
conditional_t
<
(
bool
)
Sender
<
A
,
is_many
<>>
,
many_deferred_2
<
A
,
B
>
,
any_many_deferred
<
A
,
B
>>
;
}
// namespace detail
template
<
class
A
,
class
B
>
struct
many_deferred
<
A
,
B
>
:
detail
::
many_deferred_base
<
A
,
B
>
{
constexpr
many_deferred
()
=
default
;
using
detail
::
many_deferred_base
<
A
,
B
>::
many_deferred_base
;
};
////////////////////////////////////////////////////////////////////////////////
// make_many_deferred
PUSHMI_INLINE_VAR
constexpr
struct
make_many_deferred_fn
{
inline
auto
operator
()()
const
{
return
many_deferred
<
ignoreSF
>
{};
}
PUSHMI_TEMPLATE
(
class
SF
)
(
requires
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
&&
not
Sender
<
SF
>
))
auto
operator
()(
SF
sf
)
const
{
return
many_deferred
<
SF
>
{
std
::
move
(
sf
)};
}
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
True
<>
&&
Sender
<
Data
,
is_many
<>>
)
auto
operator
()(
Data
d
)
const
{
return
many_deferred
<
Data
,
passDSF
>
{
std
::
move
(
d
)};
}
PUSHMI_TEMPLATE
(
class
Data
,
class
DSF
)
(
requires
Sender
<
Data
,
is_many
<>>
)
auto
operator
()(
Data
d
,
DSF
sf
)
const
{
return
many_deferred
<
Data
,
DSF
>
{
std
::
move
(
d
),
std
::
move
(
sf
)};
}
}
const
make_many_deferred
{};
////////////////////////////////////////////////////////////////////////////////
// deduction guides
#if __cpp_deduction_guides >= 201703
many_deferred
()
->
many_deferred
<
ignoreSF
>
;
PUSHMI_TEMPLATE
(
class
SF
)
(
requires
True
<>
PUSHMI_BROKEN_SUBSUMPTION
(
&&
not
Sender
<
SF
>
))
many_deferred
(
SF
)
->
many_deferred
<
SF
>
;
PUSHMI_TEMPLATE
(
class
Data
)
(
requires
True
<>
&&
Sender
<
Data
,
is_many
<>>
)
many_deferred
(
Data
)
->
many_deferred
<
Data
,
passDSF
>
;
PUSHMI_TEMPLATE
(
class
Data
,
class
DSF
)
(
requires
Sender
<
Data
,
is_many
<>>
)
many_deferred
(
Data
,
DSF
)
->
many_deferred
<
Data
,
DSF
>
;
#endif
// template <
// class V,
// class E = std::exception_ptr,
// SenderTo<many<V, E>, is_many<>> Wrapped>
// auto erase_cast(Wrapped w) {
// return many_deferred<V, E>{std::move(w)};
// }
}
// namespace pushmi
folly/experimental/pushmi/include/pushmi/o/extension_operators.h
View file @
0f0583e4
...
@@ -12,6 +12,8 @@
...
@@ -12,6 +12,8 @@
#include "../single.h"
#include "../single.h"
#include "../deferred.h"
#include "../deferred.h"
#include "../single_deferred.h"
#include "../single_deferred.h"
#include "../many.h"
#include "../many_deferred.h"
#include "../time_single_deferred.h"
#include "../time_single_deferred.h"
#include "../flow_single.h"
#include "../flow_single.h"
#include "../flow_single_deferred.h"
#include "../flow_single_deferred.h"
...
@@ -53,6 +55,8 @@ struct make_receiver<is_none<>, void> : construct_deduced<none> {};
...
@@ -53,6 +55,8 @@ struct make_receiver<is_none<>, void> : construct_deduced<none> {};
template
<
>
template
<
>
struct
make_receiver
<
is_single
<>
,
void
>
:
construct_deduced
<
single
>
{};
struct
make_receiver
<
is_single
<>
,
void
>
:
construct_deduced
<
single
>
{};
template
<
>
template
<
>
struct
make_receiver
<
is_many
<>
,
void
>
:
construct_deduced
<
many
>
{};
template
<
>
struct
make_receiver
<
is_single
<>
,
is_flow
<>>
:
construct_deduced
<
flow_single
>
{};
struct
make_receiver
<
is_single
<>
,
is_flow
<>>
:
construct_deduced
<
flow_single
>
{};
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
)
In
>
template
<
PUSHMI_TYPE_CONSTRAINT
(
Sender
)
In
>
...
@@ -130,18 +134,23 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
...
@@ -130,18 +134,23 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf) {
);
);
}
}
PUSHMI_TEMPLATE
(
class
In
,
class
Out
)
PUSHMI_TEMPLATE
(
class
In
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
)
auto
deferred_from_maker
()
{
auto
deferred_from_maker
()
{
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
TimeSenderTo
<
In
,
Out
,
is_single
<>>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_flow
<>
,
is_single
<>>
)
(
return
make_flow_single_deferred
;
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_time
<>
,
is_single
<>>
)
(
return
make_time_single_deferred
;
return
make_time_single_deferred
;
)
else
(
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
SenderTo
<
In
,
Out
,
is_single
<>>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_single
<>>
)
(
return
make_single_deferred
;
return
make_single_deferred
;
)
else
(
)
else
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
SenderTo
<
In
,
Out
>
)
(
PUSHMI_IF_CONSTEXPR_RETURN
(
((
bool
)
Sender
<
In
,
is_many
<>
>
)
(
return
make
_deferred
;
return
make_many
_deferred
;
)
else
(
)
else
(
return
make_deferred
;
))
))
))
))
))
))
))
...
@@ -150,13 +159,25 @@ auto deferred_from_maker() {
...
@@ -150,13 +159,25 @@ auto deferred_from_maker() {
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
auto
deferred_from
(
FN
&&
...
fn
)
{
auto
deferred_from
(
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
,
Out
>
()((
FN
&&
)
fn
...);
return
deferred_from_maker
<
In
>
()((
FN
&&
)
fn
...);
}
}
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
PUSHMI_TEMPLATE
(
class
In
,
class
Out
,
class
...
FN
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
(
requires
Sender
<
In
>
&&
Receiver
<
Out
>
)
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
,
Out
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
return
deferred_from_maker
<
In
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
}
PUSHMI_TEMPLATE
(
class
In
,
class
...
FN
)
(
requires
Sender
<
In
>
)
auto
deferred_from
(
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
>
()((
FN
&&
)
fn
...);
}
PUSHMI_TEMPLATE
(
class
In
,
class
...
FN
)
(
requires
Sender
<
In
>
)
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
return
deferred_from_maker
<
In
>
()(
std
::
move
(
in
),
(
FN
&&
)
fn
...);
}
}
PUSHMI_TEMPLATE
(
PUSHMI_TEMPLATE
(
...
@@ -214,6 +235,17 @@ struct set_done_fn {
...
@@ -214,6 +235,17 @@ struct set_done_fn {
}
}
};
};
struct
set_next_fn
{
template
<
class
V
>
auto
operator
()(
V
&&
v
)
const
{
return
constrain
(
lazy
::
Receiver
<
_1
,
is_many
<>>
,
[
v
=
(
V
&&
)
v
](
auto
out
)
mutable
{
::
pushmi
::
set_next
(
out
,
(
V
&&
)
v
);
}
);
}
};
struct
set_starting_fn
{
struct
set_starting_fn
{
PUSHMI_TEMPLATE
(
class
Up
)
PUSHMI_TEMPLATE
(
class
Up
)
(
requires
Receiver
<
Up
>
)
(
requires
Receiver
<
Up
>
)
...
@@ -264,6 +296,7 @@ namespace extension_operators {
...
@@ -264,6 +296,7 @@ namespace extension_operators {
PUSHMI_INLINE_VAR
constexpr
detail
::
set_done_fn
set_done
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_done_fn
set_done
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_error_fn
set_error
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_error_fn
set_error
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_value_fn
set_value
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_value_fn
set_value
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_next_fn
set_next
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_starting_fn
set_starting
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
set_starting_fn
set_starting
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
do_submit_fn
submit
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
do_submit_fn
submit
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
now_fn
now
{};
PUSHMI_INLINE_VAR
constexpr
detail
::
now_fn
now
{};
...
...
folly/experimental/pushmi/include/pushmi/o/from.h
0 → 100644
View file @
0f0583e4
#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 "../many_deferred.h"
#include "extension_operators.h"
#include "submit.h"
namespace
pushmi
{
namespace
operators
{
PUSHMI_TEMPLATE
(
class
O
,
class
S
)
(
requires
ConvertibleTo
<
typename
std
::
iterator_traits
<
O
>::
iterator_category
,
std
::
forward_iterator_tag
>
&&
ConvertibleTo
<
typename
std
::
iterator_traits
<
S
>::
iterator_category
,
std
::
forward_iterator_tag
>
)
auto
from
(
O
begin
,
S
end
)
{
return
make_many_deferred
(
constrain
(
lazy
::
ManyReceiver
<
_1
,
typename
std
::
iterator_traits
<
O
>::
value_type
>
,
[
begin
=
std
::
move
(
begin
),
end
=
std
::
move
(
end
)](
auto
out
)
{
auto
c
=
begin
;
for
(;
c
!=
end
;
++
c
)
{
::
pushmi
::
set_next
(
out
,
*
c
);
}
::
pushmi
::
set_done
(
out
);
}));
}
PUSHMI_TEMPLATE
(
class
R
)
(
requires
requires
(
std
::
begin
(
std
::
declval
<
R
&&>
()),
std
::
end
(
std
::
declval
<
R
&&>
())
))
auto
from
(
R
&&
range
)
{
return
from
(
std
::
begin
(
range
),
std
::
end
(
range
));
}
}
// namespace operators
}
// namespace pushmi
folly/experimental/pushmi/include/pushmi/o/transform.h
View file @
0f0583e4
...
@@ -7,6 +7,7 @@
...
@@ -7,6 +7,7 @@
// LICENSE file in the root directory of this source tree.
// LICENSE file in the root directory of this source tree.
#include "../single.h"
#include "../single.h"
#include "../many.h"
#include "submit.h"
#include "submit.h"
#include "extension_operators.h"
#include "extension_operators.h"
...
@@ -14,13 +15,19 @@ namespace pushmi {
...
@@ -14,13 +15,19 @@ namespace pushmi {
namespace
detail
{
namespace
detail
{
// extracted this to workaround cuda compiler failure to compute the static_asserts in the nested lambda context
template
<
class
F
,
class
Tag
>
struct
transform_on
;
template
<
class
F
>
template
<
class
F
>
struct
transform_on
_value
{
struct
transform_on
<
F
,
is_single
<>>
{
F
f_
;
F
f_
;
transform_on
_value
()
=
default
;
transform_on
()
=
default
;
constexpr
explicit
transform_on
_value
(
F
f
)
constexpr
explicit
transform_on
(
F
f
)
:
f_
(
std
::
move
(
f
))
{}
:
f_
(
std
::
move
(
f
))
{}
template
<
class
Out
>
auto
operator
()(
Out
out
)
const
{
return
make_single
(
std
::
move
(
out
),
on_value
(
*
this
));
}
template
<
class
Out
,
class
V
>
template
<
class
Out
,
class
V
>
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
...
@@ -32,6 +39,27 @@ struct transform_on_value {
...
@@ -32,6 +39,27 @@ struct transform_on_value {
}
}
};
};
template
<
class
F
>
struct
transform_on
<
F
,
is_many
<>>
{
F
f_
;
transform_on
()
=
default
;
constexpr
explicit
transform_on
(
F
f
)
:
f_
(
std
::
move
(
f
))
{}
template
<
class
Out
>
auto
operator
()(
Out
out
)
const
{
return
make_many
(
std
::
move
(
out
),
on_next
(
*
this
));
}
template
<
class
Out
,
class
V
>
auto
operator
()(
Out
&
out
,
V
&&
v
)
{
using
Result
=
decltype
(
f_
((
V
&&
)
v
));
static_assert
(
::
pushmi
::
SemiMovable
<
Result
>
,
"none of the functions supplied to transform can convert this value"
);
static_assert
(
::
pushmi
::
ManyReceiver
<
Out
,
Result
>
,
"Result of value transform cannot be delivered to Out"
);
::
pushmi
::
set_next
(
out
,
f_
((
V
&&
)
v
));
}
};
struct
transform_fn
{
struct
transform_fn
{
template
<
class
...
FN
>
template
<
class
...
FN
>
auto
operator
()(
FN
...
fn
)
const
;
auto
operator
()(
FN
...
fn
)
const
;
...
@@ -44,28 +72,11 @@ auto transform_fn::operator()(FN... fn) const {
...
@@ -44,28 +72,11 @@ auto transform_fn::operator()(FN... fn) const {
using
In
=
decltype
(
in
);
using
In
=
decltype
(
in
);
// copy 'f' to allow multiple calls to connect to multiple 'in'
// copy 'f' to allow multiple calls to connect to multiple 'in'
using
F
=
decltype
(
f
);
using
F
=
decltype
(
f
);
return
::
pushmi
::
detail
::
deferred_from
<
In
,
::
pushmi
::
single
<>>
(
using
Cardinality
=
property_set_index_t
<
properties_t
<
In
>
,
is_silent
<>>
;
return
::
pushmi
::
detail
::
deferred_from
<
In
>
(
std
::
move
(
in
),
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
constrain
(
::
pushmi
::
lazy
::
Receiver
<::
pushmi
::
_1
>
,
[
f
](
auto
out
)
{
transform_on
<
F
,
Cardinality
>
{
f
}
using
Out
=
decltype
(
out
);
return
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
out
),
// copy 'f' to allow multiple calls to submit
::
pushmi
::
on_value
(
transform_on_value
<
F
>
(
f
)
// [f](Out& out, auto&& v) {
// using V = decltype(v);
// using Result = decltype(f((V&&) v));
// static_assert(::pushmi::SemiMovable<Result>,
// "none of the functions supplied to transform can convert this value");
// static_assert(::pushmi::SingleReceiver<Out, Result>,
// "Result of value transform cannot be delivered to Out");
// ::pushmi::set_value(out, f((V&&) v));
// }
)
);
})
)
)
);
);
});
});
...
...
folly/experimental/pushmi/test/CompileTest.cpp
View file @
0f0583e4
...
@@ -137,6 +137,58 @@ void single_test() {
...
@@ -137,6 +137,58 @@ void single_test() {
auto
any3
=
pushmi
::
any_single
<
int
>
(
proxy0
);
auto
any3
=
pushmi
::
any_single
<
int
>
(
proxy0
);
}
}
void
many_test
()
{
auto
out0
=
pushmi
::
MAKE
(
many
)();
auto
out1
=
pushmi
::
MAKE
(
many
)(
pushmi
::
ignoreNF
{});
auto
out2
=
pushmi
::
MAKE
(
many
)(
pushmi
::
ignoreNF
{},
pushmi
::
abortEF
{});
auto
out3
=
pushmi
::
MAKE
(
many
)(
pushmi
::
ignoreNF
{},
pushmi
::
abortEF
{},
pushmi
::
ignoreDF
{});
auto
out4
=
pushmi
::
MAKE
(
many
)([](
auto
v
)
{
v
.
get
();
});
auto
out5
=
pushmi
::
MAKE
(
many
)(
pushmi
::
on_next
([](
auto
v
)
{
v
.
get
();
},
[](
int
v
)
{}),
pushmi
::
on_error
(
[](
std
::
exception_ptr
e
)
noexcept
{},
[](
auto
e
)
noexcept
{
e
.
get
();
}
));
auto
out6
=
pushmi
::
MAKE
(
many
)(
pushmi
::
on_error
(
[](
std
::
exception_ptr
e
)
noexcept
{},
[](
auto
e
)
noexcept
{
e
.
get
();
}
));
auto
out7
=
pushmi
::
MAKE
(
many
)(
pushmi
::
on_done
([]()
{
}));
using
Out0
=
decltype
(
out0
);
auto
proxy0
=
pushmi
::
MAKE
(
many
)(
out0
);
auto
proxy1
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
passDNXF
{});
auto
proxy2
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
passDNXF
{},
pushmi
::
passDEF
{});
auto
proxy3
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
passDNXF
{},
pushmi
::
passDEF
{},
pushmi
::
passDDF
{});
auto
proxy4
=
pushmi
::
MAKE
(
many
)(
out0
,
[](
auto
d
,
auto
v
)
{
pushmi
::
set_next
(
d
,
v
.
get
());
});
auto
proxy5
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
on_next
([](
Out0
&
,
auto
v
)
{
v
.
get
();
},
[](
Out0
&
,
int
v
)
{}),
pushmi
::
on_error
(
[](
Out0
&
,
std
::
exception_ptr
e
)
noexcept
{},
[](
Out0
&
,
auto
e
)
noexcept
{
e
.
get
();
}
));
auto
proxy6
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
on_error
(
[](
Out0
&
,
std
::
exception_ptr
e
)
noexcept
{},
[](
Out0
&
,
auto
e
)
noexcept
{
e
.
get
();
}
));
auto
proxy7
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
on_done
([](
Out0
&
)
{
}));
auto
any0
=
pushmi
::
any_many
<
int
>
(
out0
);
auto
any1
=
pushmi
::
any_many
<
int
>
(
proxy0
);
}
void
single_deferred_test
(){
void
single_deferred_test
(){
auto
in0
=
pushmi
::
MAKE
(
single_deferred
)();
auto
in0
=
pushmi
::
MAKE
(
single_deferred
)();
auto
in1
=
pushmi
::
MAKE
(
single_deferred
)(
pushmi
::
ignoreSF
{});
auto
in1
=
pushmi
::
MAKE
(
single_deferred
)(
pushmi
::
ignoreSF
{});
...
@@ -159,6 +211,24 @@ void single_deferred_test(){
...
@@ -159,6 +211,24 @@ void single_deferred_test(){
auto
any0
=
pushmi
::
any_single_deferred
<
int
>
(
in0
);
auto
any0
=
pushmi
::
any_single_deferred
<
int
>
(
in0
);
}
}
void
many_deferred_test
(){
auto
in0
=
pushmi
::
MAKE
(
many_deferred
)();
auto
in1
=
pushmi
::
MAKE
(
many_deferred
)(
pushmi
::
ignoreSF
{});
auto
in3
=
pushmi
::
MAKE
(
many_deferred
)([
&
](
auto
out
){
in0
.
submit
(
pushmi
::
MAKE
(
many
)(
std
::
move
(
out
),
pushmi
::
on_next
([](
auto
d
,
int
v
){
pushmi
::
set_next
(
d
,
v
);
})
));
});
auto
out0
=
pushmi
::
MAKE
(
many
)();
auto
out1
=
pushmi
::
MAKE
(
many
)(
out0
,
pushmi
::
on_next
([](
auto
d
,
int
v
){
pushmi
::
set_next
(
d
,
v
);
}));
in3
.
submit
(
out1
);
auto
any0
=
pushmi
::
any_many_deferred
<
int
>
(
in0
);
}
void
time_single_deferred_test
(){
void
time_single_deferred_test
(){
auto
in0
=
pushmi
::
MAKE
(
time_single_deferred
)();
auto
in0
=
pushmi
::
MAKE
(
time_single_deferred
)();
auto
in1
=
pushmi
::
MAKE
(
time_single_deferred
)(
pushmi
::
ignoreSF
{});
auto
in1
=
pushmi
::
MAKE
(
time_single_deferred
)(
pushmi
::
ignoreSF
{});
...
...
folly/experimental/pushmi/test/PushmiTest.cpp
View file @
0f0583e4
...
@@ -7,6 +7,7 @@ using namespace std::literals;
...
@@ -7,6 +7,7 @@ using namespace std::literals;
#include "pushmi/flow_single_deferred.h"
#include "pushmi/flow_single_deferred.h"
#include "pushmi/o/empty.h"
#include "pushmi/o/empty.h"
#include "pushmi/o/from.h"
#include "pushmi/o/just.h"
#include "pushmi/o/just.h"
#include "pushmi/o/on.h"
#include "pushmi/o/on.h"
#include "pushmi/o/transform.h"
#include "pushmi/o/transform.h"
...
@@ -117,3 +118,35 @@ SCENARIO( "just() can be used with transform and submit", "[just][deferred]" ) {
...
@@ -117,3 +118,35 @@ SCENARIO( "just() can be used with transform and submit", "[just][deferred]" ) {
}
}
}
}
}
}
SCENARIO
(
"from() can be used with transform and submit"
,
"[from][deferred]"
)
{
GIVEN
(
"A from int many_deferred"
)
{
int
arr
[]
=
{
0
,
9
,
99
};
auto
m
=
op
::
from
(
arr
);
using
M
=
decltype
(
m
);
REQUIRE
(
v
::
SenderTo
<
M
,
v
::
any_many
<
int
>
,
v
::
is_many
<>>
);
WHEN
(
"transform and submit are applied"
)
{
int
signals
=
0
;
int
value
=
0
;
m
|
op
::
transform
(
[
&
](
int
v
){
signals
+=
10000
;
return
v
+
1
;
},
[
&
](
auto
v
){
std
:
abort
();
return
v
;
})
|
op
::
transform
(
[
&
](
int
v
){
signals
+=
10000
;
return
v
*
2
;
})
|
op
::
submit
(
[
&
](
auto
v
){
value
+=
v
;
signals
+=
100
;
},
[
&
](
auto
e
)
noexcept
{
signals
+=
1000
;
},
[
&
](){
signals
+=
10
;
});
THEN
(
"the transform signal is recorded twice, the value signal once and the result is correct"
)
{
REQUIRE
(
signals
==
60310
);
REQUIRE
(
value
==
222
);
}
}
}
}
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