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
38a4477a
Commit
38a4477a
authored
Oct 16, 2018
by
Eric Niebler
Committed by
Facebook Github Bot
Oct 17, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
more cleanup and concept-ification
fbshipit-source-id: 07e042879b008fbd34f583ae4351459bd5ae84a9
parent
f1bd6185
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
309 additions
and
490 deletions
+309
-490
folly/experimental/pushmi/include/pushmi/boosters.h
folly/experimental/pushmi/include/pushmi/boosters.h
+14
-61
folly/experimental/pushmi/include/pushmi/concepts.h
folly/experimental/pushmi/include/pushmi/concepts.h
+11
-30
folly/experimental/pushmi/include/pushmi/executor.h
folly/experimental/pushmi/include/pushmi/executor.h
+1
-1
folly/experimental/pushmi/include/pushmi/flow_single.h
folly/experimental/pushmi/include/pushmi/flow_single.h
+1
-3
folly/experimental/pushmi/include/pushmi/none.h
folly/experimental/pushmi/include/pushmi/none.h
+77
-91
folly/experimental/pushmi/include/pushmi/o/extension_operators.h
...xperimental/pushmi/include/pushmi/o/extension_operators.h
+40
-113
folly/experimental/pushmi/include/pushmi/o/on.h
folly/experimental/pushmi/include/pushmi/o/on.h
+1
-1
folly/experimental/pushmi/include/pushmi/o/submit.h
folly/experimental/pushmi/include/pushmi/o/submit.h
+9
-18
folly/experimental/pushmi/include/pushmi/o/tap.h
folly/experimental/pushmi/include/pushmi/o/tap.h
+20
-32
folly/experimental/pushmi/include/pushmi/o/transform.h
folly/experimental/pushmi/include/pushmi/o/transform.h
+5
-4
folly/experimental/pushmi/include/pushmi/o/via.h
folly/experimental/pushmi/include/pushmi/o/via.h
+4
-4
folly/experimental/pushmi/include/pushmi/piping.h
folly/experimental/pushmi/include/pushmi/piping.h
+6
-4
folly/experimental/pushmi/include/pushmi/single.h
folly/experimental/pushmi/include/pushmi/single.h
+115
-123
folly/experimental/pushmi/include/pushmi/traits.h
folly/experimental/pushmi/include/pushmi/traits.h
+5
-5
No files found.
folly/experimental/pushmi/include/pushmi/boosters.h
View file @
38a4477a
...
@@ -25,74 +25,27 @@ struct construct {
...
@@ -25,74 +25,27 @@ struct construct {
};
};
template
<
template
<
class
...
>
class
T
>
template
<
template
<
class
...
>
class
T
>
struct
construct_deduced
{
struct
construct_deduced
;
template
<
>
struct
construct_deduced
<
none
>
{
template
<
class
...
AN
>
template
<
class
...
AN
>
requires
requires
(
AN
&&
...
an
)
{
T
{(
AN
&&
)
an
...};
}
auto
operator
()(
AN
&&
...
an
)
const
->
decltype
(
none
{(
AN
&&
)
an
...})
{
auto
operator
()(
AN
&&
...
an
)
const
{
return
none
{(
AN
&&
)
an
...};
return
T
{
std
::
forward
<
AN
>
(
an
)...};
}
};
template
<
>
struct
construct_deduced
<
single
>
{
template
<
class
...
AN
>
auto
operator
()(
AN
&&
...
an
)
const
->
decltype
(
single
{(
AN
&&
)
an
...})
{
return
single
{(
AN
&&
)
an
...};
}
}
};
};
template
<
template
<
class
...
>
class
T
,
class
...
AN
>
template
<
template
<
class
...
>
class
T
,
class
...
AN
>
using
deduced_type_t
=
std
::
invoke_result_t
<
construct_deduced
<
T
>
,
AN
...
>
;
using
deduced_type_t
=
std
::
invoke_result_t
<
construct_deduced
<
T
>
,
AN
...
>
;
// template <class Fn>
// struct apply {
// template <class Tup>
// requires requires (Tup&& tup) { std::apply(Fn{}, (Tup&&) tup); }
// decltype(auto) operator()(Tup&& tup) const {
// return std::apply(Fn{}, (Tup&&) tup);
// }
// };
//
// template <class Fn, class Gn>
// struct compose {
// template <class... AN>
// requires Invocable<Gn, AN...> &&
// Invocable<Fn, std::invoke_result_t<Gn, AN...>>
// decltype(auto) operator()(AN&&... an) const {
// return std::invoke(Fn{}, std::invoke(Gn{}, (AN&&) an...));
// }
// };
//
// template <class T>
// inline constexpr apply<construct<T>> from_tuple {};
//
// template <template <class...> class T>
// inline constexpr apply<construct_deduced<T>> from_tuple_deduced {};
template
<
class
T
,
class
...
AN
>
auto
from_tuple
(
std
::
tuple
<
AN
...
>&&
t
)
{
return
std
::
apply
(
construct
<
T
>
{},
std
::
move
(
t
));
}
template
<
template
<
class
...
>
class
T
,
class
...
AN
>
auto
from_tuple
(
std
::
tuple
<
AN
...
>&&
t
)
{
using
Deduced
=
decltype
(
T
{
std
::
declval
<
AN
&&>
()...});
return
std
::
apply
(
construct
<
Deduced
>
{},
std
::
move
(
t
));
}
template
<
class
T
>
void
sfinae_from_tuple
(...);
template
<
template
<
class
...
TN
>
class
T
>
void
sfinae_from_tuple
(...);
template
<
class
T
,
class
...
AN
,
class
Constructor
=
construct
<
T
>
>
auto
sfinae_from_tuple
(
std
::
tuple
<
AN
...
>&&
t
)
->
decltype
(
std
::
apply
(
Constructor
{},
std
::
move
(
t
)))
{
return
std
::
apply
(
Constructor
{},
std
::
move
(
t
));
}
template
<
template
<
class
...
>
class
T
,
class
...
AN
,
class
Deduced
=
decltype
(
T
{
std
::
declval
<
AN
>
()...}),
class
Constructor
=
construct
<
Deduced
>
>
auto
sfinae_from_tuple
(
std
::
tuple
<
AN
...
>&&
t
)
->
decltype
(
std
::
apply
(
Constructor
{},
std
::
move
(
t
)))
{
return
std
::
apply
(
Constructor
{},
std
::
move
(
t
));
}
struct
ignoreVF
{
struct
ignoreVF
{
template
<
class
V
>
template
<
class
V
>
void
operator
()(
V
&&
)
{}
void
operator
()(
V
&&
)
{}
...
...
folly/experimental/pushmi/include/pushmi/concepts.h
View file @
38a4477a
...
@@ -16,20 +16,6 @@ struct none_tag : silent_tag {};
...
@@ -16,20 +16,6 @@ struct none_tag : silent_tag {};
struct
single_tag
:
none_tag
{};
struct
single_tag
:
none_tag
{};
struct
flow_tag
:
single_tag
{};
struct
flow_tag
:
single_tag
{};
template
<
class
Tag
>
concept
bool
Silent
=
Derived
<
Tag
,
silent_tag
>
;
template
<
class
Tag
>
concept
bool
None
=
Silent
<
Tag
>
&&
Derived
<
Tag
,
none_tag
>
;
template
<
class
Tag
>
concept
bool
Single
=
None
<
Tag
>
&&
Derived
<
Tag
,
single_tag
>
;
template
<
class
Tag
>
concept
bool
Flow
=
Single
<
Tag
>
&&
Derived
<
Tag
,
flow_tag
>
;
template
<
class
T
>
template
<
class
T
>
using
__sender_category_t
=
typename
T
::
sender_category
;
using
__sender_category_t
=
typename
T
::
sender_category
;
...
@@ -69,8 +55,8 @@ using receiver_category_t = __receiver_category_t<receiver_traits<T>>;
...
@@ -69,8 +55,8 @@ using receiver_category_t = __receiver_category_t<receiver_traits<T>>;
////////////////////////////////////////////////////////////////////////////////
// Receiver concepts
template
<
class
S
,
class
Tag
=
silent_tag
>
template
<
class
S
,
class
Tag
=
silent_tag
>
concept
bool
Receiver
=
Valid
<
receiver_traits
<
S
>
,
__receiver_category_t
>
&&
concept
bool
Receiver
=
Valid
<
receiver_traits
<
S
>
,
__receiver_category_t
>
&&
Derived
<
receiver_category_t
<
S
>
,
Tag
>
&&
Derived
<
receiver_category_t
<
S
>
,
Tag
>
&&
...
@@ -93,11 +79,8 @@ concept bool SingleReceiver = NoneReceiver<S, E> &&
...
@@ -93,11 +79,8 @@ concept bool SingleReceiver = NoneReceiver<S, E> &&
};
};
////////////////////////////////////////////////////////////////////////////////
// Sender concepts
template
<
class
D
,
class
Tag
=
silent_tag
>
template
<
class
D
,
class
Tag
=
silent_tag
>
concept
bool
Sender
=
Valid
<
sender_traits
<
D
>
,
__sender_category_t
>
&&
concept
bool
Sender
=
Valid
<
sender_traits
<
D
>
,
__sender_category_t
>
&&
Derived
<
sender_category_t
<
D
>
,
Tag
>
&&
SemiMovable
<
D
>
;
Derived
<
sender_category_t
<
D
>
,
Tag
>
&&
SemiMovable
<
D
>
;
...
@@ -110,24 +93,22 @@ concept bool SenderTo = Sender<D, Tag> &&
...
@@ -110,24 +93,22 @@ concept bool SenderTo = Sender<D, Tag> &&
};
};
////////////////////////////////////////////////////////////////////////////////
// TimeSender concepts
template
<
class
D
,
class
Tag
=
silent_tag
>
template
<
class
D
,
class
Tag
=
silent_tag
>
concept
bool
TimeSender
=
Sender
<
D
,
Tag
>
&&
requires
(
D
&
d
)
{
concept
bool
TimeSender
=
Sender
<
D
,
Tag
>
&&
requires
(
D
&
d
)
{
{
::
pushmi
::
now
(
d
)
}
->
Regular
{
::
pushmi
::
now
(
d
)
}
->
Regular
};
};
template
<
TimeSender
D
>
using
time_point_t
=
decltype
(
::
pushmi
::
now
(
std
::
declval
<
D
&>
()));
template
<
class
D
,
class
S
,
class
Tag
=
silent_tag
>
template
<
class
D
,
class
S
,
class
Tag
=
silent_tag
>
concept
bool
TimeSenderTo
=
Receiver
<
S
,
Tag
>
&&
TimeSender
<
D
,
Tag
>
&&
concept
bool
TimeSenderTo
=
Receiver
<
S
,
Tag
>
&&
TimeSender
<
D
,
Tag
>
&&
requires
(
D
&
d
,
S
&&
s
)
{
requires
(
D
&
d
,
S
&&
s
,
time_point_t
<
D
>
tp
)
{
::
pushmi
::
submit
(
d
,
::
pushmi
::
now
(
d
)
,
(
S
&&
)
s
);
::
pushmi
::
submit
(
d
,
tp
,
(
S
&&
)
s
);
};
};
template
<
TimeSender
D
>
using
time_point_t
=
decltype
(
::
pushmi
::
now
(
std
::
declval
<
D
&>
()));
// // this is a more general form where C (Constraint) could be time or priority
// // this is a more general form where C (Constraint) could be time or priority
// // enum or any other ordering constraint value-type.
// // enum or any other ordering constraint value-type.
...
...
folly/experimental/pushmi/include/pushmi/executor.h
View file @
38a4477a
...
@@ -73,7 +73,7 @@ public:
...
@@ -73,7 +73,7 @@ public:
// ask whether T'& is convertible to T. That brings us right back to this
// ask whether T'& is convertible to T. That brings us right back to this
// constructor. Constraint recursion!
// constructor. Constraint recursion!
static_assert
(
TimeSenderTo
<
W
,
single
<
Other
,
E
>>
);
static_assert
(
TimeSenderTo
<
W
,
single
<
Other
,
E
>>
);
if
constexpr
((
bool
)
TimeSenderTo
<
W
,
single
<
Other
,
E
>>
)
{
if
constexpr
((
bool
)
TimeSenderTo
<
W
,
single
<
Other
,
E
>>
)
{
pobj_
=
std
::
addressof
(
w
);
pobj_
=
std
::
addressof
(
w
);
vptr_
=
detail
::
any_time_executor_ref_vtable_v
<
E
,
TP
,
Other
,
Wrapped
>
();
vptr_
=
detail
::
any_time_executor_ref_vtable_v
<
E
,
TP
,
Other
,
Wrapped
>
();
}
}
...
...
folly/experimental/pushmi/include/pushmi/flow_single.h
View file @
38a4477a
...
@@ -279,9 +279,7 @@ class flow_single<>
...
@@ -279,9 +279,7 @@ class flow_single<>
:
public
flow_single
<
ignoreVF
,
abortEF
,
ignoreDF
,
ignoreStpF
,
ignoreStrtF
>
{
:
public
flow_single
<
ignoreVF
,
abortEF
,
ignoreDF
,
ignoreStpF
,
ignoreStrtF
>
{
};
};
using
archetype_flow_single
=
flow_single
<>
;
flow_single
()
->
flow_single
<>
;
flow_single
()
->
archetype_flow_single
;
template
<
class
VF
>
template
<
class
VF
>
requires
!
Receiver
<
VF
>
&&
!
detail
::
is_v
<
VF
,
on_error
>
&&
requires
!
Receiver
<
VF
>
&&
!
detail
::
is_v
<
VF
,
on_error
>
&&
...
...
folly/experimental/pushmi/include/pushmi/none.h
View file @
38a4477a
...
@@ -20,9 +20,8 @@ class none<E> {
...
@@ -20,9 +20,8 @@ class none<E> {
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
std
::
is_nothrow_move_constructible_v
<
Wrapped
>
;
std
::
is_nothrow_move_constructible_v
<
Wrapped
>
;
}
}
enum
struct
op
{
destroy
,
move
};
struct
vtable
{
struct
vtable
{
void
(
*
op_
)(
op
,
data
&
,
data
*
)
=
+
[](
op
,
data
&
,
data
*
)
{};
void
(
*
op_
)(
data
&
,
data
*
)
=
+
[](
data
&
,
data
*
)
{};
void
(
*
done_
)(
data
&
)
=
+
[](
data
&
)
{};
void
(
*
done_
)(
data
&
)
=
+
[](
data
&
)
{};
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
+
[](
data
&
,
E
)
noexcept
{
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
+
[](
data
&
,
E
)
noexcept
{
std
::
terminate
();
std
::
terminate
();
...
@@ -31,13 +30,10 @@ class none<E> {
...
@@ -31,13 +30,10 @@ class none<E> {
}
const
*
vptr_
=
&
vtable
::
noop_
;
}
const
*
vptr_
=
&
vtable
::
noop_
;
template
<
class
Wrapped
,
bool
=
insitu
<
Wrapped
>()
>
template
<
class
Wrapped
,
bool
=
insitu
<
Wrapped
>()
>
static
constexpr
vtable
const
vtable_v
=
{
static
constexpr
vtable
const
vtable_v
=
{
+
[](
op
o
,
data
&
src
,
data
*
dst
)
{
+
[](
data
&
src
,
data
*
dst
)
{
switch
(
o
)
{
if
(
dst
)
case
op
:
:
move
:
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
case
op
:
:
destroy
:
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
},
},
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
},
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
},
+
[](
data
&
src
,
E
e
)
noexcept
{
+
[](
data
&
src
,
E
e
)
noexcept
{
...
@@ -52,7 +48,7 @@ public:
...
@@ -52,7 +48,7 @@ public:
none
()
=
default
;
none
()
=
default
;
none
(
none
&&
that
)
noexcept
:
none
()
{
none
(
none
&&
that
)
noexcept
:
none
()
{
that
.
vptr_
->
op_
(
op
::
move
,
that
.
data_
,
&
data_
);
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
}
template
<
class
Wrapped
>
template
<
class
Wrapped
>
...
@@ -65,7 +61,7 @@ public:
...
@@ -65,7 +61,7 @@ public:
vptr_
=
&
vtable_v
<
Wrapped
>
;
vptr_
=
&
vtable_v
<
Wrapped
>
;
}
}
~
none
()
{
~
none
()
{
vptr_
->
op_
(
op
::
destroy
,
data_
,
nullptr
);
vptr_
->
op_
(
data_
,
nullptr
);
}
}
none
&
operator
=
(
none
&&
that
)
noexcept
{
none
&
operator
=
(
none
&&
that
)
noexcept
{
this
->~
none
();
this
->~
none
();
...
@@ -93,14 +89,11 @@ constexpr typename none<E>::vtable const none<E>::vtable_v;
...
@@ -93,14 +89,11 @@ constexpr typename none<E>::vtable const none<E>::vtable_v;
template
<
class
E
>
template
<
class
E
>
template
<
class
Wrapped
>
template
<
class
Wrapped
>
constexpr
typename
none
<
E
>::
vtable
const
none
<
E
>::
vtable_v
<
Wrapped
,
true
>
=
{
constexpr
typename
none
<
E
>::
vtable
const
none
<
E
>::
vtable_v
<
Wrapped
,
true
>
=
{
+
[](
op
o
,
data
&
src
,
data
*
dst
)
{
+
[](
data
&
src
,
data
*
dst
)
{
switch
(
o
)
{
if
(
dst
)
case
op
:
:
move
:
new
(
dst
->
buffer_
)
new
(
dst
->
buffer_
)
Wrapped
(
std
::
move
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
)));
Wrapped
(
std
::
move
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
)));
case
op
:
:
destroy
:
static_cast
<
Wrapped
const
*>
((
void
*
)
src
.
buffer_
)
->~
Wrapped
();
static_cast
<
Wrapped
const
*>
((
void
*
)
src
.
buffer_
)
->~
Wrapped
();
}
},
},
+
[](
data
&
src
)
{
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
...
@@ -108,18 +101,18 @@ constexpr typename none<E>::vtable const none<E>::vtable_v<Wrapped, true> = {
...
@@ -108,18 +101,18 @@ constexpr typename none<E>::vtable const none<E>::vtable_v<Wrapped, true> = {
+
[](
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
+
[](
data
&
src
,
E
e
)
noexcept
{
::
pushmi
::
set_error
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
),
std
::
move
(
e
));
std
::
move
(
e
));
}
}
}
};
;
template
<
class
EF
,
class
DF
>
template
<
class
EF
,
class
DF
>
requires
Invocable
<
DF
&>
&&
!
detail
::
is_v
<
EF
,
on_value
>
&&
!
detail
::
is_v
<
EF
,
single
>
requires
Invocable
<
DF
&
>
class
none
<
EF
,
DF
>
{
class
none
<
EF
,
DF
>
{
static_assert
(
!
detail
::
is_v
<
EF
,
on_value
>
&&
!
detail
::
is_v
<
EF
,
single
>
);
bool
done_
=
false
;
bool
done_
=
false
;
EF
ef_
;
EF
ef_
{}
;
DF
df_
;
DF
df_
{}
;
public:
public:
using
receiver_category
=
none_tag
;
using
receiver_category
=
none_tag
;
// static_assert(
// static_assert(
...
@@ -137,27 +130,32 @@ class none<EF, DF> {
...
@@ -137,27 +130,32 @@ class none<EF, DF> {
template
<
class
E
>
template
<
class
E
>
requires
Invocable
<
EF
&
,
E
>
requires
Invocable
<
EF
&
,
E
>
void
error
(
E
e
)
noexcept
{
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
EF
&
,
E
>
,
"error function must be noexcept"
);
static_assert
(
if
(
done_
)
{
return
;}
noexcept
(
ef_
(
std
::
move
(
e
))),
"error function must be noexcept"
);
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
ef_
(
e
);
ef_
(
std
::
move
(
e
));
}
}
}
void
done
()
{
void
done
()
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
df_
();
df_
();
}
}
}
};
};
template
<
Receiver
Data
,
class
DEF
,
class
DDF
>
template
<
Receiver
<
none_tag
>
Data
,
class
DEF
,
class
DDF
>
requires
Invocable
<
DDF
&
,
Data
&>
&&
!
detail
::
is_v
<
DEF
,
on_value
>
&&
!
detail
::
is_v
<
Data
,
single
>
requires
Invocable
<
DDF
&
,
Data
&
>
class
none
<
Data
,
DEF
,
DDF
>
{
class
none
<
Data
,
DEF
,
DDF
>
{
bool
done_
=
false
;
bool
done_
=
false
;
Data
data_
;
Data
data_
{};
DEF
ef_
;
DEF
ef_
{};
DDF
df_
;
DDF
df_
{};
static_assert
(
!
detail
::
is_v
<
DEF
,
on_value
>
);
public:
static_assert
(
!
detail
::
is_v
<
Data
,
single
>
);
public:
using
receiver_category
=
none_tag
;
using
receiver_category
=
none_tag
;
// static_assert(
// static_assert(
...
@@ -168,71 +166,59 @@ class none<Data, DEF, DDF> {
...
@@ -168,71 +166,59 @@ class none<Data, DEF, DDF> {
constexpr
none
(
Data
d
,
DDF
df
)
constexpr
none
(
Data
d
,
DDF
df
)
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
ef_
(),
df_
(
std
::
move
(
df
))
{}
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
ef_
(),
df_
(
std
::
move
(
df
))
{}
constexpr
none
(
Data
d
,
DEF
ef
,
DDF
df
=
DDF
{})
constexpr
none
(
Data
d
,
DEF
ef
,
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
template
<
class
E
>
template
<
class
E
>
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
void
error
(
E
e
)
noexcept
{
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
void
error
(
E
e
)
noexcept
{
static_assert
(
static_assert
(
NothrowInvocable
<
DEF
&
,
Data
&
,
E
>
,
"error function must be noexcept"
);
noexcept
(
ef_
(
data_
,
std
::
move
(
e
)))
,
"error function must be noexcept"
);
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
ef_
(
data_
,
e
);
ef_
(
data_
,
std
::
move
(
e
));
}
}
}
void
done
()
{
void
done
()
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
df_
(
data_
);
df_
(
data_
);
}
}
}
};
};
template
<
>
class
none
<>
:
public
none
<
abortEF
,
ignoreDF
>
{};
template
<
>
class
none
<>
using
archetype_none
=
none
<>
;
:
public
none
<
abortEF
,
ignoreDF
>
{
};
none
()
->
archetype_none
;
none
()
->
none
<>
;
template
<
class
EF
>
template
<
class
EF
>
requires
!
Receiver
<
EF
>
&&
none
(
EF
)
->
none
<
EF
,
ignoreDF
>
;
!
detail
::
is_v
<
EF
,
single
>
&&
!
detail
::
is_v
<
EF
,
on_value
>
&&
!
detail
::
is_v
<
EF
,
on_done
>
none
(
EF
)
->
none
<
EF
,
ignoreDF
>
;
template
<
class
DF
>
template
<
class
DF
>
requires
!
Receiver
<
DF
>
&&
requires
Invocable
<
DF
&>
!
detail
::
is_v
<
DF
,
on_value
>
&&
none
(
DF
)
->
none
<
abortEF
,
DF
>
;
!
detail
::
is_v
<
DF
,
single
>
none
(
on_done
<
DF
>
)
->
none
<
abortEF
,
on_done
<
DF
>>
;
template
<
class
E
,
class
Wrapped
>
requires
NoneReceiver
<
Wrapped
,
E
>
&&
!
detail
::
is_v
<
E
,
on_value
>
&&
!
detail
::
is_v
<
Wrapped
,
single
>
none
(
Wrapped
)
->
none
<
E
>
;
template
<
class
EF
,
class
DF
>
template
<
class
EF
,
class
DF
>
requires
Invocable
<
DF
&>
none
(
EF
,
DF
)
->
none
<
EF
,
DF
>
;
requires
Invocable
<
DF
&>
none
(
EF
,
DF
)
->
none
<
EF
,
DF
>
;
template
<
Receiver
Data
>
template
<
Receiver
<
none_tag
>
Data
>
requires
!
detail
::
is_v
<
Data
,
on_value
>
&&
requires
!
Receiver
<
Data
,
single_tag
>
!
detail
::
is_v
<
Data
,
single
>
none
(
Data
)
->
none
<
Data
,
passDEF
,
passDDF
>
;
none
(
Data
)
->
none
<
Data
,
passDEF
,
passDDF
>
;
template
<
Receiver
Data
,
class
DEF
>
template
<
Receiver
<
none_tag
>
Data
,
class
DEF
>
requires
!
detail
::
is_v
<
DEF
,
on_done
>
&&
requires
!
Receiver
<
Data
,
single_tag
>
!
detail
::
is_v
<
Data
,
on_value
>
&&
none
(
Data
,
DEF
)
->
none
<
Data
,
DEF
,
passDDF
>
;
!
detail
::
is_v
<
Data
,
single
>
none
(
Data
,
DEF
)
->
none
<
Data
,
DEF
,
passDDF
>
;
template
<
Receiver
Data
,
class
DDF
>
template
<
Receiver
<
none_tag
>
Data
,
class
DDF
>
requires
!
detail
::
is_v
<
Data
,
on_value
>
&&
requires
Invocable
<
DDF
&
,
Data
&>
&&
!
Receiver
<
Data
,
single_tag
>
!
detail
::
is_v
<
Data
,
single
>
none
(
Data
,
DDF
)
->
none
<
Data
,
passDEF
,
DDF
>
;
none
(
Data
,
on_done
<
DDF
>
)
->
none
<
Data
,
passDEF
,
on_done
<
DDF
>>
;
template
<
Receiver
Data
,
class
DEF
,
class
DDF
>
template
<
Receiver
<
none_tag
>
Data
,
class
DEF
,
class
DDF
>
requires
Invocable
<
DDF
&
,
Data
&>
&&
requires
!
Receiver
<
Data
,
single_tag
>
!
detail
::
is_v
<
Data
,
on_value
>
&&
none
(
Data
,
DEF
,
DDF
)
->
none
<
Data
,
DEF
,
DDF
>
;
!
detail
::
is_v
<
Data
,
single
>
none
(
Data
,
DEF
,
DDF
)
->
none
<
Data
,
DEF
,
DDF
>
;
template
<
class
E
=
std
::
exception_ptr
>
template
<
class
E
=
std
::
exception_ptr
>
using
any_none
=
none
<
E
>
;
using
any_none
=
none
<
E
>
;
...
@@ -251,12 +237,12 @@ using any_none = none<E>;
...
@@ -251,12 +237,12 @@ using any_none = none<E>;
// return none<E>{std::move(w)};
// return none<E>{std::move(w)};
// }
// }
template
<
SenderTo
<
std
::
promise
<
void
>,
none_tag
>
S
>
template
<
SenderTo
<
std
::
promise
<
void
>,
none_tag
>
Out
>
std
::
future
<
void
>
future_from
(
S
sender
)
{
std
::
future
<
void
>
future_from
(
Out
out
)
{
std
::
promise
<
void
>
p
;
std
::
promise
<
void
>
p
;
auto
result
=
p
.
get_future
();
auto
result
=
p
.
get_future
();
submit
(
sender
,
std
::
move
(
p
));
submit
(
out
,
std
::
move
(
p
));
return
result
;
return
result
;
}
}
}
// namespace
values
}
// namespace
pushmi
folly/experimental/pushmi/include/pushmi/o/extension_operators.h
View file @
38a4477a
...
@@ -14,108 +14,35 @@ namespace pushmi {
...
@@ -14,108 +14,35 @@ namespace pushmi {
namespace
detail
{
namespace
detail
{
// template <Sender In>
template
<
class
Tag
>
// struct out_from_fn {
struct
make_receiver
;
//
template
<
>
// };
struct
make_receiver
<
none_tag
>
:
construct_deduced
<
none
>
{};
template
<
>
struct
make_receiver
<
single_tag
>
:
construct_deduced
<
single
>
{};
template
<
Sender
In
>
struct
out_from_fn
{
template
<
Sender
In
,
class
...
AN
>
using
Make
=
make_receiver
<
sender_category_t
<
In
>>
;
auto
out_from
(
std
::
tuple
<
AN
...
>&&
args
)
{
template
<
class
...
Ts
>
using
SingleReceiver
=
requires
Invocable
<
Make
,
Ts
...
>
decltype
(
pushmi
::
sfinae_from_tuple
<
single
>
(
std
::
move
(
args
)));
auto
operator
()(
std
::
tuple
<
Ts
...
>
args
)
const
{
using
NoneReceiver
=
return
std
::
apply
(
Make
(),
std
::
move
(
args
));
decltype
(
pushmi
::
sfinae_from_tuple
<
none
>
(
std
::
move
(
args
)));
}
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
SingleReceiver
,
single_tag
>
||
template
<
class
...
Ts
,
class
...
Fns
,
SenderTo
<
In
,
SingleReceiver
,
single_tag
>
)
{
class
This
=
std
::
enable_if_t
<
sizeof
...(
Fns
)
!=
0
,
out_from_fn
>
>
return
pushmi
::
from_tuple
<
single
>
(
std
::
move
(
args
));
requires
(
SemiMovable
<
Fns
>
&&
...)
&&
}
else
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
NoneReceiver
,
none_tag
>
||
Invocable
<
Make
,
std
::
tuple
<
Ts
...
>>
&&
SenderTo
<
In
,
NoneReceiver
,
none_tag
>
)
{
Invocable
<
This
,
std
::
invoke_result_t
<
Make
,
std
::
tuple
<
Ts
...
>>
,
Fns
...
>
return
pushmi
::
from_tuple
<
none
>
(
std
::
move
(
args
));
auto
operator
()(
std
::
tuple
<
Ts
...
>
args
,
Fns
...
fns
)
const
{
}
return
This
()(
This
()(
std
::
move
(
args
)),
std
::
move
(
fns
)...);
}
}
template
<
Receiver
<
sender_category_t
<
In
>
>
Out
,
class
...
Fns
>
template
<
Sender
In
,
class
...
AN
,
class
...
DVFN
,
class
...
DEFN
,
class
...
DDFN
>
requires
(
SemiMovable
<
Fns
>
&&
...)
auto
out_from
(
auto
operator
()(
Out
out
,
Fns
...
fns
)
const
{
std
::
tuple
<
AN
...
>&&
args
,
return
Make
()(
std
::
move
(
out
),
std
::
move
(
fns
)...);
on_value
<
DVFN
...
>
vf
,
on_error
<
DEFN
...
>
ef
,
on_done
<
DDFN
...
>
df
)
{
auto
out
=
out_from
<
In
>
(
std
::
move
(
args
));
if
constexpr
(
::
pushmi
::
detail
::
is_v
<
decltype
(
out
),
single
>
)
{
return
single
{
std
::
move
(
out
),
std
::
move
(
vf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
else
if
constexpr
(
::
pushmi
::
detail
::
is_v
<
decltype
(
out
),
none
>
)
{
return
none
{
std
::
move
(
out
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
}
template
<
Sender
In
,
Receiver
Out
,
class
...
DVFN
,
class
...
DEFN
,
class
...
DDFN
>
auto
out_from
(
Out
&&
out
,
on_value
<
DVFN
...
>
vf
,
on_error
<
DEFN
...
>
ef
,
on_done
<
DDFN
...
>
df
)
{
using
SingleReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
single
>
(
std
::
tuple
{
std
::
move
(
out
)}));
using
NoneReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
none
>
(
std
::
tuple
{
std
::
move
(
out
)}));
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
SingleReceiver
,
single_tag
>
||
SenderTo
<
In
,
SingleReceiver
,
single_tag
>
)
{
return
single
{
std
::
move
(
out
),
std
::
move
(
vf
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
else
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
NoneReceiver
,
none_tag
>
||
SenderTo
<
In
,
NoneReceiver
,
none_tag
>
)
{
return
none
{
std
::
move
(
out
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
}
template
<
Sender
In
,
Receiver
Out
,
class
...
DEFN
,
class
...
DDFN
>
auto
out_from
(
Out
&&
out
,
on_error
<
DEFN
...
>
ef
,
on_done
<
DDFN
...
>
df
)
{
using
SingleReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
single
>
(
std
::
tuple
{
std
::
move
(
out
)}));
using
NoneReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
none
>
(
std
::
tuple
{
std
::
move
(
out
)}));
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
SingleReceiver
,
single_tag
>
||
SenderTo
<
In
,
SingleReceiver
,
single_tag
>
)
{
return
single
{
std
::
move
(
out
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
else
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
NoneReceiver
,
none_tag
>
||
SenderTo
<
In
,
NoneReceiver
,
none_tag
>
)
{
return
none
{
std
::
move
(
out
),
std
::
move
(
ef
),
std
::
move
(
df
)};
}
}
}
};
template
<
Sender
In
,
Receiver
Out
,
class
...
DVFN
>
auto
out_from
(
Out
&&
out
,
on_value
<
DVFN
...
>
vf
)
{
using
SingleReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
single
>
(
std
::
tuple
{
std
::
move
(
out
)}));
using
NoneReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
none
>
(
std
::
tuple
{
std
::
move
(
out
)}));
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
SingleReceiver
,
single_tag
>
||
SenderTo
<
In
,
SingleReceiver
,
single_tag
>
)
{
return
single
{
std
::
move
(
out
),
std
::
move
(
vf
)};
}
else
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
NoneReceiver
,
none_tag
>
||
SenderTo
<
In
,
NoneReceiver
,
none_tag
>
)
{
return
none
{
std
::
move
(
out
)};
}
}
template
<
Sender
In
,
Receiver
Out
>
auto
out_from
(
Out
&&
out
)
{
using
SingleReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
single
>
(
std
::
tuple
{
std
::
move
(
out
)}));
using
NoneReceiver
=
decltype
(
pushmi
::
sfinae_from_tuple
<
none
>
(
std
::
tuple
{
std
::
move
(
out
)}));
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
SingleReceiver
,
single_tag
>
||
SenderTo
<
In
,
SingleReceiver
,
single_tag
>
)
{
return
single
{
std
::
move
(
out
)};
}
else
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
NoneReceiver
,
none_tag
>
||
SenderTo
<
In
,
NoneReceiver
,
none_tag
>
)
{
return
none
{
std
::
move
(
out
)};
}
}
template
<
Sender
In
,
class
FN
>
template
<
Sender
In
,
class
FN
>
auto
submit_transform_out
(
FN
fn
){
auto
submit_transform_out
(
FN
fn
){
...
@@ -151,7 +78,7 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf){
...
@@ -151,7 +78,7 @@ auto submit_transform_out(SDSF sdsf, TSDSF tsdsf){
}
}
}
}
template
<
Sender
In
,
class
Out
,
class
...
FN
>
template
<
Sender
In
,
Receiver
Out
,
class
...
FN
>
auto
deferred_from
(
FN
&&
...
fn
)
{
auto
deferred_from
(
FN
&&
...
fn
)
{
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
Out
,
single_tag
>
)
{
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
Out
,
single_tag
>
)
{
return
time_single_deferred
{(
FN
&&
)
fn
...};
return
time_single_deferred
{(
FN
&&
)
fn
...};
...
@@ -162,7 +89,7 @@ auto deferred_from(FN&&... fn) {
...
@@ -162,7 +89,7 @@ auto deferred_from(FN&&... fn) {
}
}
}
}
template
<
Sender
In
,
class
Out
,
class
...
FN
>
template
<
Sender
In
,
Receiver
Out
,
class
...
FN
>
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
auto
deferred_from
(
In
in
,
FN
&&
...
fn
)
{
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
Out
,
single_tag
>
)
{
if
constexpr
((
bool
)
TimeSenderTo
<
In
,
Out
,
single_tag
>
)
{
return
time_single_deferred
{
std
::
move
(
in
),
(
FN
&&
)
fn
...};
return
time_single_deferred
{
std
::
move
(
in
),
(
FN
&&
)
fn
...};
...
@@ -175,7 +102,7 @@ auto deferred_from(In in, FN&&... fn) {
...
@@ -175,7 +102,7 @@ auto deferred_from(In in, FN&&... fn) {
template
<
template
<
Sender
In
,
Sender
In
,
class
Out
,
Receiver
Out
,
bool
SenderRequires
,
bool
SenderRequires
,
bool
SingleSenderRequires
,
bool
SingleSenderRequires
,
bool
TimeSingleSenderRequires
>
bool
TimeSingleSenderRequires
>
...
@@ -201,7 +128,7 @@ struct set_value_fn {
...
@@ -201,7 +128,7 @@ struct set_value_fn {
return
[
v
=
(
V
&&
)
v
]
<
class
Out
>
(
Out
out
)
mutable
PUSHMI_VOID_LAMBDA_REQUIRES
(
Receiver
<
Out
>
)
{
return
[
v
=
(
V
&&
)
v
]
<
class
Out
>
(
Out
out
)
mutable
PUSHMI_VOID_LAMBDA_REQUIRES
(
Receiver
<
Out
>
)
{
::
pushmi
::
set_value
(
out
,
(
V
&&
)
v
);
::
pushmi
::
set_value
(
out
,
(
V
&&
)
v
);
};
};
}
}
};
};
struct
set_error_fn
{
struct
set_error_fn
{
...
@@ -238,7 +165,7 @@ struct set_starting_fn {
...
@@ -238,7 +165,7 @@ struct set_starting_fn {
}
}
};
};
struct
do_
submit_fn
{
struct
submit_fn
{
template
<
class
Out
>
template
<
class
Out
>
auto
operator
()(
Out
out
)
const
{
auto
operator
()(
Out
out
)
const
{
static_assert
(
Receiver
<
Out
>
,
"'Out' must be a model of Receiver"
);
static_assert
(
Receiver
<
Out
>
,
"'Out' must be a model of Receiver"
);
...
@@ -255,7 +182,7 @@ struct do_submit_fn {
...
@@ -255,7 +182,7 @@ struct do_submit_fn {
}
}
};
};
struct
get_
now_fn
{
struct
now_fn
{
auto
operator
()()
const
{
auto
operator
()()
const
{
return
[]
<
class
In
>
(
In
in
)
PUSHMI_T_LAMBDA_REQUIRES
(
decltype
(
::
pushmi
::
now
(
in
)),
TimeSender
<
In
>
)
{
return
[]
<
class
In
>
(
In
in
)
PUSHMI_T_LAMBDA_REQUIRES
(
decltype
(
::
pushmi
::
now
(
in
)),
TimeSender
<
In
>
)
{
return
::
pushmi
::
now
(
in
);
return
::
pushmi
::
now
(
in
);
...
@@ -270,9 +197,9 @@ inline constexpr detail::set_error_fn set_error{};
...
@@ -270,9 +197,9 @@ inline constexpr detail::set_error_fn set_error{};
inline
constexpr
detail
::
set_value_fn
set_value
{};
inline
constexpr
detail
::
set_value_fn
set_value
{};
inline
constexpr
detail
::
set_stopping_fn
set_stopping
{};
inline
constexpr
detail
::
set_stopping_fn
set_stopping
{};
inline
constexpr
detail
::
set_starting_fn
set_starting
{};
inline
constexpr
detail
::
set_starting_fn
set_starting
{};
inline
constexpr
detail
::
do_
submit_fn
submit
{};
inline
constexpr
detail
::
submit_fn
submit
{};
inline
constexpr
detail
::
get_
now_fn
now
{};
inline
constexpr
detail
::
now_fn
now
{};
inline
constexpr
detail
::
get_
now_fn
top
{};
inline
constexpr
detail
::
now_fn
top
{};
}
// namespace extension_operators
}
// namespace extension_operators
...
...
folly/experimental/pushmi/include/pushmi/o/on.h
View file @
38a4477a
...
@@ -22,7 +22,7 @@ struct on_fn {
...
@@ -22,7 +22,7 @@ struct on_fn {
template
<
class
ExecutorFactory
>
template
<
class
ExecutorFactory
>
auto
on_fn
::
operator
()(
ExecutorFactory
ef
)
const
{
auto
on_fn
::
operator
()(
ExecutorFactory
ef
)
const
{
return
[
ef
=
std
::
move
(
ef
)]
<
class
In
>
(
In
in
)
{
return
[
ef
=
std
::
move
(
ef
)]
<
class
In
>
(
In
in
)
{
return
::
pushmi
::
detail
::
deferred_from
<
In
,
archetype_single
>
(
return
::
pushmi
::
detail
::
deferred_from
<
In
,
single
<>
>
(
std
::
move
(
in
),
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
[
ef
]
<
class
Out
>
(
In
&
in
,
Out
out
)
{
[
ef
]
<
class
Out
>
(
In
&
in
,
Out
out
)
{
...
...
folly/experimental/pushmi/include/pushmi/o/submit.h
View file @
38a4477a
...
@@ -18,20 +18,11 @@ namespace operators {
...
@@ -18,20 +18,11 @@ namespace operators {
namespace
detail
{
namespace
detail
{
inline
constexpr
struct
make_receiver_fn
{
template
<
class
...
AN
>
deduced_type_t
<
none
,
AN
...
>
operator
()(
none_tag
,
AN
&&
...
an
)
const
{
return
none
{(
AN
&&
)
an
...};
}
template
<
class
...
AN
>
deduced_type_t
<
single
,
AN
...
>
operator
()(
single_tag
,
AN
&&
...
an
)
const
{
return
single
{(
AN
&&
)
an
...};
}
}
make_receiver
{};
template
<
Sender
In
,
class
...
AN
>
template
<
Sender
In
,
class
...
AN
>
using
receiver_type_t
=
using
receiver_type_t
=
std
::
invoke_result_t
<
make_receiver_fn
,
sender_category_t
<
In
>
,
AN
...
>
;
std
::
invoke_result_t
<
pushmi
::
detail
::
make_receiver
<
sender_category_t
<
In
>>
,
AN
...
>
;
template
<
class
In
,
class
...
AN
>
template
<
class
In
,
class
...
AN
>
concept
bool
AutoSenderTo
=
SenderTo
<
In
,
receiver_type_t
<
In
,
AN
...
>>
;
concept
bool
AutoSenderTo
=
SenderTo
<
In
,
receiver_type_t
<
In
,
AN
...
>>
;
...
@@ -49,13 +40,13 @@ private:
...
@@ -49,13 +40,13 @@ private:
std
::
tuple
<
AN
...
>
args_
;
std
::
tuple
<
AN
...
>
args_
;
template
<
AutoSenderTo
<
AN
...>
In
>
template
<
AutoSenderTo
<
AN
...>
In
>
In
operator
()(
In
in
)
{
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from
<
In
>
(
std
::
move
(
args_
))};
auto
out
{
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
return
in
;
return
in
;
}
}
template
<
AutoTimeSenderTo
<
AN
...>
In
>
template
<
AutoTimeSenderTo
<
AN
...>
In
>
In
operator
()(
In
in
)
{
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from
<
In
>
(
std
::
move
(
args_
))};
auto
out
{
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
::
pushmi
::
now
(
in
),
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
::
pushmi
::
now
(
in
),
std
::
move
(
out
));
return
in
;
return
in
;
}
}
...
@@ -75,7 +66,7 @@ private:
...
@@ -75,7 +66,7 @@ private:
std
::
tuple
<
AN
...
>
args_
;
std
::
tuple
<
AN
...
>
args_
;
template
<
AutoTimeSenderTo
<
AN
...>
In
>
template
<
AutoTimeSenderTo
<
AN
...>
In
>
In
operator
()(
In
in
)
{
In
operator
()(
In
in
)
{
auto
out
{
::
pushmi
::
detail
::
out_from
<
In
>
(
std
::
move
(
args_
))};
auto
out
{
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
args_
))};
::
pushmi
::
submit
(
in
,
std
::
move
(
at_
),
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
std
::
move
(
at_
),
std
::
move
(
out
));
return
in
;
return
in
;
}
}
...
@@ -98,7 +89,7 @@ private:
...
@@ -98,7 +89,7 @@ private:
// TODO - only move, move-only types..
// TODO - only move, move-only types..
// if out can be copied, then submit can be called multiple
// if out can be copied, then submit can be called multiple
// times..
// times..
auto
out
{
::
pushmi
::
detail
::
out_from
<
In
>
(
std
::
move
(
args_
))};
auto
out
{
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
args_
))};
auto
at
=
::
pushmi
::
now
(
in
)
+
std
::
move
(
after_
);
auto
at
=
::
pushmi
::
now
(
in
)
+
std
::
move
(
after_
);
::
pushmi
::
submit
(
in
,
std
::
move
(
at
),
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
std
::
move
(
at
),
std
::
move
(
out
));
return
in
;
return
in
;
...
@@ -124,7 +115,7 @@ private:
...
@@ -124,7 +115,7 @@ private:
In
impl_
(
In
in
)
{
In
impl_
(
In
in
)
{
bool
done
=
false
;
bool
done
=
false
;
std
::
condition_variable
signaled
;
std
::
condition_variable
signaled
;
auto
out
{
::
pushmi
::
detail
::
out_from
<
In
>
(
auto
out
{
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
args_
),
std
::
move
(
args_
),
on_value
{[
&
]
<
class
Out
,
class
V
>
(
Out
out
,
V
&&
v
){
on_value
{[
&
]
<
class
Out
,
class
V
>
(
Out
out
,
V
&&
v
){
if
constexpr
((
bool
)
TimeSender
<
std
::
remove_cvref_t
<
V
>>
)
{
if
constexpr
((
bool
)
TimeSender
<
std
::
remove_cvref_t
<
V
>>
)
{
...
@@ -150,7 +141,7 @@ private:
...
@@ -150,7 +141,7 @@ private:
signaled
.
notify_all
();
signaled
.
notify_all
();
}}
}}
)};
)};
if
constexpr
(
(
bool
)
IsTimeSender
)
{
if
constexpr
(
IsTimeSender
)
{
::
pushmi
::
submit
(
in
,
::
pushmi
::
now
(
in
),
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
::
pushmi
::
now
(
in
),
std
::
move
(
out
));
}
else
{
}
else
{
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
::
pushmi
::
submit
(
in
,
std
::
move
(
out
));
...
...
folly/experimental/pushmi/include/pushmi/o/tap.h
View file @
38a4477a
...
@@ -15,23 +15,26 @@ namespace pushmi {
...
@@ -15,23 +15,26 @@ namespace pushmi {
namespace
operators
{
namespace
operators
{
namespace
detail
{
namespace
detail
{
template
<
class
SideEffects
,
class
Out
>
template
<
Receiver
SideEffects
,
Receiver
Out
>
struct
tap_
{
struct
tap_
{
SideEffects
sideEffects
;
SideEffects
sideEffects
;
Out
out
;
Out
out
;
using
receiver_category
=
single_tag
;
using
side_effects_tag
=
receiver_category_t
<
SideEffects
>
;
using
out_tag
=
receiver_category_t
<
Out
>
;
using
receiver_category
=
std
::
common_type_t
<
side_effects_tag
,
out_tag
>
;
template
<
class
V
>
template
<
class
V
,
class
UV
=
std
::
remove_reference_t
<
V
>
>
requires
SingleReceiver
<
SideEffects
,
const
V
&>
&&
SingleReceiver
<
Out
,
V
>
requires
SingleReceiver
<
SideEffects
,
const
UV
&>
&&
SingleReceiver
<
Out
,
V
>
void
value
(
V
&&
v
)
{
void
value
(
V
&&
v
)
{
::
pushmi
::
set_value
(
sideEffects
,
const_cast
<
const
V
&>
(
v
));
::
pushmi
::
set_value
(
sideEffects
,
std
::
as_const
(
v
));
::
pushmi
::
set_value
(
out
,
(
V
&&
)
v
);
::
pushmi
::
set_value
(
out
,
(
V
&&
)
v
);
}
}
template
<
class
E
>
template
<
class
E
>
requires
NoneReceiver
<
SideEffects
,
E
>
&&
NoneReceiver
<
Out
,
E
>
requires
NoneReceiver
<
SideEffects
,
const
E
&>
&&
NoneReceiver
<
Out
,
E
>
void
error
(
E
e
)
noexcept
{
void
error
(
E
e
)
noexcept
{
::
pushmi
::
set_error
(
sideEffects
,
const_cast
<
const
E
&>
(
e
));
::
pushmi
::
set_error
(
sideEffects
,
std
::
as_const
(
e
));
::
pushmi
::
set_error
(
out
,
std
::
move
(
e
));
::
pushmi
::
set_error
(
out
,
std
::
move
(
e
));
}
}
void
done
()
{
void
done
()
{
...
@@ -41,29 +44,23 @@ struct tap_ {
...
@@ -41,29 +44,23 @@ struct tap_ {
};
};
template
<
Receiver
SideEffects
,
Receiver
Out
>
template
<
Receiver
SideEffects
,
Receiver
Out
>
tap_
(
SideEffects
,
Out
)
->
tap_
<
SideEffects
,
Out
>
;
tap_
(
SideEffects
,
Out
)
->
tap_
<
SideEffects
,
Out
>
;
struct
tap_fn
{
struct
tap_fn
{
template
<
class
...
AN
>
template
<
class
...
AN
>
auto
operator
()(
AN
...
an
)
const
;
auto
operator
()(
AN
...
an
)
const
;
};
};
template
<
class
...
AN
>
template
<
class
...
AN
>
auto
tap_fn
::
operator
()(
AN
...
an
)
const
{
auto
tap_fn
::
operator
()(
AN
...
an
)
const
{
auto
args
=
std
::
tuple
{
std
::
move
(
an
)...};
return
[
args
=
std
::
tuple
{
std
::
move
(
an
)...}]
<
class
In
>
(
In
in
)
mutable
{
return
[
args
=
std
::
move
(
args
)]
<
class
In
>
(
In
in
)
mutable
{
auto
sideEffects
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
std
::
move
(
args
))};
auto
sideEffects
{
::
pushmi
::
detail
::
out_from
<
In
>
(
std
::
move
(
args
))};
using
SideEffects
=
decltype
(
sideEffects
);
using
SideEffects
=
decltype
(
sideEffects
);
static_assert
(
static_assert
(
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
Receiver
<
SideEffects
>
&&
SenderTo
<
In
,
SideEffects
,
none_tag
>
,
SenderTo
<
In
,
SideEffects
>
,
Receiver
<
SideEffects
>
&&
SenderTo
<
In
,
SideEffects
,
single_tag
>
,
SenderTo
<
In
,
SideEffects
,
single_tag
>
,
Receiver
<
SideEffects
>
&&
TimeSenderTo
<
In
,
SideEffects
,
single_tag
>
>
(),
TimeSenderTo
<
In
,
SideEffects
,
single_tag
>
>
(),
"'In' is not deliverable to 'SideEffects'"
);
"'In' is not deliverable to 'SideEffects'"
);
...
@@ -73,26 +70,17 @@ auto tap_fn::operator()(AN... an) const {
...
@@ -73,26 +70,17 @@ auto tap_fn::operator()(AN... an) const {
[
sideEffects
=
std
::
move
(
sideEffects
)]
<
class
Out
>
(
Out
out
)
{
[
sideEffects
=
std
::
move
(
sideEffects
)]
<
class
Out
>
(
Out
out
)
{
static_assert
(
static_assert
(
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
Receiver
<
Out
>
&&
SenderTo
<
In
,
Out
,
none_tag
>
,
SenderTo
<
In
,
Out
>
,
Receiver
<
Out
>
&&
SenderTo
<
In
,
Out
,
single_tag
>
,
SenderTo
<
In
,
Out
,
single_tag
>
,
Receiver
<
Out
>
&&
TimeSenderTo
<
In
,
Out
,
single_tag
>
>
(),
TimeSenderTo
<
In
,
Out
,
single_tag
>
>
(),
"'In' is not deliverable to 'Out'"
);
"'In' is not deliverable to 'Out'"
);
auto
gang
{
::
pushmi
::
detail
::
out_from
<
In
>
(
detail
::
tap_
{
sideEffects
,
std
::
move
(
out
)})};
auto
gang
{
::
pushmi
::
detail
::
out_from_fn
<
In
>
()(
detail
::
tap_
{
sideEffects
,
std
::
move
(
out
)})};
using
Gang
=
decltype
(
gang
);
using
Gang
=
decltype
(
gang
);
static_assert
(
static_assert
(
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
::
pushmi
::
detail
::
deferred_requires_from
<
In
,
SideEffects
,
Receiver
<
Gang
>
&&
SenderTo
<
In
,
Gang
>
,
SenderTo
<
In
,
Gang
>
,
Receiver
<
Gang
>
&&
SenderTo
<
In
,
Gang
,
single_tag
>
,
SenderTo
<
In
,
Gang
,
single_tag
>
,
Receiver
<
Gang
>
&&
TimeSenderTo
<
In
,
Gang
,
single_tag
>
>
(),
TimeSenderTo
<
In
,
Gang
,
single_tag
>
>
(),
"'In' is not deliverable to 'Out' & 'SideEffects'"
);
"'In' is not deliverable to 'Out' & 'SideEffects'"
);
return
gang
;
return
gang
;
...
...
folly/experimental/pushmi/include/pushmi/o/transform.h
View file @
38a4477a
...
@@ -17,19 +17,20 @@ namespace operators {
...
@@ -17,19 +17,20 @@ namespace operators {
namespace
detail
{
namespace
detail
{
struct
transform_fn
{
struct
transform_fn
{
template
<
class
...
FN
>
template
<
class
...
FN
>
auto
operator
()(
FN
...
fn
)
const
;
auto
operator
()(
FN
...
fn
)
const
;
};
};
template
<
class
...
FN
>
template
<
class
...
FN
>
auto
transform_fn
::
operator
()(
FN
...
fn
)
const
{
auto
transform_fn
::
operator
()(
FN
...
fn
)
const
{
auto
f
=
overload
{
std
::
move
(
fn
)...};
auto
f
=
overload
{
std
::
move
(
fn
)...};
return
[
f
=
std
::
move
(
f
)]
<
class
In
>
(
In
in
)
{
return
[
f
=
std
::
move
(
f
)]
<
class
In
>
(
In
in
)
{
// copy 'f' to allow multiple calls to connect to multiple 'in'
// copy 'f' to allow multiple calls to connect to multiple 'in'
return
::
pushmi
::
detail
::
deferred_from
<
In
,
archetype_single
>
(
return
::
pushmi
::
detail
::
deferred_from
<
In
,
single
<>
>
(
std
::
move
(
in
),
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
[
f
]
<
class
Out
>
(
Out
out
)
{
[
f
]
<
class
Out
>
(
Out
out
)
{
return
::
pushmi
::
detail
::
out_from
<
In
>
(
return
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
std
::
move
(
out
),
std
::
move
(
out
),
// copy 'f' to allow multiple calls to submit
// copy 'f' to allow multiple calls to submit
on_value
{
on_value
{
...
...
folly/experimental/pushmi/include/pushmi/o/via.h
View file @
38a4477a
...
@@ -15,7 +15,7 @@ namespace operators {
...
@@ -15,7 +15,7 @@ namespace operators {
namespace
detail
{
namespace
detail
{
class
via_fn
{
class
via_fn
{
template
<
class
ExecutorFactory
>
template
<
Invocable
ExecutorFactory
>
auto
operator
()(
ExecutorFactory
ef
)
const
;
auto
operator
()(
ExecutorFactory
ef
)
const
;
};
};
...
@@ -30,15 +30,15 @@ struct via_fn_data : public Out {
...
@@ -30,15 +30,15 @@ struct via_fn_data : public Out {
template
<
class
Executor
,
class
Out
>
template
<
class
Executor
,
class
Out
>
via_fn_data
(
Out
,
Executor
)
->
via_fn_data
<
Executor
,
Out
>
;
via_fn_data
(
Out
,
Executor
)
->
via_fn_data
<
Executor
,
Out
>
;
template
<
class
ExecutorFactory
>
template
<
Invocable
ExecutorFactory
>
auto
via_fn
::
operator
()(
ExecutorFactory
ef
)
const
{
auto
via_fn
::
operator
()(
ExecutorFactory
ef
)
const
{
return
[
ef
=
std
::
move
(
ef
)]
<
class
In
>
(
In
in
)
{
return
[
ef
=
std
::
move
(
ef
)]
<
class
In
>
(
In
in
)
{
return
::
pushmi
::
detail
::
deferred_from
<
In
,
archetype_single
>
(
return
::
pushmi
::
detail
::
deferred_from
<
In
,
single
<>
>
(
std
::
move
(
in
),
std
::
move
(
in
),
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
::
pushmi
::
detail
::
submit_transform_out
<
In
>
(
[
ef
]
<
class
Out
>
(
Out
out
)
{
[
ef
]
<
class
Out
>
(
Out
out
)
{
auto
exec
=
ef
();
auto
exec
=
ef
();
return
::
pushmi
::
detail
::
out_from
<
In
>
(
return
::
pushmi
::
detail
::
out_from
_fn
<
In
>
()
(
via_fn_data
{
std
::
move
(
out
),
std
::
move
(
exec
)},
via_fn_data
{
std
::
move
(
out
),
std
::
move
(
exec
)},
// copy 'f' to allow multiple calls to submit
// copy 'f' to allow multiple calls to submit
::
pushmi
::
on_value
{[]
<
class
V
>
(
auto
&
data
,
V
&&
v
){
::
pushmi
::
on_value
{[]
<
class
V
>
(
auto
&
data
,
V
&&
v
){
...
...
folly/experimental/pushmi/include/pushmi/piping.h
View file @
38a4477a
...
@@ -4,15 +4,17 @@
...
@@ -4,15 +4,17 @@
// 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.
template
<
class
In
,
class
Operator
>
#include "traits.h"
auto
operator
|
(
In
&&
in
,
Operator
op
)
->
decltype
(
op
(
std
::
forward
<
In
>
(
in
)))
{
return
op
(
std
::
forward
<
In
>
(
in
));
template
<
class
In
,
pushmi
::
Invocable
<
In
>
Op
>
decltype
(
auto
)
operator
|
(
In
&&
in
,
Op
op
)
{
return
op
((
In
&&
)
in
);
}
}
namespace
pushmi
{
namespace
pushmi
{
template
<
class
T
,
class
...
FN
>
template
<
class
T
,
class
...
FN
>
auto
pipe
(
T
t
,
FN
...
fn
)
{
auto
pipe
(
T
t
,
FN
...
fn
)
->
decltype
((
t
|
...
|
fn
))
{
return
(
t
|
...
|
fn
);
return
(
t
|
...
|
fn
);
}
}
...
...
folly/experimental/pushmi/include/pushmi/single.h
View file @
38a4477a
...
@@ -4,15 +4,16 @@
...
@@ -4,15 +4,16 @@
// 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"
#include "none.h"
namespace
pushmi
{
namespace
pushmi
{
namespace
detail
{
namespace
detail
{
template
<
class
data
,
class
op
,
class
V
,
class
E
>
template
<
class
data
,
class
V
,
class
E
>
struct
single_vtable
{
struct
single_vtable
{
void
(
*
op_
)(
op
,
data
&
,
data
*
)
=
+
[](
op
,
data
&
,
data
*
)
{};
void
(
*
op_
)(
data
&
,
data
*
)
=
+
[](
data
&
,
data
*
)
{};
void
(
*
done_
)(
data
&
)
=
+
[](
data
&
)
{};
void
(
*
done_
)(
data
&
)
=
+
[](
data
&
)
{};
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
+
[](
data
&
,
E
)
noexcept
{
void
(
*
error_
)(
data
&
,
E
)
noexcept
=
+
[](
data
&
,
E
)
noexcept
{
std
::
terminate
();
std
::
terminate
();
...
@@ -22,19 +23,16 @@ struct single_vtable {
...
@@ -22,19 +23,16 @@ struct single_vtable {
static
constexpr
single_vtable
const
noop_
=
{};
static
constexpr
single_vtable
const
noop_
=
{};
};
};
template
<
class
data
,
class
op
,
class
V
,
class
E
,
class
Wrapped
,
bool
insitu
>
template
<
class
data
,
class
V
,
class
E
,
class
Wrapped
,
bool
insitu
>
struct
single_vtable_v
;
struct
single_vtable_v
;
template
<
class
data
,
class
op
,
class
V
,
class
E
,
class
Wrapped
>
template
<
class
data
,
class
V
,
class
E
,
class
Wrapped
>
struct
single_vtable_v
<
data
,
op
,
V
,
E
,
Wrapped
,
false
>
{
struct
single_vtable_v
<
data
,
V
,
E
,
Wrapped
,
false
>
{
static
constexpr
single_vtable
<
data
,
op
,
V
,
E
>
const
vtable_v
=
{
static
constexpr
single_vtable
<
data
,
V
,
E
>
const
vtable_v
=
{
+
[](
op
o
,
data
&
src
,
data
*
dst
)
{
+
[](
data
&
src
,
data
*
dst
)
{
switch
(
o
)
{
if
(
dst
)
case
op
:
:
move
:
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
dst
->
pobj_
=
std
::
exchange
(
src
.
pobj_
,
nullptr
);
case
op
:
:
destroy
:
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
delete
static_cast
<
Wrapped
const
*>
(
src
.
pobj_
);
}
},
},
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
},
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
(
src
.
pobj_
));
},
+
[](
data
&
src
,
E
e
)
noexcept
{
+
[](
data
&
src
,
E
e
)
noexcept
{
...
@@ -49,17 +47,14 @@ struct single_vtable_v<data, op, V, E, Wrapped, false> {
...
@@ -49,17 +47,14 @@ struct single_vtable_v<data, op, V, E, Wrapped, false> {
};
};
};
};
template
<
class
data
,
class
op
,
class
V
,
class
E
,
class
Wrapped
>
template
<
class
data
,
class
V
,
class
E
,
class
Wrapped
>
struct
single_vtable_v
<
data
,
op
,
V
,
E
,
Wrapped
,
true
>
{
struct
single_vtable_v
<
data
,
V
,
E
,
Wrapped
,
true
>
{
static
constexpr
single_vtable
<
data
,
op
,
V
,
E
>
const
vtable_v
=
{
static
constexpr
single_vtable
<
data
,
V
,
E
>
const
vtable_v
=
{
+
[](
op
o
,
data
&
src
,
data
*
dst
)
{
+
[](
data
&
src
,
data
*
dst
)
{
switch
(
o
)
{
if
(
dst
)
case
op
:
:
move
:
new
(
dst
->
buffer_
)
Wrapped
(
new
(
dst
->
buffer_
)
Wrapped
(
std
::
move
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
)));
std
::
move
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
)));
case
op
:
:
destroy
:
static_cast
<
Wrapped
const
*>
((
void
*
)
src
.
buffer_
)
->~
Wrapped
();
static_cast
<
Wrapped
const
*>
((
void
*
)
src
.
buffer_
)
->~
Wrapped
();
}
},
},
+
[](
data
&
src
)
{
+
[](
data
&
src
)
{
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
::
pushmi
::
set_done
(
*
static_cast
<
Wrapped
*>
((
void
*
)
src
.
buffer_
));
...
@@ -80,8 +75,8 @@ struct single_vtable_v<data, op, V, E, Wrapped, true> {
...
@@ -80,8 +75,8 @@ struct single_vtable_v<data, op, V, E, Wrapped, true> {
// Class static definitions:
// Class static definitions:
template
<
class
data
,
class
op
,
class
V
,
class
E
>
template
<
class
data
,
class
V
,
class
E
>
constexpr
single_vtable
<
data
,
op
,
V
,
E
>
const
single_vtable
<
data
,
op
,
V
,
E
>::
noop_
;
constexpr
single_vtable
<
data
,
V
,
E
>
const
single_vtable
<
data
,
V
,
E
>::
noop_
;
}
// namespace detail
}
// namespace detail
...
@@ -97,20 +92,20 @@ class single<V, E> {
...
@@ -97,20 +92,20 @@ class single<V, E> {
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
return
sizeof
(
Wrapped
)
<=
sizeof
(
data
::
buffer_
)
&&
std
::
is_nothrow_move_constructible_v
<
Wrapped
>
;
std
::
is_nothrow_move_constructible_v
<
Wrapped
>
;
}
}
enum
struct
op
{
destroy
,
move
};
using
vtable
=
detail
::
single_vtable
<
data
,
V
,
E
>
;
using
vtable
=
detail
::
single_vtable
<
data
,
op
,
V
,
E
>
;
vtable
const
*
vptr_
=
&
vtable
::
noop_
;
vtable
const
*
vptr_
=
&
vtable
::
noop_
;
template
<
class
T
,
class
U
=
std
::
decay_t
<
T
>
>
using
wrapped_t
=
std
::
enable_if_t
<!
std
::
is_same_v
<
U
,
single
>
,
U
>
;
public:
public:
using
receiver_category
=
single_tag
;
using
receiver_category
=
single_tag
;
single
()
=
default
;
single
()
=
default
;
single
(
single
&&
that
)
noexcept
:
single
()
{
single
(
single
&&
that
)
noexcept
:
single
()
{
that
.
vptr_
->
op_
(
op
::
move
,
that
.
data_
,
&
data_
);
that
.
vptr_
->
op_
(
that
.
data_
,
&
data_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
std
::
swap
(
that
.
vptr_
,
vptr_
);
}
}
template
<
class
T
,
class
U
=
std
::
decay_t
<
T
>
>
using
wrapped_t
=
std
::
enable_if_t
<!
std
::
is_same_v
<
U
,
single
>
,
U
>
;
template
<
class
Wrapped
>
template
<
class
Wrapped
>
requires
SingleReceiver
<
wrapped_t
<
Wrapped
>
,
V
,
E
>
requires
SingleReceiver
<
wrapped_t
<
Wrapped
>
,
V
,
E
>
explicit
single
(
Wrapped
obj
)
:
single
()
{
explicit
single
(
Wrapped
obj
)
:
single
()
{
...
@@ -124,10 +119,11 @@ public:
...
@@ -124,10 +119,11 @@ public:
new
(
data_
.
buffer_
)
Wrapped
(
std
::
move
(
obj
));
new
(
data_
.
buffer_
)
Wrapped
(
std
::
move
(
obj
));
else
else
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
data_
.
pobj_
=
new
Wrapped
(
std
::
move
(
obj
));
vptr_
=
&
detail
::
single_vtable_v
<
data
,
op
,
V
,
E
,
Wrapped
,
insitu
<
Wrapped
>
()
>::
vtable_v
;
vptr_
=
&
detail
::
single_vtable_v
<
data
,
V
,
E
,
Wrapped
,
insitu
<
Wrapped
>
()
>::
vtable_v
;
}
}
~
single
()
{
~
single
()
{
vptr_
->
op_
(
op
::
destroy
,
data_
,
nullptr
);
vptr_
->
op_
(
data_
,
nullptr
);
}
}
single
&
operator
=
(
single
&&
that
)
noexcept
{
single
&
operator
=
(
single
&&
that
)
noexcept
{
this
->~
single
();
this
->~
single
();
...
@@ -137,39 +133,41 @@ public:
...
@@ -137,39 +133,41 @@ public:
template
<
class
T
>
template
<
class
T
>
requires
ConvertibleTo
<
T
&&
,
V
&&>
requires
ConvertibleTo
<
T
&&
,
V
&&>
void
value
(
T
&&
t
)
{
void
value
(
T
&&
t
)
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
vptr_
->
rvalue_
(
data_
,
(
T
&&
)
t
);
vptr_
->
rvalue_
(
data_
,
(
T
&&
)
t
);
}
}
}
template
<
class
T
>
template
<
class
T
>
requires
ConvertibleTo
<
T
&
,
V
&>
requires
ConvertibleTo
<
T
&
,
V
&>
void
value
(
T
&
t
)
{
void
value
(
T
&
t
)
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
vptr_
->
lvalue_
(
data_
,
t
);
vptr_
->
lvalue_
(
data_
,
t
);
}
}
}
void
error
(
E
e
)
noexcept
{
void
error
(
E
e
)
noexcept
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
vptr_
->
error_
(
data_
,
std
::
move
(
e
));
vptr_
->
error_
(
data_
,
std
::
move
(
e
));
}
}
}
void
done
()
{
void
done
()
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
vptr_
->
done_
(
data_
);
vptr_
->
done_
(
data_
);
}
}
}
};
};
template
<
class
VF
,
class
EF
,
class
DF
>
template
<
class
VF
,
class
EF
,
class
DF
>
requires
Invocable
<
DF
&>
class
single
<
VF
,
EF
,
DF
>
{
requires
Invocable
<
DF
&>
class
single
<
VF
,
EF
,
DF
>
{
bool
done_
=
false
;
bool
done_
=
false
;
VF
vf_
;
VF
vf_
{};
EF
ef_
;
EF
ef_
{};
DF
df_
;
DF
df_
{};
public:
using
receiver_category
=
single_tag
;
static_assert
(
static_assert
(
!
detail
::
is_v
<
VF
,
on_error
>
,
!
detail
::
is_v
<
VF
,
on_error
>
,
...
@@ -180,6 +178,9 @@ requires Invocable<DF&> class single<VF, EF, DF> {
...
@@ -180,6 +178,9 @@ requires Invocable<DF&> class single<VF, EF, DF> {
static_assert
(
NothrowInvocable
<
EF
,
std
::
exception_ptr
>
,
static_assert
(
NothrowInvocable
<
EF
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
"error function must be noexcept and support std::exception_ptr"
);
public:
using
receiver_category
=
single_tag
;
single
()
=
default
;
single
()
=
default
;
constexpr
explicit
single
(
VF
vf
)
:
single
(
std
::
move
(
vf
),
EF
{},
DF
{})
{}
constexpr
explicit
single
(
VF
vf
)
:
single
(
std
::
move
(
vf
),
EF
{},
DF
{})
{}
constexpr
explicit
single
(
EF
ef
)
:
single
(
VF
{},
std
::
move
(
ef
),
DF
{})
{}
constexpr
explicit
single
(
EF
ef
)
:
single
(
VF
{},
std
::
move
(
ef
),
DF
{})
{}
...
@@ -187,37 +188,40 @@ requires Invocable<DF&> class single<VF, EF, DF> {
...
@@ -187,37 +188,40 @@ requires Invocable<DF&> class single<VF, EF, DF> {
constexpr
single
(
EF
ef
,
DF
df
)
constexpr
single
(
EF
ef
,
DF
df
)
:
done_
(
false
),
vf_
(),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
:
done_
(
false
),
vf_
(),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
constexpr
single
(
VF
vf
,
EF
ef
,
DF
df
=
DF
{})
constexpr
single
(
VF
vf
,
EF
ef
,
DF
df
=
DF
{})
:
done_
(
false
),
vf_
(
std
::
move
(
vf
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
:
done_
(
false
),
vf_
(
std
::
move
(
vf
)),
ef_
(
std
::
move
(
ef
)),
df_
(
std
::
move
(
df
))
{}
template
<
class
V
>
template
<
class
V
>
requires
Invocable
<
VF
&
,
V
>
void
value
(
V
&&
v
)
{
requires
Invocable
<
VF
&
,
V
>
void
value
(
V
&&
v
)
{
if
(
done_
)
{
return
;}
if
(
done_
)
{
return
;}
done_
=
true
;
done_
=
true
;
vf_
((
V
&&
)
v
);
vf_
((
V
&&
)
v
);
}
}
template
<
class
E
>
template
<
class
E
>
requires
Invocable
<
EF
&
,
E
>
void
error
(
E
e
)
noexcept
{
requires
Invocable
<
EF
&
,
E
>
void
error
(
E
e
)
noexcept
{
static_assert
(
NothrowInvocable
<
EF
&
,
E
>
,
"error function must be noexcept"
);
static_assert
(
NothrowInvocable
<
EF
&
,
E
>
,
"error function must be noexcept"
);
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
ef_
(
std
::
move
(
e
));
ef_
(
std
::
move
(
e
));
}
}
}
void
done
()
{
void
done
()
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
df_
();
df_
();
}
}
}
};
};
template
<
Receiver
Data
,
class
DVF
,
class
DEF
,
class
DDF
>
template
<
Receiver
Data
,
class
DVF
,
class
DEF
,
class
DDF
>
requires
Invocable
<
DDF
&
,
Data
&>
class
single
<
Data
,
DVF
,
DEF
,
DDF
>
{
requires
Invocable
<
DDF
&
,
Data
&>
class
single
<
Data
,
DVF
,
DEF
,
DDF
>
{
bool
done_
=
false
;
bool
done_
=
false
;
Data
data_
;
Data
data_
{};
DVF
vf_
;
DVF
vf_
{};
DEF
ef_
;
DEF
ef_
{};
DDF
df_
;
DDF
df_
{};
public:
using
receiver_category
=
single_tag
;
static_assert
(
static_assert
(
!
detail
::
is_v
<
DVF
,
on_error
>
,
!
detail
::
is_v
<
DVF
,
on_error
>
,
...
@@ -228,8 +232,9 @@ requires Invocable<DDF&, Data&> class single<Data, DVF, DEF, DDF> {
...
@@ -228,8 +232,9 @@ requires Invocable<DDF&, Data&> class single<Data, DVF, DEF, DDF> {
static_assert
(
NothrowInvocable
<
DEF
,
Data
&
,
std
::
exception_ptr
>
,
static_assert
(
NothrowInvocable
<
DEF
,
Data
&
,
std
::
exception_ptr
>
,
"error function must be noexcept and support std::exception_ptr"
);
"error function must be noexcept and support std::exception_ptr"
);
template
<
class
...
AN
>
public:
constexpr
explicit
single
(
std
::
tuple
<
AN
...
>
t
)
:
single
(
std
::
apply
(
construct
<
Data
>
{},
std
::
move
(
t
)),
DEF
{},
DDF
{})
{}
using
receiver_category
=
single_tag
;
constexpr
explicit
single
(
Data
d
)
constexpr
explicit
single
(
Data
d
)
:
single
(
std
::
move
(
d
),
DVF
{},
DEF
{},
DDF
{})
{}
:
single
(
std
::
move
(
d
),
DVF
{},
DEF
{},
DDF
{})
{}
constexpr
single
(
Data
d
,
DDF
df
)
constexpr
single
(
Data
d
,
DDF
df
)
...
@@ -238,25 +243,31 @@ requires Invocable<DDF&, Data&> class single<Data, DVF, DEF, DDF> {
...
@@ -238,25 +243,31 @@ requires Invocable<DDF&, Data&> class single<Data, DVF, DEF, DDF> {
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
vf_
(),
ef_
(
ef
),
df_
(
df
)
{}
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
vf_
(),
ef_
(
ef
),
df_
(
df
)
{}
constexpr
single
(
Data
d
,
DVF
vf
,
DEF
ef
=
DEF
{},
DDF
df
=
DDF
{})
constexpr
single
(
Data
d
,
DVF
vf
,
DEF
ef
=
DEF
{},
DDF
df
=
DDF
{})
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
vf_
(
vf
),
ef_
(
ef
),
df_
(
df
)
{}
:
done_
(
false
),
data_
(
std
::
move
(
d
)),
vf_
(
vf
),
ef_
(
ef
),
df_
(
df
)
{}
template
<
class
V
>
template
<
class
V
>
requires
Invocable
<
DVF
&
,
Data
&
,
V
>
void
value
(
V
&&
v
)
{
requires
Invocable
<
DVF
&
,
Data
&
,
V
>
if
(
done_
)
{
return
;}
void
value
(
V
&&
v
)
{
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
vf_
(
data_
,
(
V
&&
)
v
);
vf_
(
data_
,
(
V
&&
)
v
);
}
}
}
template
<
class
E
>
template
<
class
E
>
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
void
error
(
E
e
)
noexcept
{
requires
Invocable
<
DEF
&
,
Data
&
,
E
>
void
error
(
E
e
)
noexcept
{
static_assert
(
static_assert
(
NothrowInvocable
<
DEF
&
,
Data
&
,
E
>
,
"error function must be noexcept"
);
NothrowInvocable
<
DEF
&
,
Data
&
,
E
>
,
"error function must be noexcept"
);
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
ef_
(
data_
,
std
::
move
(
e
));
ef_
(
data_
,
std
::
move
(
e
));
}
}
}
void
done
()
{
void
done
()
{
if
(
done_
)
{
return
;}
if
(
!
done_
)
{
done_
=
true
;
done_
=
true
;
df_
(
data_
);
df_
(
data_
);
}
}
}
};
};
template
<
>
template
<
>
...
@@ -264,70 +275,51 @@ class single<>
...
@@ -264,70 +275,51 @@ class single<>
:
public
single
<
ignoreVF
,
abortEF
,
ignoreDF
>
{
:
public
single
<
ignoreVF
,
abortEF
,
ignoreDF
>
{
};
};
using
archetype_single
=
single
<>
;
single
()
->
single
<>
;
single
()
->
single
<>
;
template
<
class
...
AN
>
single
(
std
::
tuple
<
AN
...
>
)
->
single
<
decltype
(
single
{
std
::
declval
<
AN
&&>
()...}),
passDVF
,
passDEF
,
passDDF
>
;
template
<
class
VF
>
template
<
class
VF
>
requires
!
Receiver
<
VF
>
&&
!
detail
::
is_v
<
VF
,
on_error
>
&&
!
detail
::
is_v
<
VF
,
on_done
>
single
(
VF
)
->
single
<
VF
,
abortEF
,
ignoreDF
>
;
single
(
VF
)
->
single
<
VF
,
abortEF
,
ignoreDF
>
;
template
<
class
...
EFN
>
template
<
class
...
EFN
>
single
(
on_error
<
EFN
...
>
)
->
single
<
ignoreVF
,
on_error
<
EFN
...
>
,
ignoreDF
>
;
single
(
on_error
<
EFN
...
>
)
->
single
<
ignoreVF
,
on_error
<
EFN
...
>
,
ignoreDF
>
;
template
<
class
DF
>
template
<
class
DF
>
single
(
on_done
<
DF
>
)
->
single
<
ignoreVF
,
abortEF
,
on_done
<
DF
>>
;
requires
Invocable
<
DF
&>
single
(
DF
)
->
single
<
ignoreVF
,
abortEF
,
DF
>
;
template
<
class
V
,
class
E
,
class
Wrapped
>
requires
SingleReceiver
<
Wrapped
,
V
,
E
>
single
(
Wrapped
)
->
single
<
V
,
E
>
;
template
<
class
VF
,
class
EF
>
template
<
class
VF
,
class
EF
>
requires
!
Receiver
<
VF
>
&&
!
detail
::
is_v
<
VF
,
on_error
>
&&
!
detail
::
is_v
<
VF
,
on_done
>
&&
!
detail
::
is_v
<
EF
,
on_value
>
&&
!
detail
::
is_v
<
EF
,
on_done
>
&&
!
Invocable
<
VF
&>
&&
!
Invocable
<
EF
&>
single
(
VF
,
EF
)
->
single
<
VF
,
EF
,
ignoreDF
>
;
single
(
VF
,
EF
)
->
single
<
VF
,
EF
,
ignoreDF
>
;
template
<
class
...
EFN
,
class
DF
>
template
<
class
EF
,
class
DF
>
single
(
on_error
<
EFN
...
>
,
on_done
<
DF
>
)
-
>
requires
Invocable
<
DF
&
>
single
<
ignoreVF
,
on_error
<
EFN
...
>
,
on_done
<
DF
>
>
;
single
(
EF
,
DF
)
->
single
<
ignoreVF
,
EF
,
DF
>
;
template
<
class
VF
,
class
EF
,
class
DF
>
template
<
class
VF
,
class
EF
,
class
DF
>
requires
!
Invocable
<
VF
&>
&&
!
Invocable
<
EF
&>
&&
Invocable
<
DF
&>
requires
Invocable
<
DF
&>
single
(
VF
,
EF
,
DF
)
->
single
<
VF
,
EF
,
DF
>
;
single
(
VF
,
EF
,
DF
)
->
single
<
VF
,
EF
,
DF
>
;
template
<
Receiver
<
single_tag
>
Data
>
template
<
Receiver
<
single_tag
>
Data
>
single
(
Data
d
)
->
single
<
Data
,
passDVF
,
passDEF
,
passDDF
>
;
single
(
Data
d
)
->
single
<
Data
,
passDVF
,
passDEF
,
passDDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
>
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
>
requires
!
detail
::
is_v
<
DVF
,
on_error
>
&&
single
(
Data
d
,
DVF
vf
)
->
single
<
Data
,
DVF
,
passDEF
,
passDDF
>
;
!
detail
::
is_v
<
DVF
,
on_done
>
single
(
Data
d
,
DVF
vf
)
->
single
<
Data
,
DVF
,
passDEF
,
passDDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
...
DEFN
>
template
<
Receiver
<
single_tag
>
Data
,
class
...
DEFN
>
single
(
Data
d
,
on_error
<
DEFN
...
>
)
single
(
Data
d
,
on_error
<
DEFN
...
>
)
->
->
single
<
Data
,
passDVF
,
on_error
<
DEFN
...
>
,
passDDF
>
;
single
<
Data
,
passDVF
,
on_error
<
DEFN
...
>
,
passDDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
DDF
>
requires
Invocable
<
DDF
&
,
Data
&>
single
(
Data
d
,
DDF
)
->
single
<
Data
,
passDVF
,
passDEF
,
DDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
,
class
DEF
>
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
,
class
DEF
>
requires
!
detail
::
is_v
<
DVF
,
on_error
>
&&
!
detail
::
is_v
<
DVF
,
on_done
>
&&
!
detail
::
is_v
<
DEF
,
on_done
>
&&
!
Invocable
<
DVF
&
,
Data
&>
&&
!
Invocable
<
DEF
&
,
Data
&>
single
(
Data
d
,
DVF
vf
,
DEF
ef
)
->
single
<
Data
,
DVF
,
DEF
,
passDDF
>
;
single
(
Data
d
,
DVF
vf
,
DEF
ef
)
->
single
<
Data
,
DVF
,
DEF
,
passDDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
...
DEFN
,
class
DDF
>
template
<
Receiver
<
single_tag
>
Data
,
class
DEF
,
class
DDF
>
single
(
Data
d
,
on_error
<
DEFN
...
>
,
on_done
<
DDF
>
)
->
requires
Invocable
<
DDF
&
,
Data
&>
single
<
Data
,
passDVF
,
on_error
<
DEFN
...
>
,
on_done
<
DDF
>>
;
single
(
Data
d
,
DEF
,
DDF
)
->
single
<
Data
,
passDVF
,
DEF
,
DDF
>
;
template
<
Receiver
<
single_tag
>
Data
,
class
DDF
>
single
(
Data
d
,
on_done
<
DDF
>
)
->
single
<
Data
,
passDVF
,
passDEF
,
on_done
<
DDF
>>
;
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
,
class
DEF
,
class
DDF
>
template
<
Receiver
<
single_tag
>
Data
,
class
DVF
,
class
DEF
,
class
DDF
>
requires
!
Invocable
<
DVF
&
,
Data
&>
&&
!
Invocable
<
DEF
&
,
Data
&>
&&
Invocable
<
DDF
&
,
Data
&>
single
(
Data
d
,
DVF
vf
,
DEF
ef
,
DDF
df
)
->
single
<
Data
,
DVF
,
DEF
,
DDF
>
;
single
(
Data
d
,
DVF
vf
,
DEF
ef
,
DDF
df
)
->
single
<
Data
,
DVF
,
DEF
,
DDF
>
;
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
template
<
class
V
,
class
E
=
std
::
exception_ptr
>
...
@@ -339,12 +331,12 @@ using any_single = single<V, E>;
...
@@ -339,12 +331,12 @@ using any_single = single<V, E>;
// return single<V, E>{std::move(w)};
// return single<V, E>{std::move(w)};
// }
// }
template
<
class
T
>
template
<
class
T
,
SenderTo
<
std
::
promise
<
T
>,
single_tag
>
Out
>
std
::
future
<
T
>
future_from
(
auto
singleSender
)
{
std
::
future
<
T
>
future_from
(
Out
singleSender
)
{
std
::
promise
<
T
>
p
;
std
::
promise
<
T
>
p
;
auto
result
=
p
.
get_future
();
auto
result
=
p
.
get_future
();
submit
(
singleSender
,
s
ingle
{
std
::
move
(
p
)}
);
submit
(
singleSender
,
s
td
::
move
(
p
)
);
return
result
;
return
result
;
}
}
}
// namespace
values
}
// namespace
pushmi
folly/experimental/pushmi/include/pushmi/traits.h
View file @
38a4477a
...
@@ -4,6 +4,7 @@
...
@@ -4,6 +4,7 @@
// 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 <functional>
#include <type_traits>
#include <type_traits>
namespace
pushmi
{
namespace
pushmi
{
...
@@ -101,12 +102,11 @@ using requires_ = std::enable_if_t<B, T>;
...
@@ -101,12 +102,11 @@ using requires_ = std::enable_if_t<B, T>;
}
// namespace pushmi
}
// namespace pushmi
#if 1
#if 1
#define PUSHMI_VOID_LAMBDA_REQUIRES(...) \
->::pushmi::detail::requires_<(__VA_ARGS__)>
#define PUSHMI_VOID_LAMBDA_REQUIRES(RequiresExp...) \
#define PUSHMI_T_LAMBDA_REQUIRES(T, ...) \
->::pushmi::detail::requires_<(RequiresExp)>
->::pushmi::detail::requires_<(__VA_ARGS__), T>
#define PUSHMI_T_LAMBDA_REQUIRES(T, RequiresExp...) \
->::pushmi::detail::requires_<(RequiresExp), T>
#elif 0
#elif 0
// unsupported syntax..
// unsupported syntax..
...
...
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