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
Hide 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
...
@@ -23,19 +23,18 @@
...
@@ -23,19 +23,18 @@
#include "caf/actor.hpp"
#include "caf/actor.hpp"
#include "caf/actor_cast.hpp"
#include "caf/actor_cast.hpp"
#include "caf/actor_clock.hpp"
#include "caf/actor_control_block.hpp"
#include "caf/actor_control_block.hpp"
#include "caf/check_typed_input.hpp"
#include "caf/check_typed_input.hpp"
#include "caf/duration.hpp"
#include "caf/duration.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_type.hpp"
#include "caf/response_handle.hpp"
#include "caf/fwd.hpp"
#include "caf/fwd.hpp"
#include "caf/message.hpp"
#include "caf/message.hpp"
#include "caf/message_priority.hpp"
#include "caf/message_priority.hpp"
#include "caf/no_stages.hpp"
#include "caf/response_handle.hpp"
#include "caf/response_handle.hpp"
#include "caf/response_type.hpp"
#include "caf/response_type.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"
#include "caf/scheduler/abstract_coordinator.hpp"
#include "caf/send.hpp"
namespace
caf
{
namespace
caf
{
namespace
mixin
{
namespace
mixin
{
...
@@ -61,24 +60,9 @@ public:
...
@@ -61,24 +60,9 @@ public:
template
<
message_priority
P
=
message_priority
::
normal
,
template
<
message_priority
P
=
message_priority
::
normal
,
class
Dest
=
actor
,
class
...
Ts
>
class
Dest
=
actor
,
class
...
Ts
>
void
send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
void
send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
using
detail
::
type_list
;
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
res_t
=
response_type
<
detail
::
type_list
<
detail
::
strip_and_convert_t
<
Ts
>
...
>
args_token
;
signatures_of_t
<
Dest
>
,
type_check
(
dest
,
args_token
);
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>
;
static_assert
(
!
statically_typed
<
Subtype
>
()
||
statically_typed
<
Dest
>
(),
"statically typed actors can only send() to other "
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
static_assert
(
res_t
::
valid
,
"receiver does not accept given message"
);
static_assert
(
is_void_response
<
typename
res_t
::
type
>::
value
||
response_type_unbox
<
signatures_of_t
<
Subtype
>
,
typename
res_t
::
type
>::
valid
,
"this actor does not accept the response message"
);
if
(
dest
)
if
(
dest
)
dest
->
eq_impl
(
make_message_id
(
P
),
dptr
()
->
ctrl
(),
dest
->
eq_impl
(
make_message_id
(
P
),
dptr
()
->
ctrl
(),
dptr
()
->
context
(),
std
::
forward
<
Ts
>
(
xs
)...);
dptr
()
->
context
(),
std
::
forward
<
Ts
>
(
xs
)...);
...
@@ -101,64 +85,75 @@ public:
...
@@ -101,64 +85,75 @@ public:
template
<
message_priority
P
=
message_priority
::
normal
,
template
<
message_priority
P
=
message_priority
::
normal
,
class
Dest
=
actor
,
class
...
Ts
>
class
Dest
=
actor
,
class
...
Ts
>
void
anon_send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
void
anon_send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
caf
::
anon_send
(
dest
,
std
::
forward
<
Ts
>
(
xs
)...);
}
/// Sends a message at given time point (or immediately if `timeout` has
/// passed already).
template
<
message_priority
P
=
message_priority
::
normal
,
class
Dest
=
actor
,
class
...
Ts
>
detail
::
enable_if_t
<!
std
::
is_same
<
Dest
,
group
>::
value
>
scheduled_send
(
const
Dest
&
dest
,
actor_clock
::
time_point
timeout
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
token
=
detail
::
type_list
<
detail
::
strip_and_convert_t
<
Ts
>
...
>
args_token
;
detail
::
type_list
<
type_check
(
dest
,
args_token
);
typename
detail
::
implicit_conversions
<
if
(
dest
)
{
typename
std
::
decay
<
Ts
>::
type
auto
&
clock
=
dptr
()
->
system
().
clock
();
>::
type
...
>
;
clock
.
schedule_message
(
timeout
,
actor_cast
<
strong_actor_ptr
>
(
dest
),
static_assert
(
response_type_unbox
<
make_mailbox_element
(
dptr
()
->
ctrl
(),
signatures_of_t
<
Dest
>
,
make_message_id
(
P
),
no_stages
,
token
std
::
forward
<
Ts
>
(
xs
)...));
>::
valid
,
}
"receiver does not accept given message"
);
if
(
dest
)
dest
->
eq_impl
(
make_message_id
(
P
),
nullptr
,
dptr
()
->
context
(),
std
::
forward
<
Ts
>
(
xs
)...);
}
}
/// Sends a message at given time point (or immediately if `timeout` has
/// passed already).
template
<
class
...
Ts
>
void
scheduled_send
(
const
group
&
dest
,
actor_clock
::
time_point
timeout
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
static_assert
(
!
statically_typed
<
Subtype
>
(),
"statically typed actors are not allowed to send to groups"
);
if
(
dest
)
{
auto
&
clock
=
dptr
()
->
system
().
clock
();
clock
.
schedule_message
(
timeout
,
dest
,
dptr
()
->
ctrl
(),
make_message
(
std
::
forward
<
Ts
>
(
xs
)...));
}
}
/// Sends a message after a relative timeout.
template
<
message_priority
P
=
message_priority
::
normal
,
class
Rep
=
int
,
template
<
message_priority
P
=
message_priority
::
normal
,
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
Dest
=
actor
,
class
...
Ts
>
class
Period
=
std
::
ratio
<
1
>,
class
Dest
=
actor
,
class
...
Ts
>
void
delayed_send
(
const
Dest
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
detail
::
enable_if_t
<!
std
::
is_same
<
Dest
,
group
>::
value
>
delayed_send
(
const
Dest
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rel_timeout
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
detail
::
type_list
<
detail
::
strip_and_convert_t
<
Ts
>
...
>
args_token
;
type_check
(
dest
,
args_token
);
if
(
dest
)
{
auto
&
clock
=
dptr
()
->
system
().
clock
();
auto
timeout
=
clock
.
now
()
+
rel_timeout
;
clock
.
schedule_message
(
timeout
,
actor_cast
<
strong_actor_ptr
>
(
dest
),
make_mailbox_element
(
dptr
()
->
ctrl
(),
make_message_id
(
P
),
no_stages
,
std
::
forward
<
Ts
>
(
xs
)...));
}
}
/// Sends a message after a relative timeout.
template
<
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
Dest
=
actor
,
class
...
Ts
>
void
delayed_send
(
const
group
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
Ts
&&
...
xs
)
{
using
token
=
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
detail
::
type_list
<
static_assert
(
!
statically_typed
<
Subtype
>
(),
typename
detail
::
implicit_conversions
<
"statically typed actors are not allowed to send to groups"
);
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
!
statically_typed
<
Subtype
>
()
||
statically_typed
<
Dest
>
(),
"statically typed actors are only allowed to send() to other "
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
valid
,
"receiver does not accept given message"
);
// TODO: this only checks one way, we should check for loops
static_assert
(
is_void_response
<
typename
response_type
<
signatures_of_t
<
Dest
>
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>::
type
>::
value
||
response_type_unbox
<
signatures_of_t
<
Subtype
>
,
typename
response_type
<
signatures_of_t
<
Dest
>
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>::
type
>::
valid
,
"this actor does not accept the response message"
);
if
(
dest
)
{
if
(
dest
)
{
auto
&
clock
=
dptr
()
->
system
().
clock
();
auto
&
clock
=
dptr
()
->
system
().
clock
();
auto
t
=
clock
.
now
()
+
rtime
;
auto
t
imeout
=
clock
.
now
()
+
rtime
;
delayed_send_impl
(
clock
,
dptr
()
->
ctrl
(),
dest
,
P
,
t
,
clock
.
schedule_message
(
timeout
,
dest
,
dptr
()
->
ctrl
()
,
std
::
forward
<
Ts
>
(
xs
)...
);
make_message
(
std
::
forward
<
Ts
>
(
xs
)...)
);
}
}
}
}
...
@@ -166,49 +161,35 @@ public:
...
@@ -166,49 +161,35 @@ public:
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
...
Ts
>
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
...
Ts
>
void
delayed_anon_send
(
const
Dest
&
dest
,
void
delayed_anon_send
(
const
Dest
&
dest
,
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
caf
::
delayed_anon_send
<
P
>
(
dest
,
rtime
,
std
::
forward
<
Ts
>
(
xs
)...);
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
=
dptr
()
->
system
().
clock
();
auto
t
=
clock
.
now
()
+
rtime
;
delayed_send_impl
(
clock
,
nullptr
,
dest
,
P
,
t
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
}
private:
template
<
class
Rep
=
int
,
class
Period
=
std
::
ratio
<
1
>,
class
...
Ts
>
Subtype
*
dptr
()
{
void
delayed_anon_send
(
const
group
&
dest
,
return
static_cast
<
Subtype
*>
(
this
);
std
::
chrono
::
duration
<
Rep
,
Period
>
rtime
,
Ts
&&
...
xs
)
{
caf
::
delayed_anon_send
(
dest
,
rtime
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
template
<
class
...
Ts
>
private:
static
void
delayed_send_impl
(
actor_clock
&
clk
,
strong_actor_ptr
src
,
template
<
class
Dest
,
class
ArgTypes
>
const
group
&
dst
,
message_priority
,
static
void
type_check
(
const
Dest
&
,
ArgTypes
)
{
actor_clock
::
time_point
tout
,
Ts
&&
...
xs
)
{
static_assert
(
!
statically_typed
<
Subtype
>
()
||
statically_typed
<
Dest
>
(),
clk
.
schedule_message
(
tout
,
dst
,
std
::
move
(
src
),
"statically typed actors are only allowed to send() to other "
make_message
(
std
::
forward
<
Ts
>
(
xs
)...));
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
using
rt
=
response_type_unbox
<
signatures_of_t
<
Dest
>
,
ArgTypes
>
;
static_assert
(
rt
::
valid
,
"receiver does not accept given message"
);
// TODO: this only checks one way, we should check for loops
static_assert
(
is_void_response
<
typename
rt
::
type
>::
value
||
response_type_unbox
<
signatures_of_t
<
Subtype
>
,
typename
rt
::
type
>::
valid
,
"this actor does not accept the response message"
);
}
}
template
<
class
ActorHandle
,
class
...
Ts
>
Subtype
*
dptr
()
{
static
void
delayed_send_impl
(
actor_clock
&
clk
,
strong_actor_ptr
src
,
return
static_cast
<
Subtype
*>
(
this
);
const
ActorHandle
&
dst
,
message_priority
prio
,
actor_clock
::
time_point
tout
,
Ts
&&
...
xs
)
{
clk
.
schedule_message
(
tout
,
actor_cast
<
strong_actor_ptr
>
(
dst
),
make_mailbox_element
(
std
::
move
(
src
),
make_message_id
(
prio
),
no_stages
,
std
::
forward
<
Ts
>
(
xs
)...));
}
}
};
};
}
// namespace mixin
}
// namespace mixin
}
// namespace caf
}
// namespace caf
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
;
CAF_TEST_FIXTURE_SCOPE
(
request_timeout_tests
,
test_coordinator_fixture
<>
)
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
(
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