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
07dcd1e6
Commit
07dcd1e6
authored
Aug 01, 2018
by
Dominik Charousset
Committed by
Dominik Charousset
Aug 02, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove test_coordinator::run_cycle, refine DSL API
parent
0935d0e3
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
90 additions
and
121 deletions
+90
-121
libcaf_core/caf/detail/test_actor_clock.hpp
libcaf_core/caf/detail/test_actor_clock.hpp
+5
-0
libcaf_core/caf/scheduler/test_coordinator.hpp
libcaf_core/caf/scheduler/test_coordinator.hpp
+5
-17
libcaf_core/src/test_coordinator.cpp
libcaf_core/src/test_coordinator.cpp
+9
-51
libcaf_core/src/tick_emitter.cpp
libcaf_core/src/tick_emitter.cpp
+2
-1
libcaf_core/test/continuous_streaming.cpp
libcaf_core/test/continuous_streaming.cpp
+1
-1
libcaf_core/test/pipeline_streaming.cpp
libcaf_core/test/pipeline_streaming.cpp
+2
-2
libcaf_test/caf/test/dsl.hpp
libcaf_test/caf/test/dsl.hpp
+66
-49
No files found.
libcaf_core/caf/detail/test_actor_clock.hpp
View file @
07dcd1e6
...
...
@@ -34,6 +34,11 @@ public:
duration_type
difference
(
atom_value
measurement
,
long
units
,
time_point
t0
,
time_point
t1
)
const
noexcept
override
;
/// Returns whether the actor clock has at least one pending timeout.
bool
has_pending_timeout
()
const
{
return
!
schedule_
.
empty
();
}
/// Triggers the next pending timeout regardless of its timestamp. Sets
/// `current_time` to the time point of the triggered timeout unless
/// `current_time` is already set to a later time.
...
...
libcaf_core/caf/scheduler/test_coordinator.hpp
View file @
07dcd1e6
...
...
@@ -105,6 +105,11 @@ public:
/// left. Returns the number of processed events.
size_t
run
(
size_t
max_count
=
std
::
numeric_limits
<
size_t
>::
max
());
/// Returns whether at least one pending timeout exists.
bool
has_pending_timeout
()
const
{
return
clock_
.
has_pending_timeout
();
}
/// Tries to trigger a single timeout.
bool
trigger_timeout
()
{
return
clock_
.
trigger_timeout
();
...
...
@@ -120,23 +125,6 @@ public:
return
clock_
.
advance_time
(
x
);
}
/// Runs all events, then advances the time by `cycle_duration` and triggers
/// all timeouts, then repeats until no activity remains.
/// @param predicate Stop condition.
/// @param cycle_duration
/// @returns The number of scheduling events (first) and the number of
/// triggered timeouts (second).
/// messages (second). Advances time by `cycle` nanoseconds between to calls
/// to `dispatch()` or the default tick-duration when passing 0ns.
std
::
pair
<
size_t
,
size_t
>
run_cycle_until
(
bool_predicate
predicate
,
timespan
cycle_duration
);
/// Loops until no job or delayed message remains. Returns the total number
/// of events (first) and dispatched delayed messages (second). Advances time
/// by `cycle` nanoseconds between to calls to `dispatch()` or the default
/// tick-duration when passing 0ns.
std
::
pair
<
size_t
,
size_t
>
run_cycle
(
timespan
cycle_duration
=
timespan
{
1
});
template
<
class
F
>
void
after_next_enqueue
(
F
f
)
{
after_next_enqueue_
=
f
;
...
...
libcaf_core/src/test_coordinator.cpp
View file @
07dcd1e6
...
...
@@ -87,7 +87,8 @@ void test_coordinator::start() {
}
void
test_coordinator
::
stop
()
{
run_cycle
();
while
(
run
()
>
0
)
trigger_timeouts
();
}
void
test_coordinator
::
enqueue
(
resumable
*
ptr
)
{
...
...
@@ -147,55 +148,6 @@ size_t test_coordinator::run(size_t max_count) {
return
res
;
}
std
::
pair
<
size_t
,
size_t
>
test_coordinator
::
run_cycle_until
(
bool_predicate
predicate
,
timespan
cycle_duration
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
cycle_duration
)
<<
CAF_ARG2
(
"pending_jobs"
,
jobs
.
size
())
<<
CAF_ARG2
(
"pending_timeouts"
,
clock_
.
schedule
().
size
()));
// Bookkeeping.
size_t
events
=
0
;
size_t
timeouts
=
0
;
// Loop until no activity remains.
while
(
!
jobs
.
empty
()
||
!
clock_
.
schedule
().
empty
())
{
while
(
try_run_once
())
{
++
events
;
if
(
predicate
())
{
CAF_LOG_DEBUG
(
"stop due to predicate;"
<<
CAF_ARG
(
events
)
<<
CAF_ARG
(
timeouts
));
return
{
events
,
timeouts
};
}
}
if
(
!
clock_
.
schedule
().
empty
())
{
size_t
triggered
=
0
;
auto
next_tout
=
clock_
.
schedule
().
begin
()
->
first
;
if
(
next_tout
<=
clock_
.
now
())
{
// Trigger expired timeout first without advancing time.
triggered
=
clock_
.
trigger_expired_timeouts
();
}
else
{
// Compute how much cycles we need to trigger at least one timeout.
auto
diff
=
next_tout
-
clock_
.
current_time
;
auto
num_cycles
=
diff
.
count
()
/
cycle_duration
.
count
();
auto
advancement
=
num_cycles
*
cycle_duration
;
// `num_cyles` can have one to few cycles since we's always rounding down.
if
(
clock_
.
current_time
+
advancement
<
next_tout
)
advancement
+=
cycle_duration
;
// Advance time.
CAF_ASSERT
(
advancement
.
count
()
>
0
);
triggered
=
clock_
.
advance_time
(
advancement
);
}
CAF_ASSERT
(
triggered
>
0
);
timeouts
+=
triggered
;
}
}
CAF_LOG_DEBUG
(
"no activity left;"
<<
CAF_ARG
(
events
)
<<
CAF_ARG
(
timeouts
));
return
{
events
,
timeouts
};
}
std
::
pair
<
size_t
,
size_t
>
test_coordinator
::
run_cycle
(
timespan
cycle_duration
)
{
return
run_cycle_until
([]
{
return
false
;
},
cycle_duration
);
}
void
test_coordinator
::
inline_next_enqueue
()
{
after_next_enqueue
([
=
]
{
run_once_lifo
();
});
}
...
...
@@ -211,7 +163,13 @@ void test_coordinator::inline_all_enqueues_helper() {
std
::
pair
<
size_t
,
size_t
>
test_coordinator
::
run_dispatch_loop
(
timespan
cycle_duration
)
{
return
run_cycle
(
cycle_duration
);
size_t
messages
=
0
;
size_t
timeouts
=
0
;
while
(
has_job
()
||
has_pending_timeout
())
{
messages
+=
run
();
timeouts
+=
advance_time
(
cycle_duration
);
}
return
{
messages
,
timeouts
};
}
}
// namespace caf
...
...
libcaf_core/src/tick_emitter.cpp
View file @
07dcd1e6
...
...
@@ -56,7 +56,8 @@ void tick_emitter::interval(duration_type x) {
size_t
tick_emitter
::
timeouts
(
time_point
now
,
std
::
initializer_list
<
size_t
>
periods
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
now
)
<<
CAF_ARG
(
periods
)
<<
CAF_ARG
(
interval_
)
<<
CAF_ARG
(
start_
));
CAF_LOG_TRACE
(
CAF_ARG
(
now
)
<<
CAF_ARG
(
periods
)
<<
CAF_ARG
(
interval_
)
<<
CAF_ARG
(
start_
));
CAF_ASSERT
(
now
>=
start_
);
size_t
result
=
0
;
auto
f
=
[
&
](
size_t
tick
)
{
...
...
libcaf_core/test/continuous_streaming.cpp
View file @
07dcd1e6
...
...
@@ -221,7 +221,7 @@ CAF_TEST(closing_downstreams_before_end_of_stream) {
CAF_CHECK_EQUAL
(
st
.
stage
->
out
().
num_paths
(),
2u
);
CAF_CHECK_EQUAL
(
st
.
stage
->
inbound_paths
().
size
(),
1u
);
CAF_MESSAGE
(
"do a single round of credit"
);
t
ick
();
t
rigger_timeouts
();
consume_messages
();
CAF_MESSAGE
(
"make sure the stream isn't done yet"
);
CAF_REQUIRE
(
!
deref
<
file_reader_actor
>
(
src
).
state
.
buf
.
empty
());
...
...
libcaf_core/test/pipeline_streaming.cpp
View file @
07dcd1e6
...
...
@@ -212,8 +212,8 @@ TESTEE(doubler) {
}
struct
fixture
:
test_coordinator_fixture
<>
{
timespan
tick_duration
()
const
override
{
return
credit_round_interval
;
void
tick
()
{
advance_time
(
cfg
.
streaming_credit_round_interval
())
;
}
};
...
...
libcaf_test/caf/test/dsl.hpp
View file @
07dcd1e6
...
...
@@ -551,9 +551,6 @@ public:
/// A deterministic scheduler type.
using
scheduler_type
=
caf
::
scheduler
::
test_coordinator
;
/// Callback for boolean predicates.
using
bool_predicate
=
std
::
function
<
bool
()
>
;
// -- constructors, destructors, and assignment operators --------------------
template
<
class
...
Ts
>
...
...
@@ -569,7 +566,7 @@ public:
sched
.
clock
().
time_per_unit
.
emplace
(
caf
::
atom
(
"batch"
),
caf
::
timespan
{
1000
});
// Make sure the current time isn't 0.
sched
.
clock
().
current_time
+=
tick_duration
(
);
sched
.
clock
().
current_time
+=
std
::
chrono
::
hours
(
1
);
credit_round_interval
=
cfg
.
streaming_credit_round_interval
();
}
...
...
@@ -579,33 +576,26 @@ public:
// -- DSL functions ----------------------------------------------------------
/// Returns the duration of a single clock tick.
virtual
caf
::
timespan
tick_duration
()
const
{
return
cfg
.
streaming_tick_duration
();
}
/// Advances the clock by a single tick duration.
size_t
advance_time
(
caf
::
timespan
interval
)
{
return
sched
.
clock
().
advance_time
(
interval
);
}
/// Allows the next actor to consume one message from its mailbox.
/// @returns Whether a message was consumed.
bool
consume_message
()
{
return
sched
.
try_run_once
();
/// Allows the next actor to consume one message from its mailbox. Fails the
/// test if no message was consumed.
void
consume_message
()
{
if
(
!
sched
.
try_run_once
())
CAF_FAIL
(
"no message to consume"
);
}
/// Allows each actors to consume all messages from its mailbox.
/// Allows each actors to consume all messages from its mailbox. Fails the
/// test if no message was consumed.
/// @returns The number of consumed messages.
size_t
consume_messages
()
{
return
sched
.
run
();
}
/// Advances the clock by `tick_duration()` and tries dispatching all pending
/// timeouts.
/// @returns The number of triggered timeouts.
size_t
tick
()
{
return
advance_time
(
tick_duration
());
auto
result
=
sched
.
run
();
if
(
result
==
0
)
CAF_FAIL
(
"no message to consume"
);
return
result
;
}
/// Consume messages and trigger timeouts until no activity remains.
...
...
@@ -618,10 +608,26 @@ public:
/// Consume messages and trigger timeouts until `pred` becomes `true` or
/// until no activity remains.
/// @returns The total number of events, i.e., messages consumed and
/// timeouts triggerd.
size_t
run_until
(
bool_predicate
pred
)
{
auto
res
=
sched
.
run_cycle_until
(
pred
,
tick_duration
());
return
res
.
first
+
res
.
second
;
/// timeouts triggered.
template
<
class
BoolPredicate
>
size_t
run_until
(
BoolPredicate
predicate
)
{
CAF_LOG_TRACE
(
""
);
// Bookkeeping.
size_t
events
=
0
;
// Loop until no activity remains.
while
(
sched
.
has_job
()
||
sched
.
has_pending_timeout
())
{
while
(
sched
.
try_run_once
())
{
++
events
;
if
(
predicate
())
{
CAF_LOG_DEBUG
(
"stop due to predicate:"
<<
CAF_ARG
(
events
));
return
events
;
}
}
if
(
trigger_timeout
())
++
events
;
}
CAF_LOG_DEBUG
(
"no activity left:"
<<
CAF_ARG
(
events
));
return
events
;
}
/// Call `run()` when the next scheduled actor becomes ready.
...
...
@@ -630,7 +636,8 @@ public:
}
/// Call `run_until(predicate)` when the next scheduled actor becomes ready.
void
run_until_after_next_ready_event
(
bool_predicate
predicate
)
{
template
<
class
BoolPredicate
>
void
run_until_after_next_ready_event
(
BoolPredicate
predicate
)
{
sched
.
after_next_enqueue
([
=
]
{
run_until
(
predicate
);
});
}
...
...
@@ -659,19 +666,19 @@ public:
return
dynamic_cast
<
T
&>
(
*
ptr
);
}
/// Tries to advance the simulation, e.g., by handling the next message or
/// mocking some network activity.
/// @private
virtual
bool
advance
()
{
return
sched
.
try_run_once
();
}
/// Tries to trigger a timeout.
/// @private
/// Triggers the next pending timeout.
virtual
bool
trigger_timeout
()
{
return
sched
.
trigger_timeout
();
}
/// Triggers all pending timeouts.
size_t
trigger_timeouts
()
{
size_t
timeouts
=
0
;
while
(
trigger_timeout
())
++
timeouts
;
return
timeouts
;
}
// -- member variables -------------------------------------------------------
/// The user-generated system config.
...
...
@@ -686,25 +693,35 @@ public:
/// Deterministic scheduler.
scheduler_type
&
sched
;
// -- deprecated function
s ----
-----------------------------------------------
// -- deprecated function
ality
-----------------------------------------------
caf
::
timespan
credit_round_interval
CAF_DEPRECATED
;
void
run_exhaustively
()
CAF_DEPRECATED_MSG
(
"use run() instead"
)
;
void
run_exhaustively
()
CAF_DEPRECATED_MSG
(
"use run() instead"
)
{
run_exhaustively_until
([]
{
return
false
;
});
}
void
run_exhaustively_until
(
bool_predicate
predicate
)
CAF_DEPRECATED_MSG
(
"use run_until() instead"
)
{
sched
.
run_cycle_until
(
predicate
,
credit_round_interval
);
}
void
run_exhaustively_until
(
std
::
function
<
bool
()
>
f
)
CAF_DEPRECATED_MSG
(
"use run_until() instead"
);
void
loop_after_next_enqueue
()
CAF_DEPRECATED_MSG
(
"use run_after_next_ready_event() instead"
)
{
sched
.
after_next_enqueue
([
=
]
{
run
();
});
}
CAF_DEPRECATED_MSG
(
"use run_after_next_ready_event() instead"
)
;
caf
::
timespan
credit_round_interval
CAF_DEPRECATED
;
};
template
<
class
Config
>
void
test_coordinator_fixture
<
Config
>::
run_exhaustively
()
{
run
();
}
template
<
class
Config
>
void
test_coordinator_fixture
<
Config
>::
run_exhaustively_until
(
std
::
function
<
bool
()
>
f
)
{
run_until
(
std
::
move
(
f
));
}
template
<
class
Config
>
void
test_coordinator_fixture
<
Config
>::
loop_after_next_enqueue
()
{
sched
.
after_next_enqueue
([
=
]
{
run
();
});
}
/// Unboxes an expected value or fails the test if it doesn't exist.
template
<
class
T
>
T
unbox
(
caf
::
expected
<
T
>
x
)
{
...
...
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