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
58f1d373
Unverified
Commit
58f1d373
authored
Sep 10, 2019
by
Joseph Noir
Committed by
GitHub
Sep 10, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #904
Add scheduled_send for sending with absolute timeout
parents
db299ded
1b579742
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
190 additions
and
146 deletions
+190
-146
libcaf_core/caf/group.hpp
libcaf_core/caf/group.hpp
+13
-11
libcaf_core/caf/mixin/sender.hpp
libcaf_core/caf/mixin/sender.hpp
+87
-106
libcaf_core/caf/send.hpp
libcaf_core/caf/send.hpp
+43
-7
libcaf_core/caf/typed_actor_pointer.hpp
libcaf_core/caf/typed_actor_pointer.hpp
+5
-1
libcaf_core/caf/typed_actor_view.hpp
libcaf_core/caf/typed_actor_view.hpp
+4
-0
libcaf_core/test/composable_behavior.cpp
libcaf_core/test/composable_behavior.cpp
+1
-1
libcaf_core/test/sender.cpp
libcaf_core/test/sender.cpp
+36
-19
libcaf_core/test/simple_timeout.cpp
libcaf_core/test/simple_timeout.cpp
+1
-1
No files found.
libcaf_core/caf/group.hpp
View file @
58f1d373
...
@@ -64,11 +64,11 @@ public:
...
@@ -64,11 +64,11 @@ public:
group
(
intrusive_ptr
<
abstract_group
>
gptr
);
group
(
intrusive_ptr
<
abstract_group
>
gptr
);
inline
explicit
operator
bool
()
const
noexcept
{
explicit
operator
bool
()
const
noexcept
{
return
static_cast
<
bool
>
(
ptr_
);
return
static_cast
<
bool
>
(
ptr_
);
}
}
inline
bool
operator
!
()
const
noexcept
{
bool
operator
!
()
const
noexcept
{
return
!
ptr_
;
return
!
ptr_
;
}
}
...
@@ -76,7 +76,7 @@ public:
...
@@ -76,7 +76,7 @@ public:
intptr_t
compare
(
const
group
&
other
)
const
noexcept
;
intptr_t
compare
(
const
group
&
other
)
const
noexcept
;
in
line
in
tptr_t
compare
(
const
invalid_group_t
&
)
const
noexcept
{
intptr_t
compare
(
const
invalid_group_t
&
)
const
noexcept
{
return
ptr_
?
1
:
0
;
return
ptr_
?
1
:
0
;
}
}
...
@@ -98,12 +98,16 @@ public:
...
@@ -98,12 +98,16 @@ public:
friend
error
inspect
(
deserializer
&
,
group
&
);
friend
error
inspect
(
deserializer
&
,
group
&
);
inline
abstract_group
*
get
()
const
noexcept
{
abstract_group
*
get
()
const
noexcept
{
return
ptr_
.
get
();
return
ptr_
.
get
();
}
}
/// @cond PRIVATE
/// @cond PRIVATE
actor_system
&
system
()
const
{
return
ptr_
->
system
();
}
template
<
class
...
Ts
>
template
<
class
...
Ts
>
void
eq_impl
(
message_id
mid
,
strong_actor_ptr
sender
,
void
eq_impl
(
message_id
mid
,
strong_actor_ptr
sender
,
execution_unit
*
ctx
,
Ts
&&
...
xs
)
const
{
execution_unit
*
ctx
,
Ts
&&
...
xs
)
const
{
...
@@ -113,27 +117,25 @@ public:
...
@@ -113,27 +117,25 @@ public:
make_message
(
std
::
forward
<
Ts
>
(
xs
)...),
ctx
);
make_message
(
std
::
forward
<
Ts
>
(
xs
)...),
ctx
);
}
}
inline
bool
subscribe
(
strong_actor_ptr
who
)
const
{
bool
subscribe
(
strong_actor_ptr
who
)
const
{
if
(
!
ptr_
)
if
(
!
ptr_
)
return
false
;
return
false
;
return
ptr_
->
subscribe
(
std
::
move
(
who
));
return
ptr_
->
subscribe
(
std
::
move
(
who
));
}
}
inline
void
unsubscribe
(
const
actor_control_block
*
who
)
const
{
void
unsubscribe
(
const
actor_control_block
*
who
)
const
{
if
(
ptr_
)
if
(
ptr_
)
ptr_
->
unsubscribe
(
who
);
ptr_
->
unsubscribe
(
who
);
}
}
/// CAF's messaging primitives assume a non-null guarantee. A group
const
group
*
operator
->
()
const
noexcept
{
/// object indirects pointer-like access to a group to prevent UB.
inline
const
group
*
operator
->
()
const
noexcept
{
return
this
;
return
this
;
}
}
/// @endcond
/// @endcond
private:
private:
inline
abstract_group
*
release
()
noexcept
{
abstract_group
*
release
()
noexcept
{
return
ptr_
.
release
();
return
ptr_
.
release
();
}
}
...
@@ -150,7 +152,7 @@ std::string to_string(const group& x);
...
@@ -150,7 +152,7 @@ std::string to_string(const group& x);
namespace
std
{
namespace
std
{
template
<
>
template
<
>
struct
hash
<
caf
::
group
>
{
struct
hash
<
caf
::
group
>
{
inline
size_t
operator
()(
const
caf
::
group
&
x
)
const
{
size_t
operator
()(
const
caf
::
group
&
x
)
const
{
// groups are singleton objects, the address is thus the best possible hash
// groups are singleton objects, the address is thus the best possible hash
return
!
x
?
0
:
reinterpret_cast
<
size_t
>
(
x
.
get
());
return
!
x
?
0
:
reinterpret_cast
<
size_t
>
(
x
.
get
());
}
}
...
...
libcaf_core/caf/mixin/sender.hpp
View file @
58f1d373
This diff is collapsed.
Click to expand it.
libcaf_core/caf/send.hpp
View file @
58f1d373
...
@@ -19,17 +19,19 @@
...
@@ -19,17 +19,19 @@
#pragma once
#pragma once
#include "caf/actor.hpp"
#include "caf/actor.hpp"
#include "caf/message.hpp"
#include "caf/actor_cast.hpp"
#include "caf/actor_addr.hpp"
#include "caf/actor_addr.hpp"
#include "caf/message_id.hpp"
#include "caf/actor_cast.hpp"
#include "caf/typed_actor.hpp"
#include "caf/check_typed_input.hpp"
#include "caf/is_message_sink.hpp"
#include "caf/local_actor.hpp"
#include "caf/local_actor.hpp"
#include "caf/mailbox_element.hpp"
#include "caf/message.hpp"
#include "caf/message_id.hpp"
#include "caf/message_priority.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_type.hpp"
#include "caf/response_type.hpp"
#include "caf/system_messages.hpp"
#include "caf/system_messages.hpp"
#include "caf/is_message_sink.hpp"
#include "caf/typed_actor.hpp"
#include "caf/message_priority.hpp"
#include "caf/check_typed_input.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -69,6 +71,7 @@ void send_as(const Source& src, const Dest& dest, Ts&&... xs) {
...
@@ -69,6 +71,7 @@ void send_as(const Source& src, const Dest& dest, Ts&&... xs) {
template
<
message_priority
P
=
message_priority
::
normal
,
class
Source
,
template
<
message_priority
P
=
message_priority
::
normal
,
class
Source
,
class
Dest
,
class
...
Ts
>
class
Dest
,
class
...
Ts
>
void
unsafe_send_as
(
Source
*
src
,
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
void
unsafe_send_as
(
Source
*
src
,
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
if
(
dest
)
if
(
dest
)
actor_cast
<
abstract_actor
*>
(
dest
)
->
eq_impl
(
make_message_id
(
P
),
actor_cast
<
abstract_actor
*>
(
dest
)
->
eq_impl
(
make_message_id
(
P
),
src
->
ctrl
(),
src
->
context
(),
src
->
ctrl
(),
src
->
context
(),
...
@@ -79,6 +82,7 @@ template <class... Ts>
...
@@ -79,6 +82,7 @@ template <class... Ts>
void
unsafe_response
(
local_actor
*
self
,
strong_actor_ptr
src
,
void
unsafe_response
(
local_actor
*
self
,
strong_actor_ptr
src
,
std
::
vector
<
strong_actor_ptr
>
stages
,
message_id
mid
,
std
::
vector
<
strong_actor_ptr
>
stages
,
message_id
mid
,
Ts
&&
...
xs
)
{
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
strong_actor_ptr
next
;
strong_actor_ptr
next
;
if
(
stages
.
empty
())
{
if
(
stages
.
empty
())
{
next
=
src
;
next
=
src
;
...
@@ -108,6 +112,38 @@ void anon_send(const Dest& dest, Ts&&... xs) {
...
@@ -108,6 +112,38 @@ void anon_send(const Dest& dest, Ts&&... xs) {
std
::
forward
<
Ts
>
(
xs
)...);
std
::
forward
<
Ts
>
(
xs
)...);
}
}
template
<
message_priority
P
=
message_priority
::
normal
,
class
Dest
=
actor
,
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
...
Ts
>
detail
::
enable_if_t
<!
std
::
is_same
<
Dest
,
group
>::
value
>
delayed_anon_send
(
const
Dest
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
token
=
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
valid
,
"receiver does not accept given message"
);
if
(
dest
)
{
auto
&
clock
=
dest
->
home_system
().
clock
();
auto
timeout
=
clock
.
now
()
+
rtime
;
clock
.
schedule_message
(
timeout
,
actor_cast
<
strong_actor_ptr
>
(
dest
),
make_mailbox_element
(
nullptr
,
make_message_id
(
P
),
no_stages
,
std
::
forward
<
Ts
>
(
xs
)...));
}
}
template
<
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
...
Ts
>
void
delayed_anon_send
(
const
group
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
if
(
dest
)
{
auto
&
clock
=
dest
->
system
().
clock
();
auto
timeout
=
clock
.
now
()
+
rtime
;
clock
.
schedule_message
(
timeout
,
dest
,
make_message
(
std
::
forward
<
Ts
>
(
xs
)...));
}
}
/// Anonymously sends `dest` an exit message.
/// Anonymously sends `dest` an exit message.
template
<
class
Dest
>
template
<
class
Dest
>
void
anon_send_exit
(
const
Dest
&
dest
,
exit_reason
reason
)
{
void
anon_send_exit
(
const
Dest
&
dest
,
exit_reason
reason
)
{
...
...
libcaf_core/caf/typed_actor_pointer.hpp
View file @
58f1d373
...
@@ -48,7 +48,11 @@ public:
...
@@ -48,7 +48,11 @@ public:
return
&
view_
;
return
&
view_
;
}
}
inline
explicit
operator
bool
()
const
{
const
typed_actor_view
<
Sigs
...
>*
operator
->
()
const
{
return
&
view_
;
}
explicit
operator
bool
()
const
{
return
static_cast
<
bool
>
(
view_
.
internal_ptr
());
return
static_cast
<
bool
>
(
view_
.
internal_ptr
());
}
}
...
...
libcaf_core/caf/typed_actor_view.hpp
View file @
58f1d373
...
@@ -77,6 +77,10 @@ public:
...
@@ -77,6 +77,10 @@ public:
return
self_
->
system
();
return
self_
->
system
();
}
}
actor_system
&
home_system
()
const
{
return
self_
->
home_system
();
}
void
quit
(
exit_reason
reason
=
exit_reason
::
normal
)
{
void
quit
(
exit_reason
reason
=
exit_reason
::
normal
)
{
self_
->
quit
(
reason
);
self_
->
quit
(
reason
);
}
}
...
...
libcaf_core/test/composable_behavior.cpp
View file @
58f1d373
...
@@ -212,7 +212,7 @@ class delayed_testee : public composable_behavior<delayed_testee_actor> {
...
@@ -212,7 +212,7 @@ class delayed_testee : public composable_behavior<delayed_testee_actor> {
public:
public:
result
<
void
>
operator
()(
int
x
)
override
{
result
<
void
>
operator
()(
int
x
)
override
{
CAF_CHECK_EQUAL
(
x
,
42
);
CAF_CHECK_EQUAL
(
x
,
42
);
self
->
delayed_anon_send
(
self
,
std
::
chrono
::
milliseconds
(
10
),
true
);
delayed_anon_send
(
self
,
std
::
chrono
::
milliseconds
(
10
),
true
);
return
unit
;
return
unit
;
}
}
...
...
libcaf_core/test/
delayed_send
.cpp
→
libcaf_core/test/
sender
.cpp
View file @
58f1d373
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
* | |___ / ___ \| _| Framework *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* \____/_/ \_|_| *
* *
* *
* Copyright 2011-201
8
Dominik Charousset *
* Copyright 2011-201
9
Dominik Charousset *
* *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* 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 *
* (at your option) under the terms and conditions of the Boost Software *
...
@@ -16,16 +16,14 @@
...
@@ -16,16 +16,14 @@
* http://www.boost.org/LICENSE_1_0.txt. *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
******************************************************************************/
#define CAF_SUITE
delayed_send
#define CAF_SUITE
sender
#include <chrono>
#include "caf/mixin/sender.hpp"
#include "caf/actor_system.hpp"
#include "caf/behavior.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/test/dsl.hpp"
#include "caf/test/dsl.hpp"
#include <chrono>
using
namespace
caf
;
using
namespace
caf
;
using
std
::
chrono
::
seconds
;
using
std
::
chrono
::
seconds
;
...
@@ -34,32 +32,51 @@ namespace {
...
@@ -34,32 +32,51 @@ namespace {
behavior
testee_impl
(
event_based_actor
*
self
)
{
behavior
testee_impl
(
event_based_actor
*
self
)
{
self
->
set_default_handler
(
drop
);
self
->
set_default_handler
(
drop
);
return
{
return
{[]
{
[]
{
// nop
// nop
}
}};
};
}
}
}
// namespace <anonymous>
struct
fixture
:
test_coordinator_fixture
<>
{
group
grp
;
actor
testee
;
fixture
()
{
grp
=
sys
.
groups
().
anonymous
();
testee
=
sys
.
spawn_in_group
(
grp
,
testee_impl
);
}
~
fixture
()
{
anon_send_exit
(
testee
,
exit_reason
::
user_shutdown
);
}
};
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
request_timeout_tests
,
test_coordinator_fixture
<>
)
CAF_TEST_FIXTURE_SCOPE
(
sender_tests
,
fixture
)
CAF_TEST
(
delayed
actor
message
)
{
CAF_TEST
(
delayed
actor
message
)
{
auto
testee
=
sys
.
spawn
(
testee_impl
);
self
->
delayed_send
(
testee
,
seconds
(
1
),
"hello world"
);
self
->
delayed_send
(
testee
,
seconds
(
1
),
"hello world"
);
sched
.
trigger_timeout
();
sched
.
trigger_timeout
();
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
}
}
CAF_TEST
(
delayed
group
message
)
{
CAF_TEST
(
delayed
group
message
)
{
auto
grp
=
sys
.
groups
().
anonymous
();
auto
testee
=
sys
.
spawn_in_group
(
grp
,
testee_impl
);
self
->
delayed_send
(
grp
,
seconds
(
1
),
"hello world"
);
self
->
delayed_send
(
grp
,
seconds
(
1
),
"hello world"
);
sched
.
trigger_timeout
();
sched
.
trigger_timeout
();
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
// The group keeps a reference, so we need to shutdown 'manually'.
}
anon_send_exit
(
testee
,
exit_reason
::
user_shutdown
);
CAF_TEST
(
scheduled
actor
message
)
{
self
->
scheduled_send
(
testee
,
self
->
clock
().
now
()
+
seconds
(
1
),
"hello world"
);
sched
.
trigger_timeout
();
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
}
CAF_TEST
(
scheduled
group
message
)
{
self
->
scheduled_send
(
grp
,
self
->
clock
().
now
()
+
seconds
(
1
),
"hello world"
);
sched
.
trigger_timeout
();
expect
((
std
::
string
),
from
(
self
).
to
(
testee
).
with
(
"hello world"
));
}
}
CAF_TEST_FIXTURE_SCOPE_END
()
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/simple_timeout.cpp
View file @
58f1d373
...
@@ -57,7 +57,7 @@ timer::behavior_type timer_impl(timer::stateful_pointer<timer_state> self) {
...
@@ -57,7 +57,7 @@ timer::behavior_type timer_impl(timer::stateful_pointer<timer_state> self) {
timer
::
behavior_type
timer_impl2
(
timer
::
pointer
self
)
{
timer
::
behavior_type
timer_impl2
(
timer
::
pointer
self
)
{
auto
had_reset
=
std
::
make_shared
<
bool
>
(
false
);
auto
had_reset
=
std
::
make_shared
<
bool
>
(
false
);
self
->
delayed_anon_send
(
self
,
ms
(
100
),
reset_atom
::
value
);
delayed_anon_send
(
self
,
ms
(
100
),
reset_atom
::
value
);
return
{
return
{
[
=
](
reset_atom
)
{
[
=
](
reset_atom
)
{
CAF_MESSAGE
(
"timer reset"
);
CAF_MESSAGE
(
"timer reset"
);
...
...
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