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
ffed360f
Commit
ffed360f
authored
Feb 03, 2014
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed several issues with typed actors
parent
3b25a510
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
381 additions
and
237 deletions
+381
-237
cppa/abstract_actor.hpp
cppa/abstract_actor.hpp
+16
-2
cppa/cppa.hpp
cppa/cppa.hpp
+10
-9
cppa/event_based_actor.hpp
cppa/event_based_actor.hpp
+0
-2
cppa/local_actor.hpp
cppa/local_actor.hpp
+24
-20
cppa/spawn.hpp
cppa/spawn.hpp
+101
-32
cppa/spawn_fwd.hpp
cppa/spawn_fwd.hpp
+29
-19
cppa/typed_actor.hpp
cppa/typed_actor.hpp
+33
-16
cppa/typed_behavior.hpp
cppa/typed_behavior.hpp
+42
-11
cppa/typed_event_based_actor.hpp
cppa/typed_event_based_actor.hpp
+19
-5
cppa/util/type_list.hpp
cppa/util/type_list.hpp
+1
-1
src/abstract_actor.cpp
src/abstract_actor.cpp
+5
-8
src/uniform_type_info_map.cpp
src/uniform_type_info_map.cpp
+1
-1
unit_testing/test_typed_spawn.cpp
unit_testing/test_typed_spawn.cpp
+100
-111
No files found.
cppa/abstract_actor.hpp
View file @
ffed360f
...
...
@@ -31,9 +31,11 @@
#ifndef CPPA_ABSTRACT_ACTOR_HPP
#define CPPA_ABSTRACT_ACTOR_HPP
#include <set>
#include <mutex>
#include <atomic>
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
#include <type_traits>
...
...
@@ -119,7 +121,10 @@ class abstract_actor : public abstract_channel {
/**
* @copydoc abstract_actor::link_to(const actor_addr&)
*/
void
link_to
(
const
actor
&
whom
);
template
<
typename
ActorHandle
>
void
link_to
(
const
ActorHandle
&
whom
)
{
link_to
(
whom
.
address
());
}
/**
* @brief Unlinks this actor from @p whom.
...
...
@@ -131,7 +136,10 @@ class abstract_actor : public abstract_channel {
/**
* @copydoc abstract_actor::unlink_from(const actor_addr&)
*/
void
unlink_from
(
const
actor
&
whom
);
template
<
class
ActorHandle
>
void
unlink_from
(
const
ActorHandle
&
whom
)
{
unlink_from
(
whom
.
address
());
}
/**
* @brief Establishes a link relation between this actor and @p other.
...
...
@@ -174,6 +182,12 @@ class abstract_actor : public abstract_channel {
*/
inline
std
::
uint32_t
exit_reason
()
const
;
/**
* @brief Returns the type interface as set of strings.
* @note The returned set is empty for all untyped actors.
*/
virtual
std
::
set
<
std
::
string
>
interface
()
const
;
protected:
abstract_actor
();
...
...
cppa/cppa.hpp
View file @
ffed360f
...
...
@@ -484,7 +484,8 @@ void anon_send_exit(const actor_addr& whom, std::uint32_t reason);
/**
* @brief Anonymously sends @p whom an exit message.
*/
inline
void
anon_send_exit
(
const
actor
&
whom
,
std
::
uint32_t
reason
)
{
template
<
typename
ActorHandle
>
inline
void
anon_send_exit
(
const
ActorHandle
&
whom
,
std
::
uint32_t
reason
)
{
anon_send_exit
(
whom
.
address
(),
reason
);
}
...
...
@@ -548,10 +549,10 @@ actor remote_actor(io::stream_ptr_pair connection);
* @brief Spawns an IO actor of type @p Impl.
* @param args Constructor arguments.
* @tparam Impl Subtype of {@link io::broker}.
* @tparam O
ption
s Optional flags to modify <tt>spawn</tt>'s behavior.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
*/
template
<
class
Impl
,
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
class
Impl
,
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_io
(
Ts
&&
...
args
)
{
auto
ptr
=
make_counted
<
Impl
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
{
io
::
init_and_launch
(
std
::
move
(
ptr
))};
...
...
@@ -563,10 +564,10 @@ actor spawn_io(Ts&&... args) {
* @param in The actor's input stream.
* @param out The actor's output stream.
* @param args Optional arguments for @p fun.
* @tparam O
ption
s Optional flags to modify <tt>spawn</tt>'s behavior.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns A {@link actor handle} to the spawned actor.
*/
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
=
std
::
function
<
void
(
io
::
broker
*
)>,
typename
...
Ts
>
actor
spawn_io
(
F
fun
,
...
...
@@ -578,7 +579,7 @@ actor spawn_io(F fun,
return
{
io
::
init_and_launch
(
std
::
move
(
ptr
))};
}
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
=
std
::
function
<
void
(
io
::
broker
*
)>,
typename
...
Ts
>
actor
spawn_io
(
F
fun
,
const
std
::
string
&
host
,
uint16_t
port
,
Ts
&&
...
args
)
{
...
...
@@ -586,13 +587,13 @@ actor spawn_io(F fun, const std::string& host, uint16_t port, Ts&&... args) {
return
spawn_io
(
std
::
move
(
fun
),
ptr
,
ptr
,
std
::
forward
<
Ts
>
(
args
)...);
}
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
=
std
::
function
<
void
(
io
::
broker
*
)>,
typename
...
Ts
>
actor
spawn_io_server
(
F
fun
,
uint16_t
port
,
Ts
&&
...
args
)
{
static_assert
(
!
has_detach_flag
(
O
ption
s
),
static_assert
(
!
has_detach_flag
(
Os
),
"brokers cannot be detached"
);
static_assert
(
is_unbound
(
O
ption
s
),
static_assert
(
is_unbound
(
Os
),
"top-level spawns cannot have monitor or link flag"
);
using
namespace
std
;
auto
ptr
=
io
::
broker
::
from
(
move
(
fun
),
...
...
cppa/event_based_actor.hpp
View file @
ffed360f
...
...
@@ -44,8 +44,6 @@
namespace
cppa
{
class
event_based_actor
;
/**
* @brief A cooperatively scheduled, event-based actor implementation.
*
...
...
cppa/local_actor.hpp
View file @
ffed360f
...
...
@@ -127,13 +127,17 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* spawn typed actors *
**************************************************************************/
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
>
typename
detail
::
actor_handle_from_typed_behavior
<
typename
util
::
get_callable_trait
<
F
>::
result_type
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
,
typename
...
Ts
>
typename
detail
::
infer_typed_actor_handle
<
typename
util
::
get_callable_trait
<
F
>::
result_type
,
typename
util
::
tl_head
<
typename
util
::
get_callable_trait
<
F
>::
arg_types
>::
type
>::
type
spawn_typed
(
F
fun
)
{
spawn_typed
(
F
fun
,
Ts
&&
...
args
)
{
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn_typed
<
os
>
(
std
::
move
(
fun
));
auto
res
=
cppa
::
spawn_typed
<
os
>
(
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
...
...
@@ -195,9 +199,9 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* @param whom Receiver of the message.
* @param what Message content as a tuple.
*/
template
<
typename
...
Signature
s
,
typename
...
Ts
>
template
<
typename
...
R
s
,
typename
...
Ts
>
void
send_tuple
(
message_priority
prio
,
const
typed_actor
<
Signature
s
...
>&
whom
,
const
typed_actor
<
R
s
...
>&
whom
,
cow_tuple
<
Ts
...
>
what
)
{
check_typed_input
(
whom
,
what
);
send_tuple
(
prio
,
whom
.
m_ptr
,
any_tuple
{
std
::
move
(
what
)});
...
...
@@ -208,8 +212,8 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* @param whom Receiver of the message.
* @param what Message content as a tuple.
*/
template
<
typename
...
Signature
s
,
typename
...
Ts
>
void
send_tuple
(
const
typed_actor
<
Signature
s
...
>&
whom
,
template
<
typename
...
R
s
,
typename
...
Ts
>
void
send_tuple
(
const
typed_actor
<
R
s
...
>&
whom
,
cow_tuple
<
Ts
...
>
what
)
{
check_typed_input
(
whom
,
what
);
send_tuple_impl
(
message_priority
::
normal
,
whom
,
std
::
move
(
what
));
...
...
@@ -222,9 +226,9 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* @param what Message elements.
* @pre <tt>sizeof...(Ts) > 0</tt>.
*/
template
<
typename
...
Signature
s
,
typename
...
Ts
>
template
<
typename
...
R
s
,
typename
...
Ts
>
void
send
(
message_priority
prio
,
const
typed_actor
<
Signature
s
...
>&
whom
,
const
typed_actor
<
R
s
...
>&
whom
,
cow_tuple
<
Ts
...
>
what
)
{
send_tuple
(
prio
,
whom
,
make_cow_tuple
(
std
::
forward
<
Ts
>
(
what
)...));
}
...
...
@@ -235,8 +239,8 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* @param what Message elements.
* @pre <tt>sizeof...(Ts) > 0</tt>.
*/
template
<
typename
...
Signature
s
,
typename
...
Ts
>
void
send
(
const
typed_actor
<
Signature
s
...
>&
whom
,
Ts
...
what
)
{
template
<
typename
...
R
s
,
typename
...
Ts
>
void
send
(
const
typed_actor
<
R
s
...
>&
whom
,
Ts
...
what
)
{
send_tuple
(
message_priority
::
normal
,
whom
,
make_cow_tuple
(
std
::
forward
<
Ts
>
(
what
)...));
}
...
...
@@ -256,8 +260,8 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
/**
* @copydoc send_exit(const actor_addr&, std::uint32_t)
*/
template
<
typename
...
Signature
s
>
void
send_exit
(
const
typed_actor
<
Signature
s
...
>&
whom
,
template
<
typename
...
R
s
>
void
send_exit
(
const
typed_actor
<
R
s
...
>&
whom
,
std
::
uint32_t
reason
)
{
send_exit
(
whom
.
address
(),
reason
);
}
...
...
@@ -516,9 +520,9 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
any_tuple
&&
what
);
// returns the response ID
template
<
typename
...
Signature
s
,
typename
...
Ts
>
template
<
typename
...
R
s
,
typename
...
Ts
>
message_id
sync_send_tuple_impl
(
message_priority
mp
,
const
typed_actor
<
Signature
s
...
>&
whom
,
const
typed_actor
<
R
s
...
>&
whom
,
cow_tuple
<
Ts
...
>&&
what
)
{
check_typed_input
(
whom
,
what
);
return
sync_send_tuple_impl
(
mp
,
...
...
@@ -601,11 +605,11 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
private:
template
<
typename
...
Signature
s
,
typename
...
Ts
>
static
void
check_typed_input
(
const
typed_actor
<
Signature
s
...
>&
,
template
<
typename
...
R
s
,
typename
...
Ts
>
static
void
check_typed_input
(
const
typed_actor
<
R
s
...
>&
,
const
cow_tuple
<
Ts
...
>&
)
{
static
constexpr
int
input_pos
=
util
::
tl_find_if
<
util
::
type_list
<
Signature
s
...
>
,
util
::
type_list
<
R
s
...
>
,
detail
::
input_is
<
util
::
type_list
<
Ts
...
>
>::
template
eval
...
...
cppa/spawn.hpp
View file @
ffed360f
...
...
@@ -217,23 +217,44 @@ actor spawn_in_group(const group& grp, Ts&&... args) {
namespace
detail
{
template
<
typename
...
Sig
s
>
class
functor_based_typed_actor
:
public
typed_event_based_actor
<
Sig
s
...
>
{
template
<
typename
...
R
s
>
class
functor_based_typed_actor
:
public
typed_event_based_actor
<
R
s
...
>
{
typedef
typed_event_based_actor
<
Sig
s
...
>
super
;
typedef
typed_event_based_actor
<
R
s
...
>
super
;
public:
typedef
typed_event_based_actor
<
Sig
s
...
>*
pointer
;
typedef
typename
super
::
behavior_type
behavior_type
;
typedef
typed_event_based_actor
<
R
s
...
>*
pointer
;
typedef
typename
super
::
behavior_type
behavior_type
;
typedef
std
::
function
<
typed_behavior
<
Sigs
...
>
()
>
no_arg_fun
;
typedef
std
::
function
<
typed_behavior
<
Sigs
...
>
(
pointer
)
>
one_arg_fun
;
typedef
std
::
function
<
behavior_type
()
>
no_arg_fun
;
typedef
std
::
function
<
behavior_type
(
pointer
)
>
one_arg_fun1
;
typedef
std
::
function
<
void
(
pointer
)
>
one_arg_fun2
;
functor_based_typed_actor
(
one_arg_fun
fun
)
:
m_fun
(
std
::
move
(
fun
))
{
}
functor_based_typed_actor
(
one_arg_fun1
fun
)
{
set
(
std
::
move
(
fun
));
}
functor_based_typed_actor
(
one_arg_fun2
fun
)
{
set
(
std
::
move
(
fun
));
}
functor_based_typed_actor
(
no_arg_fun
fun
)
{
m_fun
=
[
fun
](
pointer
)
{
return
fun
();
};
set
(
std
::
move
(
fun
));
}
template
<
typename
F
,
typename
T
,
typename
...
Ts
>
functor_based_typed_actor
(
F
fun
,
T
&&
arg
,
Ts
&&
...
args
)
{
typedef
typename
util
::
get_callable_trait
<
F
>::
arg_types
arg_types
;
constexpr
bool
uses_first_arg
=
std
::
is_same
<
typename
util
::
tl_head
<
arg_types
>::
type
,
pointer
>::
value
;
std
::
integral_constant
<
bool
,
uses_first_arg
>
token
;
bind_and_set
(
token
,
std
::
move
(
fun
),
std
::
forward
<
T
>
(
arg
),
std
::
forward
<
Ts
>
(
args
)...);
}
protected:
...
...
@@ -244,45 +265,93 @@ class functor_based_typed_actor : public typed_event_based_actor<Sigs...> {
private:
one_arg_fun
m_fun
;
void
set
(
one_arg_fun1
fun
)
{
m_fun
=
std
::
move
(
fun
);
}
};
void
set
(
one_arg_fun2
fun
)
{
m_fun
=
[
fun
](
pointer
ptr
)
{
fun
(
ptr
);
return
behavior_type
{};
};
}
void
set
(
no_arg_fun
fun
)
{
m_fun
=
[
fun
](
pointer
)
{
return
fun
();
};
}
template
<
typename
F
,
typename
...
Ts
>
void
bind_and_set
(
std
::
true_type
,
F
fun
,
Ts
&&
...
args
)
{
set
(
std
::
bind
(
fun
,
std
::
placeholders
::
_1
,
std
::
forward
<
Ts
>
(
args
)...));
}
template
<
typename
TypedBehavior
>
struct
actor_type_from_typed_behavior
;
template
<
typename
F
,
typename
...
Ts
>
void
bind_and_set
(
std
::
false_type
,
F
fun
,
Ts
&&
...
args
)
{
set
(
std
::
bind
(
fun
,
std
::
forward
<
Ts
>
(
args
)...));
}
one_arg_fun1
m_fun
;
template
<
typename
...
Signatures
>
struct
actor_type_from_typed_behavior
<
typed_behavior
<
Signatures
...
>>
{
typedef
functor_based_typed_actor
<
Signatures
...
>
type
;
};
}
// namespace detail
template
<
class
TypedBehavior
,
class
FirstArg
>
struct
infer_typed_actor_base
;
template
<
spawn_options
Options
,
typename
F
>
typename
detail
::
actor_handle_from_typed_behavior
<
typename
util
::
get_callable_trait
<
F
>::
result_type
>::
type
spawn_typed
(
F
fun
)
{
typedef
typename
detail
::
actor_type_from_typed_behavior
<
typename
util
::
get_callable_trait
<
F
>::
result_type
>::
type
impl
;
return
detail
::
spawn_fwd_args
<
impl
,
Options
>
(
[
&
](
impl
*
)
{
},
std
::
move
(
fun
));
}
template
<
typename
...
Rs
,
class
FirstArg
>
struct
infer_typed_actor_base
<
typed_behavior
<
Rs
...
>
,
FirstArg
>
{
typedef
functor_based_typed_actor
<
Rs
...
>
type
;
};
template
<
typename
...
Rs
>
struct
infer_typed_actor_base
<
void
,
typed_event_based_actor
<
Rs
...
>*>
{
typedef
functor_based_typed_actor
<
Rs
...
>
type
;
};
}
// namespace detail
template
<
class
C
,
spawn_options
Options
,
typename
...
Ts
>
/**
* @brief Spawns a typed actor of type @p C.
* @param args Constructor arguments.
* @tparam C Subtype of {@link typed_event_based_actor}.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns A {@link typed_actor} handle to the spawned actor.
*/
template
<
class
C
,
spawn_options
Os
,
typename
...
Ts
>
typename
detail
::
actor_handle_from_signature_list
<
typename
C
::
signatures
>::
type
spawn_typed
(
Ts
&&
...
args
)
{
return
detail
::
spawn_fwd_args
<
C
,
O
ption
s
>
(
return
detail
::
spawn_fwd_args
<
C
,
Os
>
(
[
&
](
C
*
)
{
},
std
::
forward
<
Ts
>
(
args
)...);
}
/**
* @brief Spawns a typed actor from a functor.
* @param args A functor followed by its arguments.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns An {@link actor} to the spawned {@link actor}.
*/
template
<
spawn_options
Os
,
typename
F
,
typename
...
Ts
>
typename
detail
::
infer_typed_actor_handle
<
typename
util
::
get_callable_trait
<
F
>::
result_type
,
typename
util
::
tl_head
<
typename
util
::
get_callable_trait
<
F
>::
arg_types
>::
type
>::
type
spawn_typed
(
F
fun
,
Ts
&&
...
args
)
{
typedef
typename
detail
::
infer_typed_actor_base
<
typename
util
::
get_callable_trait
<
F
>::
result_type
,
typename
util
::
tl_head
<
typename
util
::
get_callable_trait
<
F
>::
arg_types
>::
type
>::
type
impl
;
return
detail
::
spawn_fwd_args
<
impl
,
Os
>
(
[
&
](
impl
*
)
{
},
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
args
)...);
}
/** @} */
}
// namespace cppa
...
...
cppa/spawn_fwd.hpp
View file @
ffed360f
...
...
@@ -45,16 +45,16 @@ namespace cppa {
* untyped actors *
******************************************************************************/
template
<
class
Impl
,
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
class
Impl
,
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
template
<
class
Impl
,
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
class
Impl
,
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
/******************************************************************************
...
...
@@ -63,36 +63,46 @@ actor spawn_in_group(const group&, Ts&&... args);
namespace
detail
{
// some utility
template
<
typename
TypedBehavior
>
struct
actor_handle_from_typed_behavior
;
template
<
class
TypedBehavior
,
class
FirstArg
>
struct
infer_typed_actor_handle
;
template
<
typename
...
Signatures
>
struct
actor_handle_from_typed_behavior
<
typed_behavior
<
Signatures
...
>>
{
typedef
typed_actor
<
Signatures
...
>
type
;
// infer actor type from result type if possible
template
<
typename
...
Rs
,
class
FirstArg
>
struct
infer_typed_actor_handle
<
typed_behavior
<
Rs
...
>
,
FirstArg
>
{
typedef
typed_actor
<
Rs
...
>
type
;
};
// infer actor type from first argument if result type is void
template
<
typename
...
Rs
>
struct
infer_typed_actor_handle
<
void
,
typed_event_based_actor
<
Rs
...
>*>
{
typedef
typed_actor
<
Rs
...
>
type
;
};
template
<
typename
SignatureList
>
struct
actor_handle_from_signature_list
;
template
<
typename
...
Signature
s
>
struct
actor_handle_from_signature_list
<
util
::
type_list
<
Signature
s
...
>>
{
typedef
typed_actor
<
Signature
s
...
>
type
;
template
<
typename
...
R
s
>
struct
actor_handle_from_signature_list
<
util
::
type_list
<
R
s
...
>>
{
typedef
typed_actor
<
R
s
...
>
type
;
};
}
// namespace detail
template
<
spawn_options
Options
=
no_spawn_options
,
typename
F
>
typename
detail
::
actor_handle_from_typed_behavior
<
typename
util
::
get_callable_trait
<
F
>::
result_type
>::
type
spawn_typed
(
F
fun
);
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
template
<
class
Impl
,
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
typename
detail
::
actor_handle_from_signature_list
<
typename
Impl
::
signatures
>::
type
spawn_typed
(
Ts
&&
...
args
);
template
<
spawn_options
Os
=
no_spawn_options
,
typename
F
,
typename
...
Ts
>
typename
detail
::
infer_typed_actor_handle
<
typename
util
::
get_callable_trait
<
F
>::
result_type
,
typename
util
::
tl_head
<
typename
util
::
get_callable_trait
<
F
>::
arg_types
>::
type
>::
type
spawn_typed
(
F
fun
,
Ts
&&
...
args
);
}
// namespace cppa
#endif // CPPA_SPAWN_FWD_HPP
cppa/typed_actor.hpp
View file @
ffed360f
...
...
@@ -44,38 +44,43 @@ class local_actor;
struct
invalid_actor_addr_t
;
template
<
typename
...
Signature
s
>
template
<
typename
...
R
s
>
class
typed_event_based_actor
;
/**
* @brief Identifies a strongly typed actor.
* @tparam Rs Interface as @p replies_to<...>::with<...> parameter pack.
*/
template
<
typename
...
Signature
s
>
class
typed_actor
:
util
::
comparable
<
typed_actor
<
Signature
s
...
>>
,
util
::
comparable
<
typed_actor
<
Signature
s
...
>
,
actor_addr
>
,
util
::
comparable
<
typed_actor
<
Signature
s
...
>
,
invalid_actor_addr_t
>
{
template
<
typename
...
R
s
>
class
typed_actor
:
util
::
comparable
<
typed_actor
<
R
s
...
>>
,
util
::
comparable
<
typed_actor
<
R
s
...
>
,
actor_addr
>
,
util
::
comparable
<
typed_actor
<
R
s
...
>
,
invalid_actor_addr_t
>
{
friend
class
local_actor
;
// friend with all possible instantiations
template
<
typename
...
>
friend
class
typed_actor
;
public:
/**
* @brief Identifies the behavior type actors of this kind use
* for their behavior stack.
*/
typedef
typed_behavior
<
Signature
s
...
>
behavior_type
;
typedef
typed_behavior
<
R
s
...
>
behavior_type
;
/**
* @brief Identifies pointers to instances of this kind of actor.
*/
typedef
typed_event_based_actor
<
Signature
s
...
>*
pointer
;
typedef
typed_event_based_actor
<
R
s
...
>*
pointer
;
/**
* @brief Identifies the base class for this kind of actor.
*/
typedef
typed_event_based_actor
<
Signature
s
...
>
base
;
typedef
typed_event_based_actor
<
R
s
...
>
base
;
typedef
util
::
type_list
<
Signature
s
...
>
signatures
;
typedef
util
::
type_list
<
R
s
...
>
signatures
;
typed_actor
()
=
default
;
typed_actor
(
typed_actor
&&
)
=
default
;
...
...
@@ -83,13 +88,13 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
typed_actor
&
operator
=
(
typed_actor
&&
)
=
default
;
typed_actor
&
operator
=
(
const
typed_actor
&
)
=
default
;
template
<
typename
...
Other
Signature
s
>
typed_actor
(
const
typed_actor
<
Other
Signature
s
...
>&
other
)
{
template
<
typename
...
Other
R
s
>
typed_actor
(
const
typed_actor
<
Other
R
s
...
>&
other
)
{
set
(
std
::
move
(
other
));
}
template
<
typename
...
Other
Signature
s
>
typed_actor
&
operator
=
(
const
typed_actor
<
Other
Signature
s
...
>&
other
)
{
template
<
typename
...
Other
R
s
>
typed_actor
&
operator
=
(
const
typed_actor
<
Other
R
s
...
>&
other
)
{
set
(
std
::
move
(
other
));
return
*
this
;
}
...
...
@@ -99,6 +104,14 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
set
(
other
);
}
pointer
operator
->
()
const
{
return
static_cast
<
pointer
>
(
m_ptr
.
get
());
}
base
&
operator
*
()
const
{
return
static_cast
<
base
&>
(
*
m_ptr
.
get
());
}
/**
* @brief Queries the address of the stored actor.
*/
...
...
@@ -110,6 +123,10 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
return
address
().
compare
(
rhs
);
}
inline
intptr_t
compare
(
const
typed_actor
&
other
)
const
{
return
compare
(
other
.
address
());
}
inline
intptr_t
compare
(
const
invalid_actor_addr_t
&
)
const
{
return
m_ptr
?
1
:
0
;
}
...
...
@@ -122,9 +139,9 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
"'this' must be a strict subset of 'other'"
);
}
template
<
typename
...
Other
Signature
s
>
inline
void
set
(
const
typed_actor
<
Other
Signature
s
...
>&
other
)
{
check_signatures
<
signatures
,
util
::
type_list
<
Other
Signature
s
...
>>
();
template
<
typename
...
Other
R
s
>
inline
void
set
(
const
typed_actor
<
Other
R
s
...
>&
other
)
{
check_signatures
<
signatures
,
util
::
type_list
<
Other
R
s
...
>>
();
m_ptr
=
other
.
m_ptr
;
}
...
...
cppa/typed_behavior.hpp
View file @
ffed360f
...
...
@@ -40,6 +40,9 @@ namespace cppa {
namespace
detail
{
template
<
typename
...
Rs
>
class
functor_based_typed_actor
;
template
<
typename
T
>
struct
match_hint_to_void
{
typedef
T
type
;
...
...
@@ -49,18 +52,40 @@ template<>
struct
match_hint_to_void
<
match_hint
>
{
typedef
void
type
;
};
template
<
typename
T
>
struct
infer_result_from_continue_helper
{
typedef
T
type
;
};
template
<
typename
R
>
struct
infer_result_from_continue_helper
<
typed_continue_helper
<
R
>>
{
typedef
R
type
;
};
template
<
class
List
>
struct
collapse_infered_list
{
typedef
List
type
;
};
template
<
typename
...
Ts
>
struct
collapse_infered_list
<
util
::
type_list
<
util
::
type_list
<
Ts
...
>>>
{
typedef
util
::
type_list
<
Ts
...
>
type
;
};
template
<
typename
T
>
struct
all_match_hints_to_void
{
struct
infer_response_types
{
typedef
typename
T
::
input_types
input_types
;
typedef
typename
util
::
tl_map
<
typename
T
::
output_types
,
match_hint_to_void
match_hint_to_void
,
infer_result_from_continue_helper
>::
type
output_types
;
typedef
typename
replies_to_from_type_list
<
input_types
,
output_types
// continue_helper stores a type list,
// so we need to collapse the list here
typename
collapse_infered_list
<
output_types
>::
type
>::
type
type
;
};
...
...
@@ -81,22 +106,23 @@ void static_check_typed_behavior_input() {
}
// namespace detail
template
<
typename
...
Signature
s
>
template
<
typename
...
R
s
>
class
typed_actor
;
template
<
class
Base
,
class
Subtype
,
class
BehaviorType
>
class
behavior_stack_based_impl
;
template
<
typename
...
Signature
s
>
template
<
typename
...
R
s
>
class
typed_behavior
{
template
<
typename
...
Other
Signature
s
>
template
<
typename
...
Other
R
s
>
friend
class
typed_actor
;
template
<
class
Base
,
class
Subtype
,
class
BehaviorType
>
friend
class
behavior_stack_based_impl
;
typed_behavior
()
=
delete
;
template
<
typename
...
>
friend
class
detail
::
functor_based_typed_actor
;
public:
...
...
@@ -105,7 +131,7 @@ class typed_behavior {
typed_behavior
&
operator
=
(
typed_behavior
&&
)
=
default
;
typed_behavior
&
operator
=
(
const
typed_behavior
&
)
=
default
;
typedef
util
::
type_list
<
Signature
s
...
>
signatures
;
typedef
util
::
type_list
<
R
s
...
>
signatures
;
template
<
typename
...
Cs
,
typename
...
Ts
>
typed_behavior
(
match_expr
<
Cs
...
>
expr
,
Ts
&&
...
args
)
{
...
...
@@ -139,6 +165,8 @@ class typed_behavior {
private:
typed_behavior
()
=
default
;
behavior
&
unbox
()
{
return
m_bhvr
;
}
template
<
typename
...
Cs
>
...
...
@@ -148,15 +176,18 @@ class typed_behavior {
detail
::
match_expr_has_no_guard
<
Cs
>::
value
...
>::
value
,
"typed actors are not allowed to use guard expressions"
);
// returning a match_hint from a message handler does
// not send anything back, so we can consider match_hint to be void
// do some transformation before type-checking the input signatures
typedef
typename
util
::
tl_map
<
util
::
type_list
<
typename
detail
::
deduce_signature
<
Cs
>::
type
...
>
,
detail
::
all_match_hints_to_void
// returning a match_hint from a message handler does
// not send anything back, so we can consider
// match_hint to be void
detail
::
infer_response_types
>::
type
input
;
// check types
detail
::
static_check_typed_behavior_input
<
signatures
,
input
>
();
// final (type-erasure) step
m_bhvr
=
std
::
move
(
expr
);
...
...
cppa/typed_event_based_actor.hpp
View file @
ffed360f
...
...
@@ -40,12 +40,22 @@
namespace
cppa
{
template
<
typename
...
Signatures
>
/**
* @brief A cooperatively scheduled, event-based actor implementation
* with strong type checking.
*
* This is the recommended base class for user-defined actors and is used
* implicitly when spawning typed, functor-based actors without the
* {@link blocking_api} flag.
*
* @extends local_actor
*/
template
<
typename
...
Rs
>
class
typed_event_based_actor
:
public
extend
<
local_actor
,
typed_event_based_actor
<
Signature
s
...
>>::
template
:
public
extend
<
local_actor
,
typed_event_based_actor
<
R
s
...
>>::
template
with
<
mailbox_based
,
behavior_stack_based
<
typed_behavior
<
Signature
s
...>
typed_behavior
<
R
s
...>
>::
template
impl
,
sync_sender
<
nonblocking_response_handle_tag
...
...
@@ -53,9 +63,13 @@ class typed_event_based_actor
public:
typedef
util
::
type_list
<
Signature
s
...
>
signatures
;
typedef
util
::
type_list
<
R
s
...
>
signatures
;
typedef
typed_behavior
<
Signatures
...
>
behavior_type
;
typedef
typed_behavior
<
Rs
...
>
behavior_type
;
std
::
set
<
std
::
string
>
interface
()
const
override
{
return
{
detail
::
to_uniform_name
<
Rs
>
()...};
}
protected:
...
...
cppa/util/type_list.hpp
View file @
ffed360f
...
...
@@ -85,7 +85,7 @@ struct tl_head;
template
<
template
<
typename
...
>
class
List
>
struct
tl_head
<
List
<>>
{
typedef
empty_type_list
type
;
typedef
void
type
;
};
template
<
template
<
typename
...
>
class
List
,
typename
T0
,
typename
...
Ts
>
...
...
src/abstract_actor.cpp
View file @
ffed360f
...
...
@@ -66,14 +66,6 @@ abstract_actor::abstract_actor()
:
m_id
(
get_actor_registry
()
->
next_id
()),
m_is_proxy
(
false
)
,
m_exit_reason
(
exit_reason
::
not_exited
)
{
}
void
abstract_actor
::
link_to
(
const
actor
&
whom
)
{
link_to
(
whom
.
address
());
}
void
abstract_actor
::
unlink_from
(
const
actor
&
whom
)
{
unlink_from
(
whom
.
address
());
}
bool
abstract_actor
::
link_to_impl
(
const
actor_addr
&
other
)
{
if
(
other
&&
other
!=
this
)
{
guard_type
guard
{
m_mtx
};
...
...
@@ -226,4 +218,9 @@ void abstract_actor::cleanup(std::uint32_t reason) {
}
}
std
::
set
<
std
::
string
>
abstract_actor
::
interface
()
const
{
// defaults to untyped
return
std
::
set
<
std
::
string
>
{};
}
}
// namespace cppa
src/uniform_type_info_map.cpp
View file @
ffed360f
...
...
@@ -174,7 +174,7 @@ inline void deserialize_impl(unit_t&, deserializer*) { }
void
serialize_impl
(
const
actor_addr
&
addr
,
serializer
*
sink
)
{
auto
ns
=
sink
->
get_namespace
();
if
(
ns
)
ns
->
write
(
sink
,
addr
);
else
throw
std
::
runtime_error
(
"unable to serialize actor_
pt
r: "
else
throw
std
::
runtime_error
(
"unable to serialize actor_
add
r: "
"no actor addressing defined"
);
}
...
...
unit_testing/test_typed_spawn.cpp
View file @
ffed360f
...
...
@@ -204,7 +204,13 @@ void test_event_testee() {
self
->
send
(
et
,
.3
f
);
self
->
send
(
et
,
"hello again event testee!"
);
self
->
send
(
et
,
"goodbye event testee!"
);
self
->
send
(
et
,
get_state_msg
{});
typed_actor
<
replies_to
<
get_state_msg
>::
with
<
string
>>
sub_et
=
et
;
set
<
string
>
iface
{
"cppa::replies_to<get_state_msg>::with<@str>"
,
"cppa::replies_to<@str>::with<void>"
,
"cppa::replies_to<float>::with<void>"
,
"cppa::replies_to<@i32>::with<void>"
};
CPPA_CHECK
(
sub_et
->
interface
()
==
iface
);
self
->
send
(
sub_et
,
get_state_msg
{});
self
->
receive
(
on_arg_match
>>
[
&
](
const
string
&
str
)
{
result
=
str
;
...
...
@@ -219,6 +225,88 @@ void test_event_testee() {
CPPA_CHECK_EQUAL
(
result
,
"wait4int"
);
}
/******************************************************************************
* simple 'forwarding' chain *
******************************************************************************/
typedef
typed_actor
<
replies_to
<
string
>::
with
<
string
>>
string_actor
;
void
simple_relay
(
string_actor
::
pointer
self
,
string_actor
master
,
bool
leaf
)
{
string_actor
next
=
leaf
?
spawn_typed
(
simple_relay
,
master
,
false
)
:
master
;
self
->
link_to
(
next
);
self
->
become
(
on_arg_match
>>
[
=
](
const
string
&
str
)
{
return
self
->
sync_send
(
next
,
str
).
then
(
[](
const
string
&
answer
)
->
string
{
return
answer
;
}
);
}
);
}
string_actor
::
behavior_type
simple_string_reverter
()
{
return
{
on_arg_match
>>
[](
const
string
&
str
)
{
return
string
{
str
.
rbegin
(),
str
.
rend
()};
}
};
}
void
test_simple_string_reverter
()
{
scoped_actor
self
;
// actor-under-test
auto
aut
=
self
->
spawn_typed
<
monitored
>
(
simple_relay
,
spawn_typed
(
simple_string_reverter
),
true
);
set
<
string
>
iface
{
"cppa::replies_to<@str>::with<@str>"
};
CPPA_CHECK
(
aut
->
interface
()
==
iface
);
self
->
sync_send
(
aut
,
"Hello World!"
).
await
(
[](
const
string
&
answer
)
{
CPPA_CHECK_EQUAL
(
answer
,
"!dlroW olleH"
);
}
);
anon_send_exit
(
aut
,
exit_reason
::
user_shutdown
);
}
/******************************************************************************
* sending typed actor handles *
******************************************************************************/
typedef
typed_actor
<
replies_to
<
int
>::
with
<
int
>>
int_actor
;
int_actor
::
behavior_type
int_fun
()
{
return
{
on_arg_match
>>
[](
int
i
)
{
return
i
*
i
;
}
};
}
behavior
foo
(
event_based_actor
*
self
)
{
return
{
on_arg_match
>>
[
=
](
int
i
,
int_actor
server
)
{
return
self
->
sync_send
(
server
,
i
).
then
(
[
=
](
int
result
)
->
int
{
self
->
quit
(
exit_reason
::
normal
);
return
result
;
}
);
}
};
}
void
test_sending_typed_actors
()
{
scoped_actor
self
;
auto
aut
=
spawn_typed
(
int_fun
);
self
->
send
(
spawn
(
foo
),
10
,
aut
);
self
->
receive
(
on_arg_match
>>
[](
int
i
)
{
CPPA_CHECK_EQUAL
(
i
,
100
);
}
);
self
->
send_exit
(
aut
,
exit_reason
::
user_shutdown
);
}
/******************************************************************************
* put it all together *
...
...
@@ -229,9 +317,10 @@ int main() {
// announce stuff
announce_tag
<
get_state_msg
>
();
announce
<
int_actor
>
();
announce
<
my_request
>
(
&
my_request
::
a
,
&
my_request
::
b
);
// run test series with typed_server
*
// run test series with typed_server
(1|2)
test_typed_spawn
(
spawn_typed
(
typed_server1
));
CPPA_CHECKPOINT
();
await_all_actors_done
();
...
...
@@ -255,117 +344,17 @@ int main() {
CPPA_CHECKPOINT
();
await_all_actors_done
();
// call it a day
shutdown
();
/*
auto sptr = spawn_typed_server();
sync_send(sptr, my_request{2, 2}).await(
[](bool value) {
CPPA_CHECK_EQUAL(value, true);
}
);
send_exit(sptr, exit_reason::user_shutdown);
sptr = spawn_typed<typed_testee>();
sync_send(sptr, my_request{2, 2}).await(
[](bool value) {
CPPA_CHECK_EQUAL(value, true);
}
);
send_exit(sptr, exit_reason::user_shutdown);
auto ptr0 = spawn_typed(
on_arg_match >> [](double d) {
return d * d;
},
on_arg_match >> [](float f) {
return f / 2.0f;
}
);
CPPA_CHECK((std::is_same<
decltype(ptr0),
typed_actor_ptr<
replies_to<double>::with<double>,
replies_to<float>::with<float>
>
>::value));
typed_actor_ptr<replies_to<double>::with<double>> ptr0_double = ptr0;
typed_actor_ptr<replies_to<float>::with<float>> ptr0_float = ptr0;
auto ptr = spawn_typed(
on<int>() >> [] { return "wtf"; },
on<string>() >> [] { return 42; },
on<float>() >> [] { return make_cow_tuple(1, 2, 3); },
on<double>() >> [=](double d) {
return sync_send(ptr0_double, d).then(
[](double res) { return res + res; }
);
}
);
// check async messages
send(ptr0_float, 4.0f);
receive(
on_arg_match >> [](float f) {
CPPA_CHECK_EQUAL(f, 4.0f / 2.0f);
}
);
// check sync messages
sync_send(ptr0_float, 4.0f).await(
[](float f) {
CPPA_CHECK_EQUAL(f, 4.0f / 2.0f);
}
);
sync_send(ptr, 10.0).await(
[](double d) {
CPPA_CHECK_EQUAL(d, 200.0);
}
);
sync_send(ptr, 42).await(
[](const std::string& str) {
CPPA_CHECK_EQUAL(str, "wtf");
}
);
sync_send(ptr, 1.2f).await(
[](int a, int b, int c) {
CPPA_CHECK_EQUAL(a, 1);
CPPA_CHECK_EQUAL(b, 2);
CPPA_CHECK_EQUAL(c, 3);
}
);
sync_send(ptr, 1.2f).await(
[](int b, int c) {
CPPA_CHECK_EQUAL(b, 2);
CPPA_CHECK_EQUAL(c, 3);
}
);
sync_send(ptr, 1.2f).await(
[](int c) {
CPPA_CHECK_EQUAL(c, 3);
}
);
sync_send(ptr, 1.2f).await(
[] { CPPA_CHECKPOINT(); }
);
spawn([=] {
sync_send(ptr, 2.3f).then(
[] (int c) {
CPPA_CHECK_EQUAL(c, 3);
return "hello continuation";
}
).continue_with(
[] (const string& str) {
CPPA_CHECK_EQUAL(str, "hello continuation");
return 4.2;
}
).continue_with(
[=] (double d) {
CPPA_CHECK_EQUAL(d, 4.2);
send_exit(ptr0, exit_reason::user_shutdown);
send_exit(ptr, exit_reason::user_shutdown);
self->quit();
}
);
});
// run test series with string reverter
test_simple_string_reverter
();
CPPA_CHECKPOINT
();
await_all_actors_done
();
// run test series with sending of typed actors
test_sending_typed_actors
();
CPPA_CHECKPOINT
();
await_all_actors_done
();
// call it a day
shutdown
();
*/
return
CPPA_TEST_RESULT
();
}
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