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
b23bf288
Commit
b23bf288
authored
Sep 04, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow actors to consume all upstream msgs at once
parent
8ec58ee2
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
295 additions
and
284 deletions
+295
-284
libcaf_core/caf/policy/categorized.hpp
libcaf_core/caf/policy/categorized.hpp
+8
-0
libcaf_core/caf/scheduled_actor.hpp
libcaf_core/caf/scheduled_actor.hpp
+31
-52
libcaf_core/src/inbound_path.cpp
libcaf_core/src/inbound_path.cpp
+0
-2
libcaf_core/src/scheduled_actor.cpp
libcaf_core/src/scheduled_actor.cpp
+184
-155
libcaf_core/src/stream_manager.cpp
libcaf_core/src/stream_manager.cpp
+6
-7
libcaf_core/test/continuous_streaming.cpp
libcaf_core/test/continuous_streaming.cpp
+55
-51
libcaf_core/test/native_streaming_classes.cpp
libcaf_core/test/native_streaming_classes.cpp
+9
-1
libcaf_core/test/pipeline_streaming.cpp
libcaf_core/test/pipeline_streaming.cpp
+2
-16
No files found.
libcaf_core/caf/policy/categorized.hpp
View file @
b23bf288
...
@@ -67,6 +67,14 @@ public:
...
@@ -67,6 +67,14 @@ public:
return
x
+
x
;
return
x
+
x
;
}
}
template
<
template
<
class
>
class
Queue
>
static
deficit_type
quantum
(
const
Queue
<
upstream_messages
>&
q
,
deficit_type
)
noexcept
{
// Allow actors to consume *all* upstream messages. They are lightweight by
// design and require little processing.
return
q
.
total_task_size
();
}
template
<
class
Queue
>
template
<
class
Queue
>
static
deficit_type
quantum
(
const
Queue
&
,
deficit_type
x
)
noexcept
{
static
deficit_type
quantum
(
const
Queue
&
,
deficit_type
x
)
noexcept
{
return
x
;
return
x
;
...
...
libcaf_core/caf/scheduled_actor.hpp
View file @
b23bf288
...
@@ -200,52 +200,6 @@ public:
...
@@ -200,52 +200,6 @@ public:
using
exception_handler
=
std
::
function
<
error
(
pointer
,
std
::
exception_ptr
&
)
>
;
using
exception_handler
=
std
::
function
<
error
(
pointer
,
std
::
exception_ptr
&
)
>
;
#endif // CAF_ENABLE_EXCEPTIONS
#endif // CAF_ENABLE_EXCEPTIONS
/// Consumes messages from the mailbox.
struct
mailbox_visitor
{
scheduled_actor
*
self
;
size_t
&
handled_msgs
;
size_t
max_throughput
;
bool
collect_metrics
;
/// Consumes upstream messages.
intrusive
::
task_result
operator
()(
size_t
,
upstream_queue
&
,
mailbox_element
&
);
/// Consumes downstream messages.
intrusive
::
task_result
operator
()(
size_t
,
downstream_queue
&
,
stream_slot
slot
,
policy
::
downstream_messages
::
nested_queue_type
&
,
mailbox_element
&
);
// Dispatches asynchronous messages with high and normal priority to the
// same handler.
template
<
class
Queue
>
intrusive
::
task_result
operator
()(
size_t
,
Queue
&
,
mailbox_element
&
x
)
{
return
(
*
this
)(
x
);
}
// Consumes asynchronous messages.
intrusive
::
task_result
operator
()(
mailbox_element
&
x
);
template
<
class
F
>
intrusive
::
task_result
run
(
mailbox_element
&
x
,
F
body
)
{
if
(
collect_metrics
)
{
auto
t0
=
std
::
chrono
::
steady_clock
::
now
();
auto
mbox_time
=
x
.
seconds_until
(
t0
);
auto
res
=
body
();
if
(
res
!=
intrusive
::
task_result
::
skip
)
{
auto
&
builtins
=
self
->
builtin_metrics
();
telemetry
::
timer
::
observe
(
builtins
.
processing_time
,
t0
);
builtins
.
mailbox_time
->
observe
(
mbox_time
);
builtins
.
mailbox_size
->
dec
();
}
return
res
;
}
else
{
return
body
();
}
}
};
// -- static helper functions ------------------------------------------------
// -- static helper functions ------------------------------------------------
static
void
default_error_handler
(
pointer
ptr
,
error
&
x
);
static
void
default_error_handler
(
pointer
ptr
,
error
&
x
);
...
@@ -517,6 +471,9 @@ public:
...
@@ -517,6 +471,9 @@ public:
/// Pushes `ptr` to the cache of the default queue.
/// Pushes `ptr` to the cache of the default queue.
void
push_to_cache
(
mailbox_element_ptr
ptr
);
void
push_to_cache
(
mailbox_element_ptr
ptr
);
/// Returns the queue of the mailbox that stores high priority messages.
urgent_queue
&
get_urgent_queue
();
/// Returns the default queue of the mailbox that stores ordinary messages.
/// Returns the default queue of the mailbox that stores ordinary messages.
normal_queue
&
get_normal_queue
();
normal_queue
&
get_normal_queue
();
...
@@ -526,9 +483,6 @@ public:
...
@@ -526,9 +483,6 @@ public:
/// Returns the queue of the mailbox that stores `downstream_msg` messages.
/// Returns the queue of the mailbox that stores `downstream_msg` messages.
downstream_queue
&
get_downstream_queue
();
downstream_queue
&
get_downstream_queue
();
/// Returns the queue of the mailbox that stores high priority messages.
urgent_queue
&
get_urgent_queue
();
// -- inbound_path management ------------------------------------------------
// -- inbound_path management ------------------------------------------------
/// Creates a new path for incoming stream traffic from `sender`.
/// Creates a new path for incoming stream traffic from `sender`.
...
@@ -569,8 +523,7 @@ public:
...
@@ -569,8 +523,7 @@ public:
return
;
return
;
}
}
CAF_LOG_INFO
(
"no manager found:"
<<
CAF_ARG
(
slots
));
CAF_LOG_INFO
(
"no manager found:"
<<
CAF_ARG
(
slots
));
// TODO: replace with `if constexpr` when switching to C++17
if
constexpr
(
std
::
is_same
<
T
,
upstream_msg
::
ack_batch
>::
value
)
{
if
(
std
::
is_same
<
T
,
upstream_msg
::
ack_batch
>::
value
)
{
// Make sure the other actor does not falsely believe us a source.
// Make sure the other actor does not falsely believe us a source.
inbound_path
::
emit_irregular_shutdown
(
this
,
slots
,
current_sender
(),
inbound_path
::
emit_irregular_shutdown
(
this
,
slots
,
current_sender
(),
sec
::
invalid_upstream
);
sec
::
invalid_upstream
);
...
@@ -657,6 +610,12 @@ public:
...
@@ -657,6 +610,12 @@ public:
/// Removes the stream manager mapped to `id` in `O(log n)`.
/// Removes the stream manager mapped to `id` in `O(log n)`.
void
erase_pending_stream_manager
(
stream_slot
id
);
void
erase_pending_stream_manager
(
stream_slot
id
);
/// Moves a pending stream manager to the list of active stream managers.
/// @returns `true` and a pointer to the moved stream manager on success,
/// `false` and `nullptr` otherwise.
[[
nodiscard
]]
std
::
pair
<
bool
,
stream_manager
*>
ack_pending_stream_manager
(
stream_slot
id
);
/// Removes all entries for `mgr` in `O(n)`.
/// Removes all entries for `mgr` in `O(n)`.
void
erase_stream_manager
(
const
stream_manager_ptr
&
mgr
);
void
erase_stream_manager
(
const
stream_manager_ptr
&
mgr
);
...
@@ -683,6 +642,10 @@ public:
...
@@ -683,6 +642,10 @@ public:
return
max_batch_delay_
;
return
max_batch_delay_
;
}
}
void
active_stream_managers
(
std
::
vector
<
stream_manager
*>&
result
);
std
::
vector
<
stream_manager
*>
active_stream_managers
();
/// @endcond
/// @endcond
protected:
protected:
...
@@ -746,7 +709,23 @@ protected:
...
@@ -746,7 +709,23 @@ protected:
exception_handler
exception_handler_
;
exception_handler
exception_handler_
;
#endif // CAF_ENABLE_EXCEPTIONS
#endif // CAF_ENABLE_EXCEPTIONS
/// @endcond
private:
template
<
class
F
>
intrusive
::
task_result
run_with_metrics
(
mailbox_element
&
x
,
F
body
)
{
if
(
metrics_
.
mailbox_time
)
{
auto
t0
=
std
::
chrono
::
steady_clock
::
now
();
auto
mbox_time
=
x
.
seconds_until
(
t0
);
auto
res
=
body
();
if
(
res
!=
intrusive
::
task_result
::
skip
)
{
telemetry
::
timer
::
observe
(
metrics_
.
processing_time
,
t0
);
metrics_
.
mailbox_time
->
observe
(
mbox_time
);
metrics_
.
mailbox_size
->
dec
();
}
return
res
;
}
else
{
return
body
();
}
}
};
};
}
// namespace caf
}
// namespace caf
libcaf_core/src/inbound_path.cpp
View file @
b23bf288
...
@@ -113,8 +113,6 @@ void inbound_path::handle(downstream_msg::batch& batch) {
...
@@ -113,8 +113,6 @@ void inbound_path::handle(downstream_msg::batch& batch) {
if
(
auto
available
=
available_credit
();
available
>=
desired_batch_size
)
if
(
auto
available
=
available_credit
();
available
>=
desired_batch_size
)
if
(
auto
acquired
=
mgr
->
acquire_credit
(
this
,
available
);
acquired
>
0
)
if
(
auto
acquired
=
mgr
->
acquire_credit
(
this
,
available
);
acquired
>
0
)
emit_ack_batch
(
self
(),
acquired
);
emit_ack_batch
(
self
(),
acquired
);
// FIXME: move this up to the actor
mgr
->
push
();
}
}
void
inbound_path
::
tick
(
time_point
now
,
duration_type
max_batch_delay
)
{
void
inbound_path
::
tick
(
time_point
now
,
duration_type
max_batch_delay
)
{
...
...
libcaf_core/src/scheduled_actor.cpp
View file @
b23bf288
This diff is collapsed.
Click to expand it.
libcaf_core/src/stream_manager.cpp
View file @
b23bf288
...
@@ -92,15 +92,13 @@ bool stream_manager::handle(stream_slots slots, upstream_msg::ack_open& x) {
...
@@ -92,15 +92,13 @@ bool stream_manager::handle(stream_slots slots, upstream_msg::ack_open& x) {
CAF_ASSERT
(
ptr
->
open_credit
>=
0
);
CAF_ASSERT
(
ptr
->
open_credit
>=
0
);
ptr
->
set_desired_batch_size
(
x
.
desired_batch_size
);
ptr
->
set_desired_batch_size
(
x
.
desired_batch_size
);
--
pending_handshakes_
;
--
pending_handshakes_
;
push
();
return
true
;
return
true
;
}
}
void
stream_manager
::
handle
(
stream_slots
slots
,
upstream_msg
::
ack_batch
&
x
)
{
void
stream_manager
::
handle
(
stream_slots
slots
,
upstream_msg
::
ack_batch
&
x
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
slots
)
<<
CAF_ARG
(
x
));
CAF_LOG_TRACE
(
CAF_ARG
(
slots
)
<<
CAF_ARG
(
x
));
CAF_ASSERT
(
x
.
desired_batch_size
>
0
);
CAF_ASSERT
(
x
.
desired_batch_size
>
0
);
auto
path
=
out
().
path
(
slots
.
receiver
);
if
(
auto
path
=
out
().
path
(
slots
.
receiver
);
path
!=
nullptr
)
{
if
(
path
!=
nullptr
)
{
path
->
open_credit
+=
x
.
new_capacity
;
path
->
open_credit
+=
x
.
new_capacity
;
CAF_ASSERT
(
path
->
open_credit
>=
0
);
CAF_ASSERT
(
path
->
open_credit
>=
0
);
path
->
set_desired_batch_size
(
x
.
desired_batch_size
);
path
->
set_desired_batch_size
(
x
.
desired_batch_size
);
...
@@ -108,7 +106,6 @@ void stream_manager::handle(stream_slots slots, upstream_msg::ack_batch& x) {
...
@@ -108,7 +106,6 @@ void stream_manager::handle(stream_slots slots, upstream_msg::ack_batch& x) {
// Gravefully remove path after receiving its final ACK.
// Gravefully remove path after receiving its final ACK.
if
(
path
->
closing
&&
out
().
clean
(
slots
.
receiver
))
if
(
path
->
closing
&&
out
().
clean
(
slots
.
receiver
))
out
().
remove_path
(
slots
.
receiver
,
none
,
false
);
out
().
remove_path
(
slots
.
receiver
,
none
,
false
);
push
();
}
}
}
}
...
@@ -300,9 +297,11 @@ stream_manager::add_unchecked_inbound_path_impl(type_id_t input_type,
...
@@ -300,9 +297,11 @@ stream_manager::add_unchecked_inbound_path_impl(type_id_t input_type,
}
}
void
stream_manager
::
tick
(
time_point
now
)
{
void
stream_manager
::
tick
(
time_point
now
)
{
for
(
auto
path
:
inbound_paths_
)
do
{
path
->
tick
(
now
,
max_batch_delay_
);
out
().
tick
(
now
,
max_batch_delay_
);
out
().
tick
(
now
,
max_batch_delay_
);
for
(
auto
path
:
inbound_paths_
)
path
->
tick
(
now
,
max_batch_delay_
);
}
while
(
generate_messages
());
}
}
stream_slot
stream_manager
::
assign_next_slot
()
{
stream_slot
stream_manager
::
assign_next_slot
()
{
...
...
libcaf_core/test/continuous_streaming.cpp
View file @
b23bf288
...
@@ -49,37 +49,39 @@ TESTEE_STATE(file_reader) {
...
@@ -49,37 +49,39 @@ TESTEE_STATE(file_reader) {
};
};
VARARGS_TESTEE
(
file_reader
,
size_t
buf_size
)
{
VARARGS_TESTEE
(
file_reader
,
size_t
buf_size
)
{
return
{[
=
](
string
&
fname
)
->
result
<
stream
<
int32_t
>
,
string
>
{
return
{
CAF_CHECK_EQUAL
(
fname
,
"numbers.txt"
);
[
=
](
string
&
fname
)
->
result
<
stream
<
int32_t
>
,
string
>
{
CAF_CHECK_EQUAL
(
self
->
mailbox
().
empty
(),
true
);
CAF_CHECK_EQUAL
(
fname
,
"numbers.txt"
);
return
attach_stream_source
(
CAF_CHECK_EQUAL
(
self
->
mailbox
().
empty
(),
true
);
self
,
return
attach_stream_source
(
// forward file name in handshake to next stage
self
,
std
::
forward_as_tuple
(
std
::
move
(
fname
)),
// forward file name in handshake to next stage
// initialize state
std
::
forward_as_tuple
(
std
::
move
(
fname
)),
[
=
](
unit_t
&
)
{
// initialize state
auto
&
xs
=
self
->
state
.
buf
;
[
=
](
unit_t
&
)
{
xs
.
resize
(
buf_size
);
auto
&
xs
=
self
->
state
.
buf
;
std
::
iota
(
xs
.
begin
(),
xs
.
end
(),
1
);
xs
.
resize
(
buf_size
);
},
std
::
iota
(
xs
.
begin
(),
xs
.
end
(),
1
);
// get next element
},
[
=
](
unit_t
&
,
downstream
<
int32_t
>&
out
,
size_t
num
)
{
// get next element
auto
&
xs
=
self
->
state
.
buf
;
[
=
](
unit_t
&
,
downstream
<
int32_t
>&
out
,
size_t
num
)
{
CAF_MESSAGE
(
"push "
<<
num
<<
" messages downstream"
);
auto
&
xs
=
self
->
state
.
buf
;
auto
n
=
std
::
min
(
num
,
xs
.
size
());
CAF_MESSAGE
(
"push "
<<
num
<<
" messages downstream"
);
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
auto
n
=
std
::
min
(
num
,
xs
.
size
());
out
.
push
(
xs
[
i
]);
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
xs
.
erase
(
xs
.
begin
(),
xs
.
begin
()
+
static_cast
<
ptrdiff_t
>
(
n
));
out
.
push
(
xs
[
i
]);
},
xs
.
erase
(
xs
.
begin
(),
xs
.
begin
()
+
static_cast
<
ptrdiff_t
>
(
n
));
// check whether we reached the end
},
[
=
](
const
unit_t
&
)
{
// check whether we reached the end
if
(
self
->
state
.
buf
.
empty
())
{
[
=
](
const
unit_t
&
)
{
CAF_MESSAGE
(
self
->
name
()
<<
" is done"
);
if
(
self
->
state
.
buf
.
empty
())
{
return
true
;
CAF_MESSAGE
(
self
->
name
()
<<
" is done"
);
}
return
true
;
return
false
;
}
});
return
false
;
}};
});
},
};
}
}
TESTEE_STATE
(
sum_up
)
{
TESTEE_STATE
(
sum_up
)
{
...
@@ -87,26 +89,28 @@ TESTEE_STATE(sum_up) {
...
@@ -87,26 +89,28 @@ TESTEE_STATE(sum_up) {
};
};
TESTEE
(
sum_up
)
{
TESTEE
(
sum_up
)
{
return
{[
=
](
stream
<
int32_t
>&
in
,
const
string
&
fname
)
{
return
{
CAF_CHECK_EQUAL
(
fname
,
"numbers.txt"
);
[
=
](
stream
<
int32_t
>&
in
,
const
string
&
fname
)
{
using
int_ptr
=
int32_t
*
;
CAF_CHECK_EQUAL
(
fname
,
"numbers.txt"
);
return
attach_stream_sink
(
using
int_ptr
=
int32_t
*
;
self
,
return
attach_stream_sink
(
// input stream
self
,
in
,
// input stream
// initialize state
in
,
[
=
](
int_ptr
&
x
)
{
x
=
&
self
->
state
.
x
;
},
// initialize state
// processing step
[
=
](
int_ptr
&
x
)
{
x
=
&
self
->
state
.
x
;
},
[](
int_ptr
&
x
,
int32_t
y
)
{
*
x
+=
y
;
},
// processing step
// cleanup
[](
int_ptr
&
x
,
int32_t
y
)
{
*
x
+=
y
;
},
[
=
](
int_ptr
&
,
const
error
&
)
{
// cleanup
CAF_MESSAGE
(
self
->
name
()
<<
" is done"
);
[
=
](
int_ptr
&
,
const
error
&
)
{
});
CAF_MESSAGE
(
self
->
name
()
<<
" is done"
);
},
});
[
=
](
join_atom
atm
,
actor
src
)
{
},
CAF_MESSAGE
(
self
->
name
()
<<
" joins a stream"
);
[
=
](
join_atom
atm
,
actor
src
)
{
self
->
send
(
self
*
src
,
atm
);
CAF_MESSAGE
(
self
->
name
()
<<
" joins a stream"
);
}};
self
->
send
(
self
*
src
,
atm
);
},
};
}
}
TESTEE_STATE
(
stream_multiplexer
)
{
TESTEE_STATE
(
stream_multiplexer
)
{
...
...
libcaf_core/test/native_streaming_classes.cpp
View file @
b23bf288
...
@@ -314,7 +314,7 @@ public:
...
@@ -314,7 +314,7 @@ public:
kvp
.
second
->
tick
(
now
());
kvp
.
second
->
tick
(
now
());
}
}
virtual
bool
add_inbound_path
(
type_id_t
input_type
,
virtual
bool
add_inbound_path
(
type_id_t
,
std
::
unique_ptr
<
inbound_path
>
path
)
override
{
std
::
unique_ptr
<
inbound_path
>
path
)
override
{
using
policy_type
=
policy
::
downstream_messages
::
nested
;
using
policy_type
=
policy
::
downstream_messages
::
nested
;
auto
res
=
get
<
dmsg_id
::
value
>
(
mbox
.
queues
())
auto
res
=
get
<
dmsg_id
::
value
>
(
mbox
.
queues
())
...
@@ -348,6 +348,13 @@ public:
...
@@ -348,6 +348,13 @@ public:
return
*
global_time_
;
return
*
global_time_
;
}
}
void
push
()
{
if
(
forwarder
)
forwarder
->
push
();
for
(
auto
mgr
:
active_stream_managers
())
mgr
->
push
();
}
// -- member variables -------------------------------------------------------
// -- member variables -------------------------------------------------------
mboxqueue
mbox
;
mboxqueue
mbox
;
...
@@ -402,6 +409,7 @@ struct msg_visitor {
...
@@ -402,6 +409,7 @@ struct msg_visitor {
);
);
visit
(
f
,
um
.
content
);
visit
(
f
,
um
.
content
);
self
->
current_mailbox_element
(
nullptr
);
self
->
current_mailbox_element
(
nullptr
);
self
->
push
();
return
intrusive
::
task_result
::
resume
;
return
intrusive
::
task_result
::
resume
;
}
}
...
...
libcaf_core/test/pipeline_streaming.cpp
View file @
b23bf288
...
@@ -394,12 +394,6 @@ CAF_TEST(depth_3_pipeline_50_items) {
...
@@ -394,12 +394,6 @@ CAF_TEST(depth_3_pipeline_50_items) {
auto
src
=
sys
.
spawn
(
file_reader
,
50u
);
auto
src
=
sys
.
spawn
(
file_reader
,
50u
);
auto
stg
=
sys
.
spawn
(
filter
);
auto
stg
=
sys
.
spawn
(
filter
);
auto
snk
=
sys
.
spawn
(
sum_up
);
auto
snk
=
sys
.
spawn
(
sum_up
);
auto
next_cycle
=
[
&
]
{
tick
();
allow
((
timeout_msg
),
from
(
snk
).
to
(
snk
));
allow
((
timeout_msg
),
from
(
stg
).
to
(
stg
));
allow
((
timeout_msg
),
from
(
src
).
to
(
src
));
};
CAF_MESSAGE
(
CAF_ARG
(
self
)
<<
CAF_ARG
(
src
)
<<
CAF_ARG
(
stg
)
<<
CAF_ARG
(
snk
));
CAF_MESSAGE
(
CAF_ARG
(
self
)
<<
CAF_ARG
(
src
)
<<
CAF_ARG
(
stg
)
<<
CAF_ARG
(
snk
));
CAF_MESSAGE
(
"initiate stream handshake"
);
CAF_MESSAGE
(
"initiate stream handshake"
);
self
->
send
(
snk
*
stg
*
src
,
"numbers.txt"
);
self
->
send
(
snk
*
stg
*
src
,
"numbers.txt"
);
...
@@ -412,17 +406,9 @@ CAF_TEST(depth_3_pipeline_50_items) {
...
@@ -412,17 +406,9 @@ CAF_TEST(depth_3_pipeline_50_items) {
expect
((
downstream_msg
::
batch
),
from
(
src
).
to
(
stg
));
expect
((
downstream_msg
::
batch
),
from
(
src
).
to
(
stg
));
CAF_MESSAGE
(
"the stage should delay its first batch since its underfull"
);
CAF_MESSAGE
(
"the stage should delay its first batch since its underfull"
);
disallow
((
downstream_msg
::
batch
),
from
(
stg
).
to
(
snk
));
disallow
((
downstream_msg
::
batch
),
from
(
stg
).
to
(
snk
));
next_cycle
();
CAF_MESSAGE
(
"after running the pipeline the sink received all batches"
);
CAF_MESSAGE
(
"the source shuts down and the stage sends the final batch"
);
run
();
expect
((
upstream_msg
::
ack_batch
),
from
(
stg
).
to
(
src
));
expect
((
downstream_msg
::
close
),
from
(
src
).
to
(
stg
));
expect
((
downstream_msg
::
batch
),
from
(
stg
).
to
(
snk
));
next_cycle
();
CAF_MESSAGE
(
"the stage shuts down and the sink produces its final result"
);
expect
((
upstream_msg
::
ack_batch
),
from
(
snk
).
to
(
stg
));
expect
((
downstream_msg
::
close
),
from
(
stg
).
to
(
snk
));
CAF_CHECK_EQUAL
(
deref
<
sum_up_actor
>
(
snk
).
state
.
x
,
625
);
CAF_CHECK_EQUAL
(
deref
<
sum_up_actor
>
(
snk
).
state
.
x
,
625
);
CAF_MESSAGE
(
"verify that each actor called its finalizer once"
);
CAF_CHECK_EQUAL
(
deref
<
file_reader_actor
>
(
src
).
state
.
fin_called
,
1
);
CAF_CHECK_EQUAL
(
deref
<
file_reader_actor
>
(
src
).
state
.
fin_called
,
1
);
CAF_CHECK_EQUAL
(
deref
<
filter_actor
>
(
stg
).
state
.
fin_called
,
1
);
CAF_CHECK_EQUAL
(
deref
<
filter_actor
>
(
stg
).
state
.
fin_called
,
1
);
CAF_CHECK_EQUAL
(
deref
<
sum_up_actor
>
(
snk
).
state
.
fin_called
,
1
);
CAF_CHECK_EQUAL
(
deref
<
sum_up_actor
>
(
snk
).
state
.
fin_called
,
1
);
...
...
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