Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
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
Operations
Operations
Metrics
Environments
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
cpp-libs
Actor Framework
Commits
a78f55e3
Commit
a78f55e3
authored
Apr 18, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Consolidate and clean up steps and transformations
parent
45bfe5f2
Changes
37
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1917 additions
and
1538 deletions
+1917
-1538
libcaf_core/caf/cow_vector.hpp
libcaf_core/caf/cow_vector.hpp
+206
-0
libcaf_core/caf/flow/fwd.hpp
libcaf_core/caf/flow/fwd.hpp
+29
-44
libcaf_core/caf/flow/gen/empty.hpp
libcaf_core/caf/flow/gen/empty.hpp
+21
-0
libcaf_core/caf/flow/gen/from_callable.hpp
libcaf_core/caf/flow/gen/from_callable.hpp
+53
-0
libcaf_core/caf/flow/gen/from_container.hpp
libcaf_core/caf/flow/gen/from_container.hpp
+45
-0
libcaf_core/caf/flow/gen/iota.hpp
libcaf_core/caf/flow/gen/iota.hpp
+35
-0
libcaf_core/caf/flow/gen/just.hpp
libcaf_core/caf/flow/gen/just.hpp
+34
-0
libcaf_core/caf/flow/gen/repeat.hpp
libcaf_core/caf/flow/gen/repeat.hpp
+35
-0
libcaf_core/caf/flow/observable.hpp
libcaf_core/caf/flow/observable.hpp
+336
-278
libcaf_core/caf/flow/observable_builder.hpp
libcaf_core/caf/flow/observable_builder.hpp
+86
-360
libcaf_core/caf/flow/observable_decl.hpp
libcaf_core/caf/flow/observable_decl.hpp
+103
-78
libcaf_core/caf/flow/op/from_generator.hpp
libcaf_core/caf/flow/op/from_generator.hpp
+1
-1
libcaf_core/caf/flow/op/prefetch.hpp
libcaf_core/caf/flow/op/prefetch.hpp
+122
-0
libcaf_core/caf/flow/op/prefix_and_tail.hpp
libcaf_core/caf/flow/op/prefix_and_tail.hpp
+0
-291
libcaf_core/caf/flow/op/publish.hpp
libcaf_core/caf/flow/op/publish.hpp
+0
-4
libcaf_core/caf/flow/single.hpp
libcaf_core/caf/flow/single.hpp
+82
-17
libcaf_core/caf/flow/step.hpp
libcaf_core/caf/flow/step.hpp
+0
-423
libcaf_core/caf/flow/step/all.hpp
libcaf_core/caf/flow/step/all.hpp
+12
-0
libcaf_core/caf/flow/step/distinct.hpp
libcaf_core/caf/flow/step/distinct.hpp
+42
-0
libcaf_core/caf/flow/step/do_finally.hpp
libcaf_core/caf/flow/step/do_finally.hpp
+51
-0
libcaf_core/caf/flow/step/do_on_complete.hpp
libcaf_core/caf/flow/step/do_on_complete.hpp
+50
-0
libcaf_core/caf/flow/step/do_on_error.hpp
libcaf_core/caf/flow/step/do_on_error.hpp
+50
-0
libcaf_core/caf/flow/step/do_on_next.hpp
libcaf_core/caf/flow/step/do_on_next.hpp
+58
-0
libcaf_core/caf/flow/step/filter.hpp
libcaf_core/caf/flow/step/filter.hpp
+60
-0
libcaf_core/caf/flow/step/fwd.hpp
libcaf_core/caf/flow/step/fwd.hpp
+39
-0
libcaf_core/caf/flow/step/map.hpp
libcaf_core/caf/flow/step/map.hpp
+57
-0
libcaf_core/caf/flow/step/on_error_complete.hpp
libcaf_core/caf/flow/step/on_error_complete.hpp
+37
-0
libcaf_core/caf/flow/step/reduce.hpp
libcaf_core/caf/flow/step/reduce.hpp
+64
-0
libcaf_core/caf/flow/step/skip.hpp
libcaf_core/caf/flow/step/skip.hpp
+53
-0
libcaf_core/caf/flow/step/take.hpp
libcaf_core/caf/flow/step/take.hpp
+58
-0
libcaf_core/caf/flow/step/take_while.hpp
libcaf_core/caf/flow/step/take_while.hpp
+62
-0
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+1
-0
libcaf_core/test/flow/empty.cpp
libcaf_core/test/flow/empty.cpp
+6
-8
libcaf_core/test/flow/for_each.cpp
libcaf_core/test/flow/for_each.cpp
+3
-5
libcaf_core/test/flow/generation.cpp
libcaf_core/test/flow/generation.cpp
+13
-14
libcaf_core/test/flow/prefix_and_tail.cpp
libcaf_core/test/flow/prefix_and_tail.cpp
+1
-1
libcaf_core/test/response_handle.cpp
libcaf_core/test/response_handle.cpp
+12
-14
No files found.
libcaf_core/caf/cow_vector.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/comparable.hpp"
#include "caf/intrusive_cow_ptr.hpp"
#include "caf/make_counted.hpp"
#include "caf/ref_counted.hpp"
#include <vector>
namespace
caf
{
/// A copy-on-write vector implementation that wraps a `std::vector`.
template
<
class
T
>
class
cow_vector
{
public:
// -- member types -----------------------------------------------------------
using
std_type
=
std
::
vector
<
T
>
;
using
size_type
=
typename
std_type
::
size_type
;
using
const_iterator
=
typename
std_type
::
const_iterator
;
using
const_reverse_iterator
=
typename
std_type
::
const_reverse_iterator
;
// -- constants --------------------------------------------------------------
static
inline
const
size_type
npos
=
std_type
::
npos
;
// -- constructors, destructors, and assignment operators --------------------
cow_vector
()
{
impl_
=
make_counted
<
impl
>
();
}
explicit
cow_vector
(
std_type
std
)
{
impl_
=
make_counted
<
impl
>
(
std
::
move
(
std
));
}
cow_vector
(
cow_vector
&&
)
noexcept
=
default
;
cow_vector
(
const
cow_vector
&
)
noexcept
=
default
;
cow_vector
&
operator
=
(
cow_vector
&&
)
noexcept
=
default
;
cow_vector
&
operator
=
(
const
cow_vector
&
)
noexcept
=
default
;
// -- properties -------------------------------------------------------------
/// Returns a mutable reference to the managed vector. Copies the vector if
/// more than one reference to it exists to make sure the reference count is
/// exactly 1 when returning from this function.
std_type
&
unshared
()
{
return
impl_
.
unshared
().
std
;
}
/// Returns the managed STD container.
const
std_type
&
std
()
const
noexcept
{
return
impl_
->
std
;
}
/// Returns whether the reference count of the managed object is 1.
[[
nodiscard
]]
bool
unique
()
const
noexcept
{
return
impl_
->
unique
();
}
[[
nodiscard
]]
bool
empty
()
const
noexcept
{
return
impl_
->
std
.
empty
();
}
size_type
size
()
const
noexcept
{
return
impl_
->
std
.
size
();
}
size_type
max_size
()
const
noexcept
{
return
impl_
->
std
.
max_size
();
}
// -- element access ---------------------------------------------------------
T
at
(
size_type
pos
)
const
{
return
impl_
->
std
.
at
(
pos
);
}
T
operator
[](
size_type
pos
)
const
{
return
impl_
->
std
[
pos
];
}
T
front
()
const
{
return
impl_
->
std
.
front
();
}
T
back
()
const
{
return
impl_
->
std
.
back
();
}
const
T
*
data
()
const
noexcept
{
return
impl_
->
std
.
data
();
}
// -- iterator access --------------------------------------------------------
const_iterator
begin
()
const
noexcept
{
return
impl_
->
std
.
begin
();
}
const_iterator
cbegin
()
const
noexcept
{
return
impl_
->
std
.
begin
();
}
const_reverse_iterator
rbegin
()
const
noexcept
{
return
impl_
->
std
.
rbegin
();
}
const_reverse_iterator
crbegin
()
const
noexcept
{
return
impl_
->
std
.
rbegin
();
}
const_iterator
end
()
const
noexcept
{
return
impl_
->
std
.
end
();
}
const_iterator
cend
()
const
noexcept
{
return
impl_
->
std
.
end
();
}
const_reverse_iterator
rend
()
const
noexcept
{
return
impl_
->
std
.
rend
();
}
const_reverse_iterator
crend
()
const
noexcept
{
return
impl_
->
std
.
rend
();
}
// -- friends ----------------------------------------------------------------
template
<
class
Inspector
>
friend
bool
inspect
(
Inspector
&
f
,
cow_vector
&
x
)
{
if
constexpr
(
Inspector
::
is_loading
)
{
return
f
.
apply
(
x
.
unshared
());
}
else
{
return
f
.
apply
(
x
.
impl_
->
std
);
}
}
private:
struct
impl
:
ref_counted
{
std_type
std
;
impl
()
=
default
;
explicit
impl
(
std_type
in
)
:
std
(
std
::
move
(
in
))
{
// nop
}
impl
*
copy
()
const
{
return
new
impl
{
std
};
}
};
intrusive_cow_ptr
<
impl
>
impl_
;
};
// -- comparison ---------------------------------------------------------------
template
<
class
T
>
auto
operator
==
(
const
cow_vector
<
T
>&
xs
,
const
cow_vector
<
T
>&
ys
)
->
decltype
(
xs
.
std
()
==
ys
.
std
())
{
return
xs
.
std
()
==
ys
.
std
();
}
template
<
class
T
>
auto
operator
==
(
const
cow_vector
<
T
>&
xs
,
const
std
::
vector
<
T
>&
ys
)
->
decltype
(
xs
.
std
()
==
ys
)
{
return
xs
.
std
()
==
ys
;
}
template
<
class
T
>
auto
operator
==
(
const
std
::
vector
<
T
>&
xs
,
const
cow_vector
<
T
>&
ys
)
->
decltype
(
xs
==
ys
.
std
())
{
return
xs
.
std
()
==
ys
;
}
template
<
class
T
>
auto
operator
!=
(
const
cow_vector
<
T
>&
xs
,
const
cow_vector
<
T
>&
ys
)
->
decltype
(
xs
.
std
()
!=
ys
.
std
())
{
return
xs
.
std
()
!=
ys
.
std
();
}
template
<
class
T
>
auto
operator
!=
(
const
cow_vector
<
T
>&
xs
,
const
std
::
vector
<
T
>&
ys
)
->
decltype
(
xs
.
std
()
!=
ys
)
{
return
xs
.
std
()
!=
ys
;
}
template
<
class
T
>
auto
operator
!=
(
const
std
::
vector
<
T
>&
xs
,
const
cow_vector
<
T
>&
ys
)
->
decltype
(
xs
!=
ys
.
std
())
{
return
xs
.
std
()
!=
ys
;
}
}
// namespace caf
libcaf_core/caf/flow/fwd.hpp
View file @
a78f55e3
...
@@ -38,17 +38,29 @@ class observer;
...
@@ -38,17 +38,29 @@ class observer;
template
<
class
T
>
template
<
class
T
>
class
observable
;
class
observable
;
template
<
class
T
>
template
<
class
Materializer
,
class
...
Steps
>
class
connectable
;
class
observable_def
;
template
<
class
In
,
class
Out
>
template
<
class
Generator
>
class
processo
r
;
class
generation_materialize
r
;
/// A blueprint for an @ref observer that generates items and applies any number
/// of processing steps immediately before emitting them.
template
<
class
Generator
,
class
...
Steps
>
template
<
class
Generator
,
class
...
Steps
>
class
generation
;
using
generation
=
observable_def
<
generation_materializer
<
Generator
>
,
Steps
...
>
;
template
<
class
Input
>
class
transformation_materializer
;
/// A blueprint for an @ref observer that applies a series of transformation
/// steps to its inputs and emits the results.
template
<
class
Step
,
class
...
Steps
>
template
<
class
Step
,
class
...
Steps
>
class
transformation
;
using
transformation
=
observable_def
<
transformation_materializer
<
typename
Step
::
input_type
>
,
Step
,
Steps
...
>
;
template
<
class
T
>
class
connectable
;
template
<
class
T
>
template
<
class
T
>
struct
is_observable
{
struct
is_observable
{
...
@@ -60,18 +72,8 @@ struct is_observable<observable<T>> {
...
@@ -60,18 +72,8 @@ struct is_observable<observable<T>> {
static
constexpr
bool
value
=
true
;
static
constexpr
bool
value
=
true
;
};
};
template
<
class
Step
,
class
...
Steps
>
template
<
class
Materializer
,
class
...
Steps
>
struct
is_observable
<
transformation
<
Step
,
Steps
...
>>
{
struct
is_observable
<
observable_def
<
Materializer
,
Steps
...
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
Generator
,
class
...
Steps
>
struct
is_observable
<
generation
<
Generator
,
Steps
...
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
In
,
class
Out
>
struct
is_observable
<
processor
<
In
,
Out
>>
{
static
constexpr
bool
value
=
true
;
static
constexpr
bool
value
=
true
;
};
};
...
@@ -83,29 +85,6 @@ struct is_observable<single<T>> {
...
@@ -83,29 +85,6 @@ struct is_observable<single<T>> {
template
<
class
T
>
template
<
class
T
>
constexpr
bool
is_observable_v
=
is_observable
<
T
>::
value
;
constexpr
bool
is_observable_v
=
is_observable
<
T
>::
value
;
template
<
class
T
>
struct
is_observer
{
static
constexpr
bool
value
=
false
;
};
template
<
class
T
>
struct
is_observer
<
observer
<
T
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
Step
,
class
...
Steps
>
struct
is_observer
<
transformation
<
Step
,
Steps
...
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
In
,
class
Out
>
struct
is_observer
<
processor
<
In
,
Out
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
T
>
constexpr
bool
is_observer_v
=
is_observer
<
T
>::
value
;
class
observable_builder
;
class
observable_builder
;
template
<
class
T
>
template
<
class
T
>
...
@@ -116,13 +95,19 @@ struct input_type_oracle {
...
@@ -116,13 +95,19 @@ struct input_type_oracle {
template
<
class
T
>
template
<
class
T
>
using
input_type_t
=
typename
input_type_oracle
<
T
>::
type
;
using
input_type_t
=
typename
input_type_oracle
<
T
>::
type
;
template
<
class
...
>
struct
output_type_oracle
;
template
<
class
T
>
template
<
class
T
>
struct
output_type_oracle
{
struct
output_type_oracle
<
T
>
{
using
type
=
typename
T
::
output_type
;
using
type
=
typename
T
::
output_type
;
};
};
template
<
class
T
>
template
<
class
T0
,
class
T1
,
class
...
Ts
>
using
output_type_t
=
typename
output_type_oracle
<
T
>::
type
;
struct
output_type_oracle
<
T0
,
T1
,
Ts
...
>
:
output_type_oracle
<
T1
,
Ts
...
>
{};
template
<
class
...
Ts
>
using
output_type_t
=
typename
output_type_oracle
<
Ts
...
>::
type
;
template
<
class
>
template
<
class
>
struct
has_impl_include
{
struct
has_impl_include
{
...
...
libcaf_core/caf/flow/gen/empty.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
namespace
caf
::
flow
::
gen
{
/// A generator that emits nothing and calls `on_complete` immediately.
template
<
class
T
>
class
empty
{
public:
using
output_type
=
T
;
template
<
class
Step
,
class
...
Steps
>
void
pull
(
size_t
,
Step
&
step
,
Steps
&
...
steps
)
{
step
.
on_complete
(
steps
...);
}
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/gen/from_callable.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include <type_traits>
namespace
caf
::
flow
::
gen
{
/// A generator that emits values from a function object.
template
<
class
F
>
class
from_callable
{
public:
using
callable_res_t
=
std
::
invoke_result_t
<
F
>
;
static
constexpr
bool
boxed_output
=
detail
::
is_optional_v
<
callable_res_t
>
;
using
output_type
=
detail
::
unboxed_t
<
callable_res_t
>
;
explicit
from_callable
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
from_callable
(
from_callable
&&
)
=
default
;
from_callable
(
const
from_callable
&
)
=
default
;
from_callable
&
operator
=
(
from_callable
&&
)
=
default
;
from_callable
&
operator
=
(
const
from_callable
&
)
=
default
;
template
<
class
Step
,
class
...
Steps
>
void
pull
(
size_t
n
,
Step
&
step
,
Steps
&
...
steps
)
{
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
{
if
constexpr
(
boxed_output
)
{
auto
val
=
fn_
();
if
(
!
val
)
{
step
.
on_complete
(
steps
...);
return
;
}
else
if
(
!
step
.
on_next
(
*
val
,
steps
...))
return
;
}
else
{
if
(
!
step
.
on_next
(
fn_
(),
steps
...))
return
;
}
}
}
private:
F
fn_
;
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/gen/from_container.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include <memory>
namespace
caf
::
flow
::
gen
{
/// A generator that emits values from a vector.
template
<
class
Container
>
class
from_container
{
public:
using
output_type
=
typename
Container
::
value_type
;
explicit
from_container
(
Container
&&
values
)
{
values_
=
std
::
make_shared
<
Container
>
(
std
::
move
(
values
));
pos_
=
values_
->
begin
();
}
from_container
()
=
default
;
from_container
(
from_container
&&
)
=
default
;
from_container
(
const
from_container
&
)
=
default
;
from_container
&
operator
=
(
from_container
&&
)
=
default
;
from_container
&
operator
=
(
const
from_container
&
)
=
default
;
template
<
class
Step
,
class
...
Steps
>
void
pull
(
size_t
n
,
Step
&
step
,
Steps
&
...
steps
)
{
auto
end
=
values_
->
end
();
while
(
pos_
!=
end
&&
n
>
0
)
{
if
(
!
step
.
on_next
(
*
pos_
++
,
steps
...))
return
;
--
n
;
}
if
(
pos_
==
end
)
step
.
on_complete
(
steps
...);
}
private:
std
::
shared_ptr
<
Container
>
values_
;
typename
Container
::
const_iterator
pos_
;
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/gen/iota.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
namespace
caf
::
flow
::
gen
{
/// A generator that emits ascending values.
template
<
class
T
>
class
iota
{
public:
using
output_type
=
T
;
explicit
iota
(
T
init
)
:
value_
(
std
::
move
(
init
))
{
// nop
}
iota
(
iota
&&
)
=
default
;
iota
(
const
iota
&
)
=
default
;
iota
&
operator
=
(
iota
&&
)
=
default
;
iota
&
operator
=
(
const
iota
&
)
=
default
;
template
<
class
Step
,
class
...
Steps
>
void
pull
(
size_t
n
,
Step
&
step
,
Steps
&
...
steps
)
{
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
if
(
!
step
.
on_next
(
value_
++
,
steps
...))
return
;
}
private:
T
value_
;
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/gen/just.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
namespace
caf
::
flow
::
gen
{
/// A generator that emits a single value once.
template
<
class
T
>
class
just
{
public:
using
output_type
=
T
;
explicit
just
(
T
value
)
:
value_
(
std
::
move
(
value
))
{
// nop
}
just
(
just
&&
)
=
default
;
just
(
const
just
&
)
=
default
;
just
&
operator
=
(
just
&&
)
=
default
;
just
&
operator
=
(
const
just
&
)
=
default
;
template
<
class
Step
,
class
...
Steps
>
void
pull
([[
maybe_unused
]]
size_t
n
,
Step
&
step
,
Steps
&
...
steps
)
{
if
(
step
.
on_next
(
value_
,
steps
...))
step
.
on_complete
(
steps
...);
}
private:
T
value_
;
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/gen/repeat.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
namespace
caf
::
flow
::
gen
{
/// A generator that emits the same value repeatedly.
template
<
class
T
>
class
repeat
{
public:
using
output_type
=
T
;
explicit
repeat
(
T
value
)
:
value_
(
std
::
move
(
value
))
{
// nop
}
repeat
(
repeat
&&
)
=
default
;
repeat
(
const
repeat
&
)
=
default
;
repeat
&
operator
=
(
repeat
&&
)
=
default
;
repeat
&
operator
=
(
const
repeat
&
)
=
default
;
template
<
class
Step
,
class
...
Steps
>
void
pull
(
size_t
n
,
Step
&
step
,
Steps
&
...
steps
)
{
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
if
(
!
step
.
on_next
(
value_
,
steps
...))
return
;
}
private:
T
value_
;
};
}
// namespace caf::flow::gen
libcaf_core/caf/flow/observable.hpp
View file @
a78f55e3
This diff is collapsed.
Click to expand it.
libcaf_core/caf/flow/observable_builder.hpp
View file @
a78f55e3
This diff is collapsed.
Click to expand it.
libcaf_core/caf/flow/observable_decl.hpp
View file @
a78f55e3
This diff is collapsed.
Click to expand it.
libcaf_core/caf/flow/op/from_generator.hpp
View file @
a78f55e3
...
@@ -20,7 +20,7 @@ class from_generator_sub : public subscription::impl_base {
...
@@ -20,7 +20,7 @@ class from_generator_sub : public subscription::impl_base {
public:
public:
// -- member types -----------------------------------------------------------
// -- member types -----------------------------------------------------------
using
output_type
=
steps_
output_type_t
<
Generator
,
Steps
...
>
;
using
output_type
=
output_type_t
<
Generator
,
Steps
...
>
;
// -- constructors, destructors, and assignment operators --------------------
// -- constructors, destructors, and assignment operators --------------------
...
...
libcaf_core/caf/flow/op/prefetch.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/error.hpp"
#include "caf/flow/observer.hpp"
#include "caf/flow/op/hot.hpp"
#include "caf/flow/subscription.hpp"
#include "caf/sec.hpp"
#include <utility>
namespace
caf
::
flow
::
op
{
/// Allows operators to subscribe to an observable immediately to force an eager
/// subscription while the observable that actually consumes the items
/// subscribes later. May only be subscribed once.
template
<
class
T
>
class
prefetch
:
public
hot
<
T
>
,
public
observer_impl
<
T
>
{
public:
// -- member types -----------------------------------------------------------
using
super
=
hot
<
T
>
;
using
output_type
=
T
;
// -- constructors, destructors, and assignment operators --------------------
explicit
prefetch
(
coordinator
*
ctx
)
:
super
(
ctx
)
{
// nop
}
// -- ref counting (and disambiguation due to multiple base types) -----------
void
ref_coordinated
()
const
noexcept
override
{
this
->
ref
();
}
void
deref_coordinated
()
const
noexcept
override
{
this
->
deref
();
}
friend
void
intrusive_ptr_add_ref
(
const
prefetch
*
ptr
)
noexcept
{
ptr
->
ref_coordinated
();
}
friend
void
intrusive_ptr_release
(
const
prefetch
*
ptr
)
noexcept
{
ptr
->
deref_coordinated
();
}
// -- implementation of observable_impl<T> -----------------------------------
disposable
subscribe
(
observer
<
T
>
out
)
override
{
if
(
completed_
)
{
if
(
err_
)
out
.
on_error
(
err_
);
else
out
.
on_complete
();
return
{};
}
else
if
(
!
out_
&&
sub_
)
{
out_
=
std
::
move
(
out
);
out_
.
on_subscribe
(
sub_
);
return
sub_
.
as_disposable
();
}
else
{
auto
err
=
make_error
(
sec
::
invalid_observable
,
"prefetch cannot add more than one subscriber"
);
out
.
on_error
(
err
);
return
{};
}
}
// -- implementation of observer_impl<T> -------------------------------------
void
on_next
(
const
T
&
item
)
override
{
out_
.
on_next
(
item
);
}
void
on_complete
()
override
{
completed_
=
true
;
if
(
out_
)
{
out_
.
on_complete
();
out_
=
nullptr
;
sub_
=
nullptr
;
}
}
void
on_error
(
const
error
&
what
)
override
{
completed_
=
true
;
err_
=
what
;
if
(
out_
)
{
out_
.
on_error
(
what
);
out_
=
nullptr
;
sub_
=
nullptr
;
}
}
void
on_subscribe
(
subscription
sub
)
override
{
if
(
!
sub_
)
{
sub_
=
sub
;
}
else
{
sub
.
dispose
();
}
}
// -- convenience functions --------------------------------------------------
static
intrusive_ptr
<
base
<
T
>>
apply
(
intrusive_ptr
<
base
<
T
>>
src
)
{
auto
ptr
=
make_counted
<
prefetch
>
(
src
->
ctx
());
src
->
subscribe
(
observer
<
T
>
{
ptr
});
return
ptr
;
}
private:
bool
completed_
=
false
;
error
err_
;
observer
<
T
>
out_
;
subscription
sub_
;
};
}
// namespace caf::flow::op
libcaf_core/caf/flow/op/prefix_and_tail.hpp
deleted
100644 → 0
View file @
45bfe5f2
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/cow_tuple.hpp"
#include "caf/flow/observable.hpp"
#include "caf/flow/observable_decl.hpp"
#include "caf/flow/observer.hpp"
#include "caf/flow/op/cell.hpp"
#include "caf/flow/subscription.hpp"
#include <cstdint>
namespace
caf
::
flow
::
op
{
template
<
class
T
>
class
pipe_sub
:
public
detail
::
plain_ref_counted
,
public
observer_impl
<
T
>
,
public
subscription_impl
{
public:
// -- constructors, destructors, and assignment operators --------------------
explicit
pipe_sub
(
subscription
in
)
:
in_
(
std
::
move
(
in
))
{
// nop
}
void
init
(
observer
<
T
>
out
)
{
if
(
!
completed_
)
out_
=
std
::
move
(
out
);
else
if
(
err_
)
out
.
on_error
(
err_
);
else
out
.
on_complete
();
}
// -- ref counting -----------------------------------------------------------
void
ref_coordinated
()
const
noexcept
final
{
this
->
ref
();
}
void
deref_coordinated
()
const
noexcept
final
{
this
->
deref
();
}
void
ref_disposable
()
const
noexcept
final
{
this
->
ref
();
}
void
deref_disposable
()
const
noexcept
final
{
this
->
deref
();
}
friend
void
intrusive_ptr_add_ref
(
const
pipe_sub
*
ptr
)
noexcept
{
ptr
->
ref
();
}
friend
void
intrusive_ptr_release
(
const
pipe_sub
*
ptr
)
noexcept
{
ptr
->
deref
();
}
// -- implementation of observer_impl<Input> ---------------------------------
void
on_next
(
const
T
&
item
)
override
{
if
(
out_
)
out_
.
on_next
(
item
);
}
void
on_complete
()
override
{
if
(
out_
)
{
in_
=
nullptr
;
out_
.
on_complete
();
out_
=
nullptr
;
completed_
=
true
;
}
else
if
(
!
completed_
)
{
completed_
=
true
;
}
}
void
on_error
(
const
error
&
what
)
override
{
if
(
out_
)
{
in_
=
nullptr
;
out_
.
on_error
(
what
);
out_
=
nullptr
;
completed_
=
true
;
err_
=
what
;
}
else
if
(
!
completed_
)
{
completed_
=
true
;
err_
=
what
;
}
}
void
on_subscribe
(
subscription
in
)
override
{
in
.
dispose
();
}
// -- implementation of subscription_impl ------------------------------------
bool
disposed
()
const
noexcept
override
{
return
!
out_
;
}
void
dispose
()
override
{
if
(
in_
)
{
in_
.
dispose
();
in_
=
nullptr
;
}
if
(
out_
)
{
out_
.
on_complete
();
out_
=
nullptr
;
}
}
void
request
(
size_t
n
)
override
{
if
(
in_
)
{
in_
.
request
(
n
);
}
}
private:
subscription
in_
;
observer
<
T
>
out_
;
/// Stores whether on_complete has been called. This may be the case even
/// before init gets called.
bool
completed_
=
false
;
/// Stores the error passed to on_error.
error
err_
;
};
template
<
class
T
>
class
pipe
:
public
hot
<
T
>
{
public:
using
super
=
hot
<
T
>
;
using
sub_ptr
=
intrusive_ptr
<
pipe_sub
<
T
>>
;
explicit
pipe
(
coordinator
*
ctx
,
sub_ptr
sub
)
:
super
(
ctx
),
sub_
(
std
::
move
(
sub
))
{
// nop
}
~
pipe
()
{
if
(
sub_
)
sub_
->
dispose
();
}
disposable
subscribe
(
observer
<
T
>
out
)
override
{
if
(
sub_
)
{
sub_
->
init
(
out
);
out
.
on_subscribe
(
subscription
{
sub_
});
return
disposable
{
std
::
move
(
sub_
)};
}
else
{
auto
err
=
make_error
(
sec
::
invalid_observable
,
"pipes may only be subscribed once"
);
out
.
on_error
(
err
);
return
disposable
{};
}
}
private:
sub_ptr
sub_
;
};
template
<
class
T
>
class
prefix_and_tail_fwd
:
public
detail
::
plain_ref_counted
,
public
observer_impl
<
T
>
{
public:
// -- constructors, destructors, and assignment operators --------------------
using
output_type
=
cow_tuple
<
std
::
vector
<
T
>
,
observable
<
T
>>
;
using
cell_ptr
=
intrusive_ptr
<
cell
<
output_type
>>
;
prefix_and_tail_fwd
(
coordinator
*
ctx
,
size_t
prefix_size
,
cell_ptr
sync
)
:
ctx_
(
ctx
),
prefix_size_
(
prefix_size
),
sync_
(
std
::
move
(
sync
))
{
// nop
}
// -- ref counting -----------------------------------------------------------
void
ref_coordinated
()
const
noexcept
final
{
this
->
ref
();
}
void
deref_coordinated
()
const
noexcept
final
{
this
->
deref
();
}
friend
void
intrusive_ptr_add_ref
(
const
prefix_and_tail_fwd
*
ptr
)
noexcept
{
ptr
->
ref
();
}
friend
void
intrusive_ptr_release
(
const
prefix_and_tail_fwd
*
ptr
)
noexcept
{
ptr
->
deref
();
}
// -- implementation of observer_impl<T> -------------------------------------
void
on_next
(
const
T
&
item
)
override
{
if
(
next_
)
{
next_
.
on_next
(
item
);
}
else
if
(
sync_
)
{
prefix_
.
push_back
(
item
);
if
(
prefix_
.
size
()
==
prefix_size_
)
{
auto
fwd
=
make_counted
<
pipe_sub
<
T
>>
(
std
::
move
(
in_
));
auto
tmp
=
make_counted
<
pipe
<
T
>>
(
ctx_
,
fwd
);
output_type
result
{
std
::
move
(
prefix_
),
observable
<
T
>
{
tmp
}};
sync_
->
set_value
(
std
::
move
(
result
));
sync_
=
nullptr
;
next_
=
observer
<
T
>
{
fwd
};
}
}
}
void
on_complete
()
override
{
if
(
next_
)
{
next_
.
on_complete
();
next_
=
nullptr
;
}
else
if
(
sync_
)
{
sync_
->
set_null
();
sync_
=
nullptr
;
}
}
void
on_error
(
const
error
&
what
)
override
{
if
(
next_
)
{
next_
.
on_error
(
what
);
next_
=
nullptr
;
}
else
if
(
sync_
)
{
sync_
->
set_error
(
what
);
sync_
=
nullptr
;
}
}
void
on_subscribe
(
subscription
in
)
override
{
in_
=
std
::
move
(
in
);
in_
.
request
(
prefix_size_
);
}
private:
coordinator
*
ctx_
;
size_t
prefix_size_
=
0
;
subscription
in_
;
std
::
vector
<
T
>
prefix_
;
observer
<
T
>
next_
;
cell_ptr
sync_
;
};
template
<
class
T
>
class
prefix_and_tail
:
public
cold
<
cow_tuple
<
std
::
vector
<
T
>
,
observable
<
T
>>>
{
public:
// -- member types -----------------------------------------------------------
using
output_type
=
cow_tuple
<
std
::
vector
<
T
>
,
observable
<
T
>>
;
using
super
=
cold
<
output_type
>
;
using
observer_type
=
observer
<
T
>
;
// -- constructors, destructors, and assignment operators --------------------
prefix_and_tail
(
coordinator
*
ctx
,
intrusive_ptr
<
base
<
T
>>
decorated
,
size_t
prefix_size
)
:
super
(
ctx
),
decorated_
(
std
::
move
(
decorated
)),
prefix_size_
(
prefix_size
)
{
// nop
}
disposable
subscribe
(
observer
<
output_type
>
out
)
override
{
// The cell acts as a sort of handshake between the dispatcher and the
// observer. After producing the (prefix, tail) pair, the dispatcher goes on
// to forward items from the decorated observable to the tail.
auto
sync
=
make_counted
<
cell
<
output_type
>>
(
super
::
ctx_
);
auto
fwd
=
make_counted
<
prefix_and_tail_fwd
<
T
>>
(
super
::
ctx_
,
prefix_size_
,
sync
);
std
::
vector
<
disposable
>
result
;
result
.
reserve
(
2
);
result
.
emplace_back
(
sync
->
subscribe
(
std
::
move
(
out
)));
result
.
emplace_back
(
decorated_
->
subscribe
(
observer
<
T
>
{
std
::
move
(
fwd
)}));
return
disposable
::
make_composite
(
std
::
move
(
result
));
}
private:
intrusive_ptr
<
base
<
T
>>
decorated_
;
size_t
prefix_size_
;
};
}
// namespace caf::flow::op
libcaf_core/caf/flow/op/publish.hpp
View file @
a78f55e3
...
@@ -49,10 +49,6 @@ public:
...
@@ -49,10 +49,6 @@ public:
// -- implementation of conn<T> ----------------------------------------------
// -- implementation of conn<T> ----------------------------------------------
coordinator
*
ctx
()
const
noexcept
override
{
return
super
::
ctx_
;
}
disposable
subscribe
(
observer
<
T
>
out
)
override
{
disposable
subscribe
(
observer
<
T
>
out
)
override
{
auto
result
=
super
::
subscribe
(
std
::
move
(
out
));
auto
result
=
super
::
subscribe
(
std
::
move
(
out
));
if
(
!
connected_
&&
super
::
observer_count
()
==
auto_connect_threshold_
)
{
if
(
!
connected_
&&
super
::
observer_count
()
==
auto_connect_threshold_
)
{
...
...
libcaf_core/caf/flow/single.hpp
View file @
a78f55e3
...
@@ -4,18 +4,90 @@
...
@@ -4,18 +4,90 @@
#pragma once
#pragma once
#include <algorithm>
#include <utility>
#include <variant>
#include "caf/detail/overload.hpp"
#include "caf/detail/overload.hpp"
#include "caf/disposable.hpp"
#include "caf/disposable.hpp"
#include "caf/error.hpp"
#include "caf/error.hpp"
#include "caf/flow/observable.hpp"
#include "caf/flow/observable.hpp"
#include "caf/ref_counted.hpp"
#include "caf/ref_counted.hpp"
#include <algorithm>
#include <optional>
#include <type_traits>
#include <utility>
namespace
caf
::
flow
{
namespace
caf
::
flow
{
template
<
class
OnSuccess
>
struct
on_success_orcacle
{
using
trait
=
detail
::
get_callable_trait_t
<
OnSuccess
>
;
static_assert
(
trait
::
num_args
==
1
,
"OnSuccess functions must take exactly one argument"
);
using
arg_type
=
std
::
decay_t
<
detail
::
tl_head_t
<
typename
trait
::
arg_types
>>
;
};
template
<
class
OnSuccess
>
using
on_success_arg_t
=
typename
on_success_orcacle
<
OnSuccess
>::
arg_type
;
template
<
class
OnSuccess
,
class
OnError
>
class
single_observer_impl
:
public
observer_impl_base
<
on_success_arg_t
<
OnSuccess
>>
{
public:
using
input_type
=
on_success_arg_t
<
OnSuccess
>
;
single_observer_impl
(
OnSuccess
on_success
,
OnError
on_error
)
:
on_success_
(
std
::
move
(
on_success
)),
on_error_
(
std
::
move
(
on_error
))
{
// nop
}
void
on_subscribe
(
subscription
sub
)
{
// Request one additional item to detect whether the observable emits more
// than one item.
sub
.
request
(
2
);
sub_
=
std
::
move
(
sub
);
}
void
on_next
(
const
input_type
&
item
)
{
if
(
!
result_
)
{
result_
.
emplace
(
item
);
}
else
{
sub_
.
dispose
();
sub_
=
nullptr
;
auto
err
=
make_error
(
sec
::
runtime_error
,
"single emitted more than one item"
);
on_error_
(
err
);
}
}
void
on_complete
()
{
if
(
sub_
)
{
sub_
=
nullptr
;
if
(
result_
)
{
on_success_
(
*
result_
);
result_
=
std
::
nullopt
;
}
else
{
auto
err
=
make_error
(
sec
::
broken_promise
,
"single failed to produce an item"
);
on_error_
(
err
);
}
}
}
void
on_error
(
const
error
&
what
)
{
if
(
sub_
)
{
sub_
=
nullptr
;
on_error_
(
what
);
}
}
private:
OnSuccess
on_success_
;
OnError
on_error_
;
std
::
optional
<
input_type
>
result_
;
subscription
sub_
;
};
/// Similar to an `observable`, but always emits either a single value or an
/// Similar to an `observable`, but always emits either a single value or an
/// error.
/// error.
template
<
class
T
>
template
<
class
T
>
...
@@ -46,19 +118,13 @@ public:
...
@@ -46,19 +118,13 @@ public:
return
observable
<
T
>
{
pimpl_
};
return
observable
<
T
>
{
pimpl_
};
}
}
void
subscribe
(
observer
<
T
>
what
)
{
if
(
pimpl_
)
pimpl_
->
subscribe
(
std
::
move
(
what
));
else
what
.
on_error
(
make_error
(
sec
::
invalid_observable
));
}
template
<
class
OnSuccess
,
class
OnError
>
template
<
class
OnSuccess
,
class
OnError
>
void
subscribe
(
OnSuccess
on_success
,
OnError
on_error
)
{
disposable
subscribe
(
OnSuccess
on_success
,
OnError
on_error
)
{
static_assert
(
std
::
is_invocable_v
<
OnSuccess
,
const
T
&>
);
static_assert
(
std
::
is_invocable_v
<
OnSuccess
,
const
T
&>
);
as_observable
().
for_each
([
f
{
std
::
move
(
on_success
)}](
static_assert
(
std
::
is_invocable_v
<
OnError
,
const
error
&>
);
const
T
&
item
)
mutable
{
f
(
item
);
},
using
impl_t
=
single_observer_impl
<
OnSuccess
,
OnError
>
;
std
::
move
(
on_error
));
auto
ptr
=
make_counted
<
impl_t
>
(
std
::
move
(
on_success
),
std
::
move
(
on_error
));
return
pimpl_
->
subscribe
(
observer
<
T
>
{
ptr
});
}
}
bool
valid
()
const
noexcept
{
bool
valid
()
const
noexcept
{
...
@@ -81,8 +147,7 @@ private:
...
@@ -81,8 +147,7 @@ private:
intrusive_ptr
<
op
::
base
<
T
>>
pimpl_
;
intrusive_ptr
<
op
::
base
<
T
>>
pimpl_
;
};
};
/// Convenience function for creating an @ref observable from a concrete
/// Convenience function for creating a @ref single from a flow operator.
/// operator type.
template
<
class
Operator
,
class
...
Ts
>
template
<
class
Operator
,
class
...
Ts
>
single
<
typename
Operator
::
output_type
>
single
<
typename
Operator
::
output_type
>
make_single
(
coordinator
*
ctx
,
Ts
&&
...
xs
)
{
make_single
(
coordinator
*
ctx
,
Ts
&&
...
xs
)
{
...
...
libcaf_core/caf/flow/step.hpp
deleted
100644 → 0
View file @
45bfe5f2
This diff is collapsed.
Click to expand it.
libcaf_core/caf/flow/step/all.hpp
0 → 100644
View file @
a78f55e3
#include "caf/flow/step/distinct.hpp"
#include "caf/flow/step/do_finally.hpp"
#include "caf/flow/step/do_on_complete.hpp"
#include "caf/flow/step/do_on_error.hpp"
#include "caf/flow/step/do_on_next.hpp"
#include "caf/flow/step/filter.hpp"
#include "caf/flow/step/map.hpp"
#include "caf/flow/step/on_error_complete.hpp"
#include "caf/flow/step/reduce.hpp"
#include "caf/flow/step/skip.hpp"
#include "caf/flow/step/take.hpp"
#include "caf/flow/step/take_while.hpp"
libcaf_core/caf/flow/step/distinct.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/fwd.hpp"
#include <unordered_set>
namespace
caf
::
flow
::
step
{
template
<
class
T
>
class
distinct
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
prev_
.
insert
(
item
).
second
)
return
next
.
on_next
(
item
,
steps
...);
else
return
true
;
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
std
::
unordered_set
<
T
>
prev_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/do_finally.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
T
,
class
F
>
class
do_finally
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
explicit
do_finally
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
do_finally
(
do_finally
&&
)
=
default
;
do_finally
(
const
do_finally
&
)
=
default
;
do_finally
&
operator
=
(
do_finally
&&
)
=
default
;
do_finally
&
operator
=
(
const
do_finally
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
T
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
return
next
.
on_next
(
item
,
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
finally
(
Next
&
next
,
Steps
&
...
steps
)
{
fn_
();
next
.
finally
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
finally
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
fn_
();
next
.
finally
(
what
,
steps
...);
}
private:
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/do_on_complete.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
T
,
class
F
>
class
do_on_complete
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
explicit
do_on_complete
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
do_on_complete
(
do_on_complete
&&
)
=
default
;
do_on_complete
(
const
do_on_complete
&
)
=
default
;
do_on_complete
&
operator
=
(
do_on_complete
&&
)
=
default
;
do_on_complete
&
operator
=
(
const
do_on_complete
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
T
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
return
next
.
on_next
(
item
,
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
fn_
();
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/do_on_error.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
T
,
class
F
>
class
do_on_error
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
explicit
do_on_error
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
do_on_error
(
do_on_error
&&
)
=
default
;
do_on_error
(
const
do_on_error
&
)
=
default
;
do_on_error
&
operator
=
(
do_on_error
&&
)
=
default
;
do_on_error
&
operator
=
(
const
do_on_error
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
T
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
return
next
.
on_next
(
item
,
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
fn_
(
what
);
next
.
on_error
(
what
,
steps
...);
}
private:
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/do_on_next.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
F
>
class
do_on_next
{
public:
using
trait
=
detail
::
get_callable_trait_t
<
F
>
;
static_assert
(
!
std
::
is_same_v
<
typename
trait
::
result_type
,
void
>
,
"do_on_next functions may not return void"
);
static_assert
(
trait
::
num_args
==
1
,
"do_on_next functions must take exactly one argument"
);
using
input_type
=
std
::
decay_t
<
detail
::
tl_head_t
<
typename
trait
::
arg_types
>>
;
using
output_type
=
std
::
decay_t
<
typename
trait
::
result_type
>
;
explicit
do_on_next
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
do_on_next
(
do_on_next
&&
)
=
default
;
do_on_next
(
const
do_on_next
&
)
=
default
;
do_on_next
&
operator
=
(
do_on_next
&&
)
=
default
;
do_on_next
&
operator
=
(
const
do_on_next
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
fn_
(
item
);
return
next
.
on_next
(
item
,
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/filter.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
Predicate
>
class
filter
{
public:
using
trait
=
detail
::
get_callable_trait_t
<
Predicate
>
;
static_assert
(
std
::
is_convertible_v
<
typename
trait
::
result_type
,
bool
>
,
"predicates must return a boolean value"
);
static_assert
(
trait
::
num_args
==
1
,
"predicates must take exactly one argument"
);
using
input_type
=
std
::
decay_t
<
detail
::
tl_head_t
<
typename
trait
::
arg_types
>>
;
using
output_type
=
input_type
;
explicit
filter
(
Predicate
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
filter
(
filter
&&
)
=
default
;
filter
(
const
filter
&
)
=
default
;
filter
&
operator
=
(
filter
&&
)
=
default
;
filter
&
operator
=
(
const
filter
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
fn_
(
item
))
return
next
.
on_next
(
item
,
steps
...);
else
return
true
;
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
Predicate
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/fwd.hpp
0 → 100644
View file @
a78f55e3
namespace
caf
::
flow
::
step
{
template
<
class
>
class
distinct
;
template
<
class
,
class
>
class
do_finally
;
template
<
class
,
class
>
class
do_on_complete
;
template
<
class
,
class
>
class
do_on_error
;
template
<
class
>
class
do_on_next
;
template
<
class
>
class
filter
;
template
<
class
>
class
map
;
template
<
class
>
class
on_error_complete
;
template
<
class
>
class
reduce
;
template
<
class
>
class
skip
;
template
<
class
>
class
take
;
template
<
class
>
class
take_while
;
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/map.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
F
>
class
map
{
public:
using
trait
=
detail
::
get_callable_trait_t
<
F
>
;
static_assert
(
!
std
::
is_same_v
<
typename
trait
::
result_type
,
void
>
,
"map functions may not return void"
);
static_assert
(
trait
::
num_args
==
1
,
"map functions must take exactly one argument"
);
using
input_type
=
std
::
decay_t
<
detail
::
tl_head_t
<
typename
trait
::
arg_types
>>
;
using
output_type
=
std
::
decay_t
<
typename
trait
::
result_type
>
;
explicit
map
(
F
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
map
(
map
&&
)
=
default
;
map
(
const
map
&
)
=
default
;
map
&
operator
=
(
map
&&
)
=
default
;
map
&
operator
=
(
const
map
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
return
next
.
on_next
(
fn_
(
item
),
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/on_error_complete.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
T
>
class
on_error_complete
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
T
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
return
next
.
on_next
(
item
,
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/reduce.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
F
>
class
reduce
{
public:
using
trait
=
detail
::
get_callable_trait_t
<
F
>
;
static_assert
(
!
std
::
is_same_v
<
typename
trait
::
result_type
,
void
>
,
"reduce functions may not return void"
);
static_assert
(
trait
::
num_args
==
2
,
"reduce functions must take exactly two arguments"
);
using
arg_type
=
typename
trait
::
arg_types
;
using
input_type
=
std
::
decay_t
<
detail
::
tl_at_t
<
arg_type
,
1
>>
;
using
output_type
=
std
::
decay_t
<
typename
trait
::
result_type
>
;
explicit
reduce
(
output_type
init
,
F
fn
)
:
val_
(
std
::
move
(
init
)),
fn_
(
std
::
move
(
fn
))
{
// nop
}
reduce
(
reduce
&&
)
=
default
;
reduce
(
const
reduce
&
)
=
default
;
reduce
&
operator
=
(
reduce
&&
)
=
default
;
reduce
&
operator
=
(
const
reduce
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
,
Steps
&
...)
{
val_
=
fn_
(
std
::
move
(
val_
),
item
);
return
true
;
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
if
(
next
.
on_next
(
val_
,
steps
...))
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
next
.
on_next
(
val_
,
steps
...))
next
.
on_error
(
what
,
steps
...);
}
private:
output_type
val_
;
F
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/skip.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/fwd.hpp"
#include <cstddef>
namespace
caf
::
flow
::
step
{
template
<
class
T
>
class
skip
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
explicit
skip
(
size_t
num
)
:
remaining_
(
num
)
{
// nop
}
skip
(
skip
&&
)
=
default
;
skip
(
const
skip
&
)
=
default
;
skip
&
operator
=
(
skip
&&
)
=
default
;
skip
&
operator
=
(
const
skip
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
remaining_
==
0
)
{
return
next
.
on_next
(
item
,
steps
...);
}
else
{
--
remaining_
;
return
true
;
}
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
size_t
remaining_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/take.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/fwd.hpp"
#include <cstddef>
namespace
caf
::
flow
::
step
{
template
<
class
T
>
class
take
{
public:
using
input_type
=
T
;
using
output_type
=
T
;
explicit
take
(
size_t
num
)
:
remaining_
(
num
)
{
// nop
}
take
(
take
&&
)
=
default
;
take
(
const
take
&
)
=
default
;
take
&
operator
=
(
take
&&
)
=
default
;
take
&
operator
=
(
const
take
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
remaining_
>
0
)
{
if
(
next
.
on_next
(
item
,
steps
...))
{
if
(
--
remaining_
>
0
)
{
return
true
;
}
else
{
next
.
on_complete
(
steps
...);
return
false
;
}
}
}
return
false
;
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
size_t
remaining_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/flow/step/take_while.hpp
0 → 100644
View file @
a78f55e3
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include <utility>
namespace
caf
::
flow
::
step
{
template
<
class
Predicate
>
class
take_while
{
public:
using
trait
=
detail
::
get_callable_trait_t
<
Predicate
>
;
static_assert
(
std
::
is_convertible_v
<
typename
trait
::
result_type
,
bool
>
,
"predicates must return a boolean value"
);
static_assert
(
trait
::
num_args
==
1
,
"predicates must take exactly one argument"
);
using
input_type
=
std
::
decay_t
<
detail
::
tl_head_t
<
typename
trait
::
arg_types
>>
;
using
output_type
=
input_type
;
explicit
take_while
(
Predicate
fn
)
:
fn_
(
std
::
move
(
fn
))
{
// nop
}
take_while
(
take_while
&&
)
=
default
;
take_while
(
const
take_while
&
)
=
default
;
take_while
&
operator
=
(
take_while
&&
)
=
default
;
take_while
&
operator
=
(
const
take_while
&
)
=
default
;
template
<
class
Next
,
class
...
Steps
>
bool
on_next
(
const
input_type
&
item
,
Next
&
next
,
Steps
&
...
steps
)
{
if
(
fn_
(
item
))
{
return
next
.
on_next
(
item
,
steps
...);
}
else
{
next
.
on_complete
(
steps
...);
return
false
;
}
}
template
<
class
Next
,
class
...
Steps
>
void
on_complete
(
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_complete
(
steps
...);
}
template
<
class
Next
,
class
...
Steps
>
void
on_error
(
const
error
&
what
,
Next
&
next
,
Steps
&
...
steps
)
{
next
.
on_error
(
what
,
steps
...);
}
private:
Predicate
fn_
;
};
}
// namespace caf::flow::step
libcaf_core/caf/fwd.hpp
View file @
a78f55e3
...
@@ -20,6 +20,7 @@ template <class> class [[nodiscard]] error_code;
...
@@ -20,6 +20,7 @@ template <class> class [[nodiscard]] error_code;
template
<
class
>
class
basic_cow_string
;
template
<
class
>
class
basic_cow_string
;
template
<
class
>
class
behavior_type_of
;
template
<
class
>
class
behavior_type_of
;
template
<
class
>
class
callback
;
template
<
class
>
class
callback
;
template
<
class
>
class
cow_vector
;
template
<
class
>
class
dictionary
;
template
<
class
>
class
dictionary
;
template
<
class
>
class
expected
;
template
<
class
>
class
expected
;
template
<
class
>
class
intrusive_cow_ptr
;
template
<
class
>
class
intrusive_cow_ptr
;
...
...
libcaf_core/test/flow/empty.cpp
View file @
a78f55e3
...
@@ -26,19 +26,17 @@ SCENARIO("an empty observable terminates normally") {
...
@@ -26,19 +26,17 @@ SCENARIO("an empty observable terminates normally") {
GIVEN
(
"an empty<int32>"
)
{
GIVEN
(
"an empty<int32>"
)
{
WHEN
(
"an observer subscribes"
)
{
WHEN
(
"an observer subscribes"
)
{
THEN
(
"the observer receives on_complete"
)
{
THEN
(
"the observer receives on_complete"
)
{
auto
uut
=
ctx
->
make_observable
().
empty
<
int32_t
>
();
auto
snk
=
flow
::
make_passive_observer
<
int32_t
>
();
auto
snk
=
flow
::
make_passive_observer
<
int32_t
>
();
uut
.
subscribe
(
snk
->
as_observer
());
ctx
->
make_observable
().
empty
<
int32_t
>
()
.
subscribe
(
snk
->
as_observer
());
ctx
->
run
();
ctx
->
run
();
if
(
CHECK
(
snk
->
sub
))
{
CHECK
(
snk
->
subscribed
());
snk
->
sub
.
request
(
42
);
snk
->
request
(
42
);
ctx
->
run
();
ctx
->
run
();
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
completed
);
CHECK
(
snk
->
completed
()
);
CHECK
(
snk
->
buf
.
empty
());
CHECK
(
snk
->
buf
.
empty
());
}
}
}
}
}
}
}
}
}
END_FIXTURE_SCOPE
()
END_FIXTURE_SCOPE
()
libcaf_core/test/flow/for_each.cpp
View file @
a78f55e3
...
@@ -77,11 +77,9 @@ SCENARIO("for_each iterates all values in a stream") {
...
@@ -77,11 +77,9 @@ SCENARIO("for_each iterates all values in a stream") {
.
as_observable
()
.
as_observable
()
.
take
(
7
)
.
take
(
7
)
.
map
([](
int
x
)
{
return
x
*
3
;
})
.
map
([](
int
x
)
{
return
x
*
3
;
})
.
for_each
([
&
outputs
](
int
x
)
{
outputs
.
emplace_back
(
x
);
},
.
do_on_error
([](
const
error
&
err
)
{
FAIL
(
"on_error: "
<<
err
);
})
[](
const
error
&
reason
)
{
.
do_on_complete
([
&
completed
]
{
completed
=
true
;
})
FAIL
(
"on_error called: "
<<
reason
);
.
for_each
([
&
outputs
](
int
x
)
{
outputs
.
emplace_back
(
x
);
});
},
[
&
completed
]
{
completed
=
true
;
});
ctx
->
run
();
ctx
->
run
();
CHECK
(
completed
);
CHECK
(
completed
);
CHECK_EQ
(
inputs
,
outputs
);
CHECK_EQ
(
inputs
,
outputs
);
...
...
libcaf_core/test/flow/generation.cpp
View file @
a78f55e3
...
@@ -149,7 +149,7 @@ SCENARIO("callable sources stream values generated from a function object") {
...
@@ -149,7 +149,7 @@ SCENARIO("callable sources stream values generated from a function object") {
namespace
{
namespace
{
class
custom_
pullable
{
class
custom_
generator
{
public:
public:
using
output_type
=
int
;
using
output_type
=
int
;
...
@@ -171,25 +171,24 @@ private:
...
@@ -171,25 +171,24 @@ private:
}
// namespace
}
// namespace
SCENARIO
(
"lifting converts a
Pullable
into an observable"
)
{
SCENARIO
(
"lifting converts a
generator
into an observable"
)
{
GIVEN
(
"a lifted implementation of the
Pullable
concept"
)
{
GIVEN
(
"a lifted implementation of the
generator
concept"
)
{
WHEN
(
"subscribing to its output"
)
{
WHEN
(
"subscribing to its output"
)
{
THEN
(
"the observer receives the generated values"
)
{
THEN
(
"the observer receives the generated values"
)
{
using
ivec
=
std
::
vector
<
int
>
;
using
ivec
=
std
::
vector
<
int
>
;
auto
snk
=
flow
::
make_passive_observer
<
int
>
();
auto
snk
=
flow
::
make_passive_observer
<
int
>
();
auto
f
=
custom_
pullable
{};
auto
f
=
custom_
generator
{};
ctx
->
make_observable
().
lift
(
f
).
subscribe
(
snk
->
as_observer
());
ctx
->
make_observable
().
from_generator
(
f
).
subscribe
(
snk
->
as_observer
());
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
subscribed
);
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
subscribed
);
CHECK
(
snk
->
buf
.
empty
());
CHECK
(
snk
->
buf
.
empty
());
if
(
CHECK
(
snk
->
sub
))
{
CHECK
(
snk
->
subscribed
());
snk
->
sub
.
request
(
3
);
snk
->
request
(
3
);
ctx
->
run
();
ctx
->
run
();
CHECK_EQ
(
snk
->
buf
,
ivec
({
1
,
2
,
3
}));
CHECK_EQ
(
snk
->
buf
,
ivec
({
1
,
2
,
3
}));
snk
->
sub
.
request
(
21
);
snk
->
sub
.
request
(
21
);
ctx
->
run
();
ctx
->
run
();
CHECK_EQ
(
snk
->
buf
,
ivec
({
1
,
2
,
3
,
4
,
5
,
6
,
7
}));
CHECK_EQ
(
snk
->
buf
,
ivec
({
1
,
2
,
3
,
4
,
5
,
6
,
7
}));
CHECK_EQ
(
snk
->
state
,
flow
::
observer_state
::
completed
);
CHECK
(
snk
->
completed
());
}
}
}
}
}
}
}
...
...
libcaf_core/test/flow/prefix_and_tail.cpp
View file @
a78f55e3
...
@@ -34,7 +34,7 @@ auto ls(T x, Ts... xs) {
...
@@ -34,7 +34,7 @@ auto ls(T x, Ts... xs) {
BEGIN_FIXTURE_SCOPE
(
fixture
)
BEGIN_FIXTURE_SCOPE
(
fixture
)
SCENARIO
(
"prefix_and_tail splits off initial elements"
)
{
SCENARIO
(
"prefix_and_tail splits off initial elements"
)
{
using
tuple_t
=
cow_tuple
<
std
::
vector
<
int
>
,
flow
::
observable
<
int
>>
;
using
tuple_t
=
cow_tuple
<
cow_
vector
<
int
>
,
flow
::
observable
<
int
>>
;
GIVEN
(
"a generation with 0 values"
)
{
GIVEN
(
"a generation with 0 values"
)
{
WHEN
(
"calling prefix_and_tail(2)"
)
{
WHEN
(
"calling prefix_and_tail(2)"
)
{
THEN
(
"the observer of prefix_and_tail only receives on_complete"
)
{
THEN
(
"the observer of prefix_and_tail only receives on_complete"
)
{
...
...
libcaf_core/test/response_handle.cpp
View file @
a78f55e3
...
@@ -72,13 +72,12 @@ SCENARIO("response handles are convertible to observables and singles") {
...
@@ -72,13 +72,12 @@ SCENARIO("response handles are convertible to observables and singles") {
auto
[
self
,
launch
]
=
sys
.
spawn_inactive
<
event_based_actor
>
();
auto
[
self
,
launch
]
=
sys
.
spawn_inactive
<
event_based_actor
>
();
self
->
request
(
dummy
,
infinite
,
int32_t
{
42
})
self
->
request
(
dummy
,
infinite
,
int32_t
{
42
})
.
as_observable
<
int32_t
>
()
.
as_observable
<
int32_t
>
()
.
for_each
(
.
do_on_error
([
&
](
const
error
&
what
)
{
result
=
what
;
})
[
&
](
int32_t
val
)
{
.
do_on_complete
([
&
]
{
completed
=
true
;
})
.
for_each
([
&
](
int32_t
val
)
{
result
=
val
;
result
=
val
;
++
on_next_calls
;
++
on_next_calls
;
},
});
[
&
](
const
error
&
what
)
{
result
=
what
;
},
[
&
]
{
completed
=
true
;
});
auto
aut
=
actor
{
self
};
auto
aut
=
actor
{
self
};
launch
();
launch
();
expect
((
int32_t
),
from
(
aut
).
to
(
dummy
).
with
(
42
));
expect
((
int32_t
),
from
(
aut
).
to
(
dummy
).
with
(
42
));
...
@@ -117,13 +116,12 @@ SCENARIO("response handles are convertible to observables and singles") {
...
@@ -117,13 +116,12 @@ SCENARIO("response handles are convertible to observables and singles") {
auto
[
self
,
launch
]
=
sys
.
spawn_inactive
<
event_based_actor
>
();
auto
[
self
,
launch
]
=
sys
.
spawn_inactive
<
event_based_actor
>
();
self
->
request
(
dummy
,
infinite
,
int32_t
{
13
})
self
->
request
(
dummy
,
infinite
,
int32_t
{
13
})
.
as_observable
<
int32_t
>
()
.
as_observable
<
int32_t
>
()
.
for_each
(
.
do_on_error
([
&
](
const
error
&
what
)
{
result
=
what
;
})
[
&
](
int32_t
val
)
{
.
do_on_complete
([
&
]
{
completed
=
true
;
})
.
for_each
([
&
](
int32_t
val
)
{
result
=
val
;
result
=
val
;
++
on_next_calls
;
++
on_next_calls
;
},
});
[
&
](
const
error
&
what
)
{
result
=
what
;
},
[
&
]
{
completed
=
true
;
});
auto
aut
=
actor
{
self
};
auto
aut
=
actor
{
self
};
launch
();
launch
();
expect
((
int32_t
),
from
(
aut
).
to
(
dummy
).
with
(
13
));
expect
((
int32_t
),
from
(
aut
).
to
(
dummy
).
with
(
13
));
...
...
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