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
64e2ee87
Commit
64e2ee87
authored
Feb 07, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve tick emitter
parent
8972ef8a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
194 additions
and
14 deletions
+194
-14
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+1
-0
libcaf_core/caf/detail/tick_emitter.hpp
libcaf_core/caf/detail/tick_emitter.hpp
+24
-9
libcaf_core/src/tick_emitter.cpp
libcaf_core/src/tick_emitter.cpp
+91
-0
libcaf_core/test/tick_emitter.cpp
libcaf_core/test/tick_emitter.cpp
+78
-5
No files found.
libcaf_core/CMakeLists.txt
View file @
64e2ee87
...
@@ -103,6 +103,7 @@ set (LIBCAF_CORE_SRCS
...
@@ -103,6 +103,7 @@ set (LIBCAF_CORE_SRCS
src/test_actor_clock.cpp
src/test_actor_clock.cpp
src/test_coordinator.cpp
src/test_coordinator.cpp
src/thread_safe_actor_clock.cpp
src/thread_safe_actor_clock.cpp
src/tick_emitter.cpp
src/timestamp.cpp
src/timestamp.cpp
src/try_match.cpp
src/try_match.cpp
src/type_erased_tuple.cpp
src/type_erased_tuple.cpp
...
...
libcaf_core/caf/detail/tick_emitter.hpp
View file @
64e2ee87
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#define CAF_DETAIL_TICK_EMITTER_HPP
#define CAF_DETAIL_TICK_EMITTER_HPP
#include <chrono>
#include <chrono>
#include <initializer_list>
#include "caf/config.hpp"
#include "caf/config.hpp"
...
@@ -45,17 +46,23 @@ public:
...
@@ -45,17 +46,23 @@ public:
// -- constructors, destructors, and assignment operators --------------------
// -- constructors, destructors, and assignment operators --------------------
tick_emitter
(
time_point
now
)
tick_emitter
();
:
start_
(
std
::
move
(
now
)),
interval_
(
0
),
last_tick_id_
(
0
)
{
// nop
}
void
interval
(
duration_type
x
)
{
tick_emitter
(
time_point
now
);
interval_
=
x
;
}
/// Queries whether the start time is non-default constructed.
bool
started
()
const
;
/// Configures the start time.
void
start
(
time_point
now
);
/// Resets the start time to 0.
void
stop
();
/// Configures the time interval per tick.
void
interval
(
duration_type
x
);
/// Advances time and calls `consumer` for each emitted tick.
template
<
class
F
>
template
<
class
F
>
void
update
(
time_point
now
,
F
&
consumer
)
{
void
update
(
time_point
now
,
F
&
consumer
)
{
CAF_ASSERT
(
interval_
.
count
()
!=
0
);
CAF_ASSERT
(
interval_
.
count
()
!=
0
);
...
@@ -65,6 +72,14 @@ public:
...
@@ -65,6 +72,14 @@ public:
consumer
(
++
last_tick_id_
);
consumer
(
++
last_tick_id_
);
}
}
/// Advances time by `t` and returns all triggered periods as bitmask.
long
timeouts
(
time_point
t
,
std
::
initializer_list
<
long
>
periods
);
/// Returns the next time point after `t` that would trigger any of the tick
/// periods, i.e., returns the next time where any of the tick periods
/// triggers `tick id % period == 0`.
time_point
next_timeout
(
time_point
t
,
std
::
initializer_list
<
long
>
periods
);
private:
private:
time_point
start_
;
time_point
start_
;
duration_type
interval_
;
duration_type
interval_
;
...
...
libcaf_core/src/tick_emitter.cpp
0 → 100644
View file @
64e2ee87
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2017 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/tick_emitter.hpp"
#include "caf/logger.hpp"
namespace
caf
{
namespace
detail
{
tick_emitter
::
tick_emitter
()
:
start_
(
duration_type
{
0
}),
interval_
(
0
),
last_tick_id_
(
0
)
{
// nop
}
tick_emitter
::
tick_emitter
(
time_point
now
)
:
tick_emitter
()
{
start
(
std
::
move
(
now
));
}
bool
tick_emitter
::
started
()
const
{
return
start_
.
time_since_epoch
().
count
()
!=
0
;
}
void
tick_emitter
::
start
(
time_point
now
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
now
));
start_
=
std
::
move
(
now
);
}
void
tick_emitter
::
stop
()
{
CAF_LOG_TRACE
(
""
);
start_
=
time_point
{
duration_type
{
0
}};
}
void
tick_emitter
::
interval
(
duration_type
x
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
x
));
interval_
=
x
;
}
long
tick_emitter
::
timeouts
(
time_point
now
,
std
::
initializer_list
<
long
>
periods
)
{
CAF_LOG_TRACE
(
CAF_ARG
(
now
)
<<
CAF_ARG
(
periods
));
long
result
=
0
;
auto
f
=
[
&
](
long
tick
)
{
long
n
=
0
;
for
(
auto
p
:
periods
)
{
if
(
tick
%
p
==
0
)
result
|=
1l
<<
n
;
++
n
;
}
};
update
(
now
,
f
);
return
result
;
}
tick_emitter
::
time_point
tick_emitter
::
next_timeout
(
time_point
t
,
std
::
initializer_list
<
long
>
periods
)
{
CAF_ASSERT
(
interval_
.
count
()
!=
0
);
auto
is_trigger
=
[
&
](
long
tick_id
)
{
for
(
auto
period
:
periods
)
if
(
tick_id
%
period
==
0
)
return
true
;
return
false
;
};
auto
diff
=
t
-
start_
;
auto
this_tick
=
diff
.
count
()
/
interval_
.
count
();
auto
tick_id
=
this_tick
+
1
;
while
(
!
is_trigger
(
tick_id
))
++
tick_id
;
return
start_
+
(
interval_
*
tick_id
);
}
}
// namespace detail
}
// namespace caf
libcaf_core/test/ti
me
_emitter.cpp
→
libcaf_core/test/ti
ck
_emitter.cpp
View file @
64e2ee87
...
@@ -29,10 +29,12 @@
...
@@ -29,10 +29,12 @@
// We mock just enough of an actor to use the streaming classes and put them to
// We mock just enough of an actor to use the streaming classes and put them to
// work in a pipeline with 2 or 3 stages.
// work in a pipeline with 2 or 3 stages.
#define CAF_SUITE ti
me
_emitter
#define CAF_SUITE ti
ck
_emitter
#include <vector>
#include <vector>
#include "caf/timestamp.hpp"
#include "caf/detail/gcd.hpp"
#include "caf/detail/gcd.hpp"
#include "caf/detail/tick_emitter.hpp"
#include "caf/detail/tick_emitter.hpp"
...
@@ -42,16 +44,36 @@ using std::vector;
...
@@ -42,16 +44,36 @@ using std::vector;
using
namespace
caf
;
using
namespace
caf
;
using
time_point
=
caf
::
detail
::
tick_emitter
::
time_point
;
namespace
{
timespan
credit_interval
{
200
};
timespan
force_batch_interval
{
50
};
}
// namespace <anonymous>
CAF_TEST
(
start_and_stop
)
{
detail
::
tick_emitter
x
;
detail
::
tick_emitter
y
{
time_point
{
timespan
{
100
}}};
detail
::
tick_emitter
z
;
z
.
start
(
time_point
{
timespan
{
100
}});
CAF_CHECK_EQUAL
(
x
.
started
(),
false
);
CAF_CHECK_EQUAL
(
y
.
started
(),
true
);
CAF_CHECK_EQUAL
(
z
.
started
(),
true
);
for
(
auto
t
:
{
&
x
,
&
y
,
&
z
})
t
->
stop
();
CAF_CHECK_EQUAL
(
x
.
started
(),
false
);
CAF_CHECK_EQUAL
(
y
.
started
(),
false
);
CAF_CHECK_EQUAL
(
z
.
started
(),
false
);
}
CAF_TEST
(
ticks
)
{
CAF_TEST
(
ticks
)
{
using
timespan
=
std
::
chrono
::
microseconds
;
timespan
credit_interval
{
200
};
timespan
force_batch_interval
{
50
};
auto
cycle
=
detail
::
gcd
(
credit_interval
.
count
(),
auto
cycle
=
detail
::
gcd
(
credit_interval
.
count
(),
force_batch_interval
.
count
());
force_batch_interval
.
count
());
CAF_CHECK_EQUAL
(
cycle
,
50
);
CAF_CHECK_EQUAL
(
cycle
,
50
);
auto
force_batch_frequency
=
force_batch_interval
.
count
()
/
cycle
;
auto
force_batch_frequency
=
force_batch_interval
.
count
()
/
cycle
;
auto
credit_frequency
=
credit_interval
.
count
()
/
cycle
;
auto
credit_frequency
=
credit_interval
.
count
()
/
cycle
;
using
time_point
=
std
::
chrono
::
steady_clock
::
time_point
;
detail
::
tick_emitter
tctrl
{
time_point
{
timespan
{
100
}}};
detail
::
tick_emitter
tctrl
{
time_point
{
timespan
{
100
}}};
tctrl
.
interval
(
timespan
{
cycle
});
tctrl
.
interval
(
timespan
{
cycle
});
vector
<
long
>
ticks
;
vector
<
long
>
ticks
;
...
@@ -76,3 +98,54 @@ CAF_TEST(ticks) {
...
@@ -76,3 +98,54 @@ CAF_TEST(ticks) {
CAF_CHECK_EQUAL
(
credit_triggers
,
1
);
CAF_CHECK_EQUAL
(
credit_triggers
,
1
);
}
}
CAF_TEST
(
timeouts
)
{
timespan
interval
{
50
};
time_point
start
{
timespan
{
100
}};
auto
now
=
start
;
detail
::
tick_emitter
tctrl
{
now
};
tctrl
.
interval
(
interval
);
CAF_MESSAGE
(
"advance until the first 5-tick-period ends"
);
now
+=
interval
*
5
;
auto
bitmask
=
tctrl
.
timeouts
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
bitmask
,
0x01
);
CAF_MESSAGE
(
"advance until the first 7-tick-period ends"
);
now
+=
interval
*
2
;
bitmask
=
tctrl
.
timeouts
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
bitmask
,
0x02
);
CAF_MESSAGE
(
"advance until both tick period ends"
);
now
+=
interval
*
7
;
bitmask
=
tctrl
.
timeouts
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
bitmask
,
0x03
);
CAF_MESSAGE
(
"advance until both tick period end multiple times"
);
now
+=
interval
*
21
;
bitmask
=
tctrl
.
timeouts
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
bitmask
,
0x03
);
CAF_MESSAGE
(
"advance without any timeout"
);
now
+=
interval
*
1
;
bitmask
=
tctrl
.
timeouts
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
bitmask
,
0x00
);
}
CAF_TEST
(
next_timeout
)
{
timespan
interval
{
50
};
time_point
start
{
timespan
{
100
}};
auto
now
=
start
;
detail
::
tick_emitter
tctrl
{
now
};
tctrl
.
interval
(
interval
);
CAF_MESSAGE
(
"advance until the first 5-tick-period ends"
);
auto
next
=
tctrl
.
next_timeout
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
next
,
start
+
timespan
(
5
*
interval
));
CAF_MESSAGE
(
"advance until the first 7-tick-period ends"
);
now
=
start
+
timespan
(
5
*
interval
);
next
=
tctrl
.
next_timeout
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
next
,
start
+
timespan
(
7
*
interval
));
CAF_MESSAGE
(
"advance until the second 5-tick-period ends"
);
now
=
start
+
timespan
(
7
*
interval
);
next
=
tctrl
.
next_timeout
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
next
,
start
+
timespan
((
2
*
5
)
*
interval
));
CAF_MESSAGE
(
"advance until the second 7-tick-period ends"
);
now
=
start
+
timespan
(
11
*
interval
);
next
=
tctrl
.
next_timeout
(
now
,
{
5
,
7
});
CAF_CHECK_EQUAL
(
next
,
start
+
timespan
((
2
*
7
)
*
interval
));
}
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