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
3b25a510
Commit
3b25a510
authored
Feb 02, 2014
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
typed actors: proper impl for spawning & sending
parent
3ce764a9
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
417 additions
and
230 deletions
+417
-230
cppa.files
cppa.files
+3
-2
cppa/announce.hpp
cppa/announce.hpp
+19
-6
cppa/cppa_fwd.hpp
cppa/cppa_fwd.hpp
+0
-17
cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/default_uniform_type_info_impl.hpp
+54
-2
cppa/local_actor.hpp
cppa/local_actor.hpp
+60
-16
cppa/replies_to.hpp
cppa/replies_to.hpp
+8
-0
cppa/spawn.hpp
cppa/spawn.hpp
+47
-115
cppa/spawn_fwd.hpp
cppa/spawn_fwd.hpp
+48
-45
cppa/typed_actor.hpp
cppa/typed_actor.hpp
+1
-1
cppa/typed_behavior.hpp
cppa/typed_behavior.hpp
+59
-23
unit_testing/test_typed_spawn.cpp
unit_testing/test_typed_spawn.cpp
+118
-3
No files found.
cppa.files
View file @
3b25a510
...
...
@@ -166,7 +166,9 @@ cppa/serializer.hpp
cppa/single_timeout.hpp
cppa/singletons.hpp
cppa/spawn.hpp
cppa/spawn_fwd.hpp
cppa/spawn_options.hpp
cppa/sync_sender.hpp
cppa/system_messages.hpp
cppa/timeout_definition.hpp
cppa/to_string.hpp
...
...
@@ -176,6 +178,7 @@ cppa/type_lookup_table.hpp
cppa/typed_actor.hpp
cppa/typed_actor_ptr.hpp
cppa/typed_behavior.hpp
cppa/typed_continue_helper.hpp
cppa/typed_event_based_actor.hpp
cppa/uniform_type_info.hpp
cppa/unit.hpp
...
...
@@ -345,5 +348,3 @@ unit_testing/test_tuple.cpp
unit_testing/test_typed_spawn.cpp
unit_testing/test_uniform_type.cpp
unit_testing/test_yield_interface.cpp
cppa/typed_continue_helper.hpp
cppa/sync_sender.hpp
cppa/announce.hpp
View file @
3b25a510
...
...
@@ -156,16 +156,29 @@ compound_member(const std::pair<GRes (Parent::*)() const,
return
{
gspair
,
new
detail
::
default_uniform_type_info_impl
<
mtype
>
(
args
...)};
}
/**
* @brief Adds a new type mapping for @p T to the libcppa type system.
* @param args Members of @p T.
* @brief Adds a new type mapping for @p C to the libcppa type system.
* @tparam C A class that is default constructible, copy constructible,
* and comparable.
* @param arg First members of @p C.
* @param args Additional members of @p C.
* @warning @p announce is <b>not</b> thead safe!
*/
template
<
typename
T
,
typename
...
Ts
>
template
<
class
C
,
typename
...
Ts
>
inline
const
uniform_type_info
*
announce
(
const
Ts
&
...
args
)
{
auto
ptr
=
new
detail
::
default_uniform_type_info_impl
<
T
>
(
args
...);
return
announce
(
typeid
(
T
),
std
::
unique_ptr
<
uniform_type_info
>
{
ptr
});
auto
ptr
=
new
detail
::
default_uniform_type_info_impl
<
C
>
(
args
...);
return
announce
(
typeid
(
C
),
std
::
unique_ptr
<
uniform_type_info
>
{
ptr
});
}
/**
* @brief Adds a new type mapping for an empty or "tag" class.
* @tparam C A class without any member.
* @warning @p announce_tag is <b>not</b> thead safe!
*/
template
<
class
C
>
inline
const
uniform_type_info
*
announce_tag
()
{
auto
ptr
=
new
detail
::
empty_uniform_type_info_impl
<
C
>
();
return
announce
(
typeid
(
C
),
std
::
unique_ptr
<
uniform_type_info
>
{
ptr
});
}
/**
...
...
cppa/cppa_fwd.hpp
View file @
3b25a510
...
...
@@ -33,8 +33,6 @@
#include <cstdint>
#include "cppa/spawn_options.hpp"
namespace
cppa
{
// classes
...
...
@@ -76,21 +74,6 @@ typedef intrusive_ptr<node_id> node_id_ptr;
// weak intrusive pointer typedefs
typedef
weak_intrusive_ptr
<
actor_proxy
>
weak_actor_proxy_ptr
;
// prototype definitions of the spawn function famility;
// implemented in spawn.hpp (this header is included there)
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
template
<
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
template
<
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
}
// namespace cppa
#endif // CPPA_FWD_HPP
cppa/detail/default_uniform_type_info_impl.hpp
View file @
3b25a510
...
...
@@ -457,16 +457,68 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
m_members
.
push_back
(
unique_uti
(
new
result_type
));
}
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
override
{
for
(
auto
&
m
:
m_members
)
m
->
serialize
(
obj
,
s
);
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
override
{
for
(
auto
&
m
:
m_members
)
m
->
deserialize
(
obj
,
d
);
}
};
template
<
typename
T
>
class
empty_uniform_type_info_impl
:
public
uniform_type_info
{
public:
bool
equals
(
const
std
::
type_info
&
tinfo
)
const
override
{
return
typeid
(
T
)
==
tinfo
;
}
const
char
*
name
()
const
override
{
return
m_name
.
c_str
();
}
any_tuple
as_any_tuple
(
void
*
)
const
override
{
return
make_any_tuple
(
T
{});
}
void
serialize
(
const
void
*
,
serializer
*
)
const
override
{
// no members means: nothing to do
}
void
deserialize
(
void
*
,
deserializer
*
)
const
override
{
// no members means: nothing to do
}
empty_uniform_type_info_impl
()
{
auto
uname
=
detail
::
to_uniform_name
<
T
>
();
auto
cname
=
detail
::
mapped_name_by_decorated_name
(
uname
.
c_str
());
if
(
cname
==
uname
.
c_str
())
m_name
=
std
::
move
(
uname
);
else
m_name
=
cname
;
}
protected:
bool
equals
(
const
void
*
,
const
void
*
)
const
override
{
return
true
;
}
void
*
new_instance
(
const
void
*
)
const
override
{
return
new
T
();
}
void
delete_instance
(
void
*
instance
)
const
override
{
delete
reinterpret_cast
<
T
*>
(
instance
);
}
private:
std
::
string
m_name
;
};
}
}
// namespace detail
#endif // CPPA_DEFAULT_UNIFORM_TYPE_INFO_IMPL_HPP
cppa/local_actor.hpp
View file @
3b25a510
...
...
@@ -39,9 +39,9 @@
#include "cppa/extend.hpp"
#include "cppa/channel.hpp"
#include "cppa/behavior.hpp"
#include "cppa/cppa_fwd.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/spawn_fwd.hpp"
#include "cppa/message_id.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/actor_state.hpp"
...
...
@@ -91,31 +91,66 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
~
local_actor
();
/**************************************************************************
* spawn untyped actors *
**************************************************************************/
template
<
class
Impl
,
spawn_options
Option
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
class
C
,
spawn_options
O
s
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
)
{
auto
res
=
cppa
::
spawn
<
Impl
,
make_unbound
(
Options
)
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Options
,
std
::
move
(
res
));
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn
<
C
,
os
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
template
<
spawn_options
O
ption
s
=
no_spawn_options
,
typename
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
)
{
auto
res
=
cppa
::
spawn
<
make_unbound
(
Options
)
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Options
,
std
::
move
(
res
));
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn
<
os
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
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
&
grp
,
Ts
&&
...
args
)
{
auto
res
=
cppa
::
spawn_in_group
<
make_unbound
(
Options
)
>
(
grp
,
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Options
,
std
::
move
(
res
));
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn_in_group
<
os
>
(
grp
,
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
template
<
class
Impl
,
spawn_options
Option
s
,
typename
...
Ts
>
template
<
class
C
,
spawn_options
O
s
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
grp
,
Ts
&&
...
args
)
{
auto
res
=
cppa
::
spawn_in_group
<
Impl
,
make_unbound
(
Options
)
>
(
grp
,
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Options
,
std
::
move
(
res
));
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn_in_group
<
C
,
os
>
(
grp
,
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
/**************************************************************************
* 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
>::
type
spawn_typed
(
F
fun
)
{
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn_typed
<
os
>
(
std
::
move
(
fun
));
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
template
<
class
C
,
spawn_options
Os
=
no_spawn_options
,
typename
...
Ts
>
typename
detail
::
actor_handle_from_signature_list
<
typename
C
::
signatures
>::
type
spawn_typed
(
Ts
&&
...
args
)
{
constexpr
auto
os
=
make_unbound
(
Os
);
auto
res
=
cppa
::
spawn_typed
<
C
,
os
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_opts
(
Os
,
std
::
move
(
res
));
}
/**************************************************************************
* send asynchronous messages *
**************************************************************************/
/**
* @brief Sends @p what to the receiver specified in @p dest.
*/
...
...
@@ -283,6 +318,10 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
make_any_tuple
(
std
::
forward
<
Ts
>
(
args
)...));
}
/**************************************************************************
* miscellaneous actor operations *
**************************************************************************/
/**
* @brief Causes this actor to subscribe to the group @p what.
*
...
...
@@ -422,16 +461,21 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
on_sync_failure
(
fun
);
}
/**************************************************************************
* here be dragons: end of public interface *
**************************************************************************/
/** @cond PRIVATE */
local_actor
();
inline
actor
eval_opts
(
spawn_options
opts
,
actor
res
)
{
template
<
class
ActorHandle
>
inline
ActorHandle
eval_opts
(
spawn_options
opts
,
ActorHandle
res
)
{
if
(
has_monitor_flag
(
opts
))
{
monitor
(
res
);
monitor
(
res
.
address
()
);
}
if
(
has_link_flag
(
opts
))
{
link_to
(
res
);
link_to
(
res
.
address
()
);
}
return
res
;
}
...
...
cppa/replies_to.hpp
View file @
3b25a510
...
...
@@ -44,6 +44,14 @@ struct replies_to {
};
};
template
<
class
InputList
,
class
OutputList
>
struct
replies_to_from_type_list
;
template
<
typename
...
Is
,
typename
...
Os
>
struct
replies_to_from_type_list
<
util
::
type_list
<
Is
...
>
,
util
::
type_list
<
Os
...
>>
{
typedef
typename
replies_to
<
Is
...
>::
template
with
<
Os
...>
type
;
};
}
// namespace cppa
#endif // CPPA_REPLIES_TO_HPP
cppa/spawn.hpp
View file @
3b25a510
...
...
@@ -35,8 +35,8 @@
#include "cppa/policy.hpp"
#include "cppa/logging.hpp"
#include "cppa/cppa_fwd.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/spawn_fwd.hpp"
#include "cppa/typed_actor.hpp"
#include "cppa/spawn_options.hpp"
#include "cppa/typed_event_based_actor.hpp"
...
...
@@ -54,48 +54,48 @@ namespace cppa {
namespace
detail
{
template
<
class
Impl
,
spawn_options
Opt
s
,
typename
BeforeLaunch
,
typename
...
Ts
>
intrusive_ptr
<
Impl
>
spawn_impl
(
BeforeLaunch
before_launch_fun
,
Ts
&&
...
args
)
{
static_assert
(
!
std
::
is_base_of
<
blocking_actor
,
Impl
>::
value
||
has_blocking_api_flag
(
O
pt
s
),
"
Impl
is derived type of blocking_actor but "
template
<
class
C
,
spawn_options
O
s
,
typename
BeforeLaunch
,
typename
...
Ts
>
intrusive_ptr
<
C
>
spawn_impl
(
BeforeLaunch
before_launch_fun
,
Ts
&&
...
args
)
{
static_assert
(
!
std
::
is_base_of
<
blocking_actor
,
C
>::
value
||
has_blocking_api_flag
(
Os
),
"
C
is derived type of blocking_actor but "
"blocking_api_flag is missing"
);
static_assert
(
is_unbound
(
O
pt
s
),
static_assert
(
is_unbound
(
Os
),
"top-level spawns cannot have monitor or link flag"
);
CPPA_LOGF_TRACE
(
"spawn "
<<
detail
::
demangle
<
Impl
>
());
CPPA_LOGF_TRACE
(
"spawn "
<<
detail
::
demangle
<
C
>
());
// runtime check wheter context_switching_resume can be used,
// i.e., add the detached flag if libcppa compiled without fiber support
// when using the blocking API
if
(
has_blocking_api_flag
(
O
pt
s
)
&&
!
has_detach_flag
(
O
pt
s
)
if
(
has_blocking_api_flag
(
Os
)
&&
!
has_detach_flag
(
Os
)
&&
util
::
fiber
::
is_disabled_feature
())
{
return
spawn_impl
<
Impl
,
Opt
s
+
detached
>
(
before_launch_fun
,
return
spawn_impl
<
C
,
O
s
+
detached
>
(
before_launch_fun
,
std
::
forward
<
Ts
>
(
args
)...);
}
/*
using scheduling_policy = typename std::conditional<
has_detach_flag(O
pt
s),
has_detach_flag(Os),
policy::no_scheduling,
policy::cooperative_scheduling
>::type;
*/
using
scheduling_policy
=
policy
::
no_scheduling
;
using
priority_policy
=
typename
std
::
conditional
<
has_priority_aware_flag
(
O
pt
s
),
has_priority_aware_flag
(
Os
),
policy
::
prioritizing
,
policy
::
not_prioritizing
>::
type
;
using
resume_policy
=
typename
std
::
conditional
<
has_blocking_api_flag
(
O
pt
s
),
has_blocking_api_flag
(
Os
),
typename
std
::
conditional
<
has_detach_flag
(
O
pt
s
),
has_detach_flag
(
Os
),
policy
::
no_resume
,
policy
::
context_switching_resume
>::
type
,
policy
::
event_based_resume
>::
type
;
using
invoke_policy
=
typename
std
::
conditional
<
has_blocking_api_flag
(
O
pt
s
),
has_blocking_api_flag
(
Os
),
policy
::
nestable_invoke
,
policy
::
sequential_invoke
>::
type
;
...
...
@@ -103,11 +103,11 @@ intrusive_ptr<Impl> spawn_impl(BeforeLaunch before_launch_fun, Ts&&... args) {
priority_policy
,
resume_policy
,
invoke_policy
>
;
using
proper_impl
=
detail
::
proper_actor
<
Impl
,
policies
>
;
using
proper_impl
=
detail
::
proper_actor
<
C
,
policies
>
;
auto
ptr
=
make_counted
<
proper_impl
>
(
std
::
forward
<
Ts
>
(
args
)...);
CPPA_PUSH_AID
(
ptr
->
id
());
before_launch_fun
(
ptr
.
get
());
ptr
->
launch
(
has_hide_flag
(
O
pt
s
));
ptr
->
launch
(
has_hide_flag
(
Os
));
return
ptr
;
}
...
...
@@ -132,9 +132,9 @@ struct spawn_fwd<scoped_actor> {
// forwards the arguments to spawn_impl, replacing pointers
// to actors with instances of 'actor'
template
<
class
Impl
,
spawn_options
Opt
s
,
typename
BeforeLaunch
,
typename
...
Ts
>
intrusive_ptr
<
Impl
>
spawn_fwd_args
(
BeforeLaunch
before_launch_fun
,
Ts
&&
...
args
)
{
return
spawn_impl
<
Impl
,
Opt
s
>
(
template
<
class
C
,
spawn_options
O
s
,
typename
BeforeLaunch
,
typename
...
Ts
>
intrusive_ptr
<
C
>
spawn_fwd_args
(
BeforeLaunch
before_launch_fun
,
Ts
&&
...
args
)
{
return
spawn_impl
<
C
,
O
s
>
(
before_launch_fun
,
spawn_fwd
<
typename
util
::
rm_const_and_ref
<
Ts
>::
type
>::
fwd
(
std
::
forward
<
Ts
>
(
args
))...);
...
...
@@ -148,70 +148,70 @@ intrusive_ptr<Impl> spawn_fwd_args(BeforeLaunch before_launch_fun, Ts&&... args)
*/
/**
* @brief Spawns an actor of type @p
Impl
.
* @brief Spawns an actor of type @p
C
.
* @param args Constructor arguments.
* @tparam
Impl
Subtype of {@link event_based_actor} or {@link sb_actor}.
* @tparam O
pt
s Optional flags to modify <tt>spawn</tt>'s behavior.
* @tparam
C
Subtype of {@link event_based_actor} or {@link sb_actor}.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns An {@link actor} to the spawned {@link actor}.
*/
template
<
class
Impl
,
spawn_options
Opt
s
,
typename
...
Ts
>
template
<
class
C
,
spawn_options
O
s
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
)
{
return
detail
::
spawn_fwd_args
<
Impl
,
Opt
s
>
(
[](
Impl
*
)
{
/* no-op as BeforeLaunch callback */
},
return
detail
::
spawn_fwd_args
<
C
,
O
s
>
(
[](
C
*
)
{
/* no-op as BeforeLaunch callback */
},
std
::
forward
<
Ts
>
(
args
)...);
}
/**
* @brief Spawns a new {@link actor} that evaluates given arguments.
* @param args A functor followed by its arguments.
* @tparam O
pt
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} to the spawned {@link actor}.
*/
//template<spawn_options O
pt
s = no_spawn_options, typename... Ts>
template
<
spawn_options
O
pt
s
,
typename
...
Ts
>
//template<spawn_options Os = no_spawn_options, typename... Ts>
template
<
spawn_options
Os
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"too few arguments provided"
);
using
base_class
=
typename
std
::
conditional
<
has_blocking_api_flag
(
O
pt
s
),
has_blocking_api_flag
(
Os
),
detail
::
functor_based_blocking_actor
,
detail
::
functor_based_actor
>::
type
;
return
spawn
<
base_class
,
O
pt
s
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
spawn
<
base_class
,
Os
>
(
std
::
forward
<
Ts
>
(
args
)...);
}
/**
* @brief Spawns a new actor that evaluates given arguments and
* immediately joins @p grp.
* @param args A functor followed by its arguments.
* @tparam O
pt
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} to the spawned {@link actor}.
* @note The spawned has joined the group before this function returns.
*/
template
<
spawn_options
O
pt
s
,
typename
...
Ts
>
template
<
spawn_options
Os
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
grp
,
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"too few arguments provided"
);
using
base_class
=
typename
std
::
conditional
<
has_blocking_api_flag
(
O
pt
s
),
has_blocking_api_flag
(
Os
),
detail
::
functor_based_blocking_actor
,
detail
::
functor_based_actor
>::
type
;
return
detail
::
spawn_fwd_args
<
base_class
,
O
pt
s
>
(
return
detail
::
spawn_fwd_args
<
base_class
,
Os
>
(
[
&
](
base_class
*
ptr
)
{
ptr
->
join
(
grp
);
},
std
::
forward
<
Ts
>
(
args
)...);
}
/**
* @brief Spawns an actor of type @p
Impl
that immediately joins @p grp.
* @brief Spawns an actor of type @p
C
that immediately joins @p grp.
* @param args Constructor arguments.
* @tparam
Impl
Subtype of {@link event_based_actor} or {@link sb_actor}.
* @tparam O
pt
s Optional flags to modify <tt>spawn</tt>'s behavior.
* @tparam
C
Subtype of {@link event_based_actor} or {@link sb_actor}.
* @tparam Os Optional flags to modify <tt>spawn</tt>'s behavior.
* @returns An {@link actor} to the spawned {@link actor}.
* @note The spawned has joined the group before this function returns.
*/
template
<
class
Impl
,
spawn_options
Opt
s
,
typename
...
Ts
>
template
<
class
C
,
spawn_options
O
s
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
grp
,
Ts
&&
...
args
)
{
return
detail
::
spawn_fwd_args
<
Impl
,
Opt
s
>
(
[
&
](
Impl
*
ptr
)
{
ptr
->
join
(
grp
);
},
return
detail
::
spawn_fwd_args
<
C
,
O
s
>
(
[
&
](
C
*
ptr
)
{
ptr
->
join
(
grp
);
},
std
::
forward
<
Ts
>
(
args
)...);
}
...
...
@@ -256,25 +256,9 @@ struct actor_type_from_typed_behavior<typed_behavior<Signatures...>> {
typedef
functor_based_typed_actor
<
Signatures
...
>
type
;
};
template
<
typename
TypedBehavior
>
struct
actor_handle_from_typed_behavior
;
template
<
typename
...
Signatures
>
struct
actor_handle_from_typed_behavior
<
typed_behavior
<
Signatures
...
>>
{
typedef
typed_actor
<
Signatures
...
>
type
;
};
template
<
typename
SignatureList
>
struct
actor_handle_from_signature_list
;
template
<
typename
...
Signatures
>
struct
actor_handle_from_signature_list
<
util
::
type_list
<
Signatures
...
>>
{
typedef
typed_actor
<
Signatures
...
>
type
;
};
}
// namespace detail
template
<
spawn_options
Options
=
no_spawn_options
,
typename
F
>
template
<
spawn_options
Options
,
typename
F
>
typename
detail
::
actor_handle_from_typed_behavior
<
typename
util
::
get_callable_trait
<
F
>::
result_type
>::
type
...
...
@@ -289,68 +273,16 @@ spawn_typed(F fun) {
}
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_o
ptions
,
typename
...
Ts
>
template
<
class
C
,
spawn_options
O
ptions
,
typename
...
Ts
>
typename
detail
::
actor_handle_from_signature_list
<
typename
Impl
::
signatures
typename
C
::
signatures
>::
type
spawn_typed
(
Ts
&&
...
args
)
{
return
detail
::
spawn_fwd_args
<
Impl
,
Options
>
(
[
&
](
Impl
*
)
{
},
return
detail
::
spawn_fwd_args
<
C
,
Options
>
(
[
&
](
C
*
)
{
},
std
::
forward
<
Ts
>
(
args
)...);
}
/*
template<class Impl, spawn_options Opts = no_spawn_options, typename... Ts>
typename Impl::typed_pointer_type spawn_typed(Ts&&... args) {
static_assert(util::tl_is_distinct<typename Impl::signatures>::value,
"typed actors are not allowed to define "
"multiple patterns with identical signature");
auto p = make_counted<Impl>(std::forward<Ts>(args)...);
using result_type = typename Impl::typed_pointer_type;
return result_type::cast_from(
eval_sopts(Opts, get_scheduler()->exec(Opts, std::move(p)))
);
}
*/
/*TODO:
template<spawn_options Opts, typename... Ts>
typed_actor<typename detail::deduce_signature<Ts>::type...>
spawn_typed(const match_expr<Ts...>& me) {
static_assert(util::conjunction<
detail::match_expr_has_no_guard<Ts>::value...
>::value,
"typed actors are not allowed to use guard expressions");
static_assert(util::tl_is_distinct<
util::type_list<
typename detail::deduce_signature<Ts>::arg_types...
>
>::value,
"typed actors are not allowed to define "
"multiple patterns with identical signature");
using impl = detail::default_typed_actor<
typename detail::deduce_signature<Ts>::type...
>;
return spawn_typed<impl, Opts>(me);
}
template<typename... Ts>
typed_actor<typename detail::deduce_signature<Ts>::type...>
spawn_typed(const match_expr<Ts...>& me) {
return spawn_typed<no_spawn_options>(me);
}
template<typename T0, typename T1, typename... Ts>
auto spawn_typed(T0&& v0, T1&& v1, Ts&&... vs)
-> decltype(spawn_typed(match_expr_collect(std::forward<T0>(v0),
std::forward<T1>(v1),
std::forward<Ts>(vs)...))) {
return spawn_typed(match_expr_collect(std::forward<T0>(v0),
std::forward<T1>(v1),
std::forward<Ts>(vs)...));
}
*/
/** @} */
}
// namespace cppa
...
...
cppa/
typed_actor_ptr
.hpp
→
cppa/
spawn_fwd
.hpp
View file @
3b25a510
...
...
@@ -28,68 +28,71 @@
\******************************************************************************/
#ifndef CPPA_TYPED_ACTOR_PTR_HPP
#define CPPA_TYPED_ACTOR_PTR_HPP
// this header contains prototype definitions of the spawn function famility;
// implementations can be found in spawn.hpp (this header is included there)
#include "cppa/replies_to.hpp"
#include "cppa/match_expr.hpp"
#ifndef CPPA_SPAWN_FWD_HPP
#define CPPA_SPAWN_FWD_HPP
#include "cppa/typed_actor.hpp"
#include "cppa/spawn_options.hpp"
#include "cppa/detail/typed_actor_util.hpp"
#include "cppa/util/type_list.hpp"
namespace
cppa
{
template
<
typename
...
Signatures
>
class
typed_actor_ptr
{
/******************************************************************************
* untyped actors *
******************************************************************************/
public:
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
typedef
util
::
type_list
<
Signatures
...
>
signatures
;
template
<
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn
(
Ts
&&
...
args
);
typed_actor_ptr
()
=
default
;
typed_actor_ptr
(
typed_actor_ptr
&&
)
=
default
;
typed_actor_ptr
(
const
typed_actor_ptr
&
)
=
default
;
typed_actor_ptr
&
operator
=
(
typed_actor_ptr
&&
)
=
default
;
typed_actor_ptr
&
operator
=
(
const
typed_actor_ptr
&
)
=
default
;
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
template
<
typename
...
Others
>
typed_actor_ptr
(
typed_actor_ptr
<
Others
...
>
other
)
{
set
(
std
::
move
(
other
));
}
template
<
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor
spawn_in_group
(
const
group
&
,
Ts
&&
...
args
);
template
<
typename
...
Others
>
typed_actor_ptr
&
operator
=
(
typed_actor_ptr
<
Others
...
>
other
)
{
set
(
std
::
move
(
other
));
return
*
this
;
}
/******************************************************************************
* typed actors *
******************************************************************************/
/** @cond PRIVATE */
static
typed_actor_ptr
cast_from
(
actor_ptr
from
)
{
return
{
std
::
move
(
from
)};
}
const
actor_ptr
&
type_erased
()
const
{
return
m_ptr
;
}
actor_ptr
&
type_erased
()
{
return
m_ptr
;
}
/** @endcond */
namespace
detail
{
// some utility
private:
template
<
typename
TypedBehavior
>
struct
actor_handle_from_typed_behavior
;
typed_actor_ptr
(
actor_ptr
ptr
)
:
m_ptr
(
std
::
move
(
ptr
))
{
}
template
<
typename
...
Signatures
>
struct
actor_handle_from_typed_behavior
<
typed_behavior
<
Signatures
...
>>
{
typedef
typed_actor
<
Signatures
...
>
type
;
};
template
<
class
ListA
,
class
ListB
>
inline
void
check_signatures
()
{
static_assert
(
util
::
tl_is_strict_subset
<
ListA
,
ListB
>::
value
,
"'this' must be a strict subset of 'other'"
);
}
template
<
typename
SignatureList
>
struct
actor_handle_from_signature_list
;
template
<
typename
...
Others
>
inline
void
set
(
typed_actor_ptr
<
Others
...
>
other
)
{
check_signatures
<
signatures
,
util
::
type_list
<
Others
...
>>
();
m_ptr
=
std
::
move
(
other
.
type_erased
());
}
template
<
typename
...
Signatures
>
struct
actor_handle_from_signature_list
<
util
::
type_list
<
Signatures
...
>>
{
typedef
typed_actor
<
Signatures
...
>
type
;
};
actor_ptr
m_ptr
;
}
// 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
>
typename
detail
::
actor_handle_from_signature_list
<
typename
Impl
::
signatures
>::
type
spawn_typed
(
Ts
&&
...
args
);
}
// namespace cppa
#endif // CPPA_
TYPED_ACTOR_PTR
_HPP
#endif // CPPA_
SPAWN_FWD
_HPP
cppa/typed_actor.hpp
View file @
3b25a510
...
...
@@ -73,7 +73,7 @@ class typed_actor : util::comparable<typed_actor<Signatures...>>
/**
* @brief Identifies the base class for this kind of actor.
*/
typedef
typed_event_based_actor
<
Signatures
...
>
impl
;
typedef
typed_event_based_actor
<
Signatures
...
>
base
;
typedef
util
::
type_list
<
Signatures
...
>
signatures
;
...
...
cppa/typed_behavior.hpp
View file @
3b25a510
...
...
@@ -38,6 +38,49 @@
namespace
cppa
{
namespace
detail
{
template
<
typename
T
>
struct
match_hint_to_void
{
typedef
T
type
;
};
template
<
>
struct
match_hint_to_void
<
match_hint
>
{
typedef
void
type
;
};
template
<
typename
T
>
struct
all_match_hints_to_void
{
typedef
typename
T
::
input_types
input_types
;
typedef
typename
util
::
tl_map
<
typename
T
::
output_types
,
match_hint_to_void
>::
type
output_types
;
typedef
typename
replies_to_from_type_list
<
input_types
,
output_types
>::
type
type
;
};
// this function is called from typed_behavior<...>::set and its whole
// purpose is to give users a nicer error message on a type mismatch
// (this function only has the type informations needed to understand the error)
template
<
class
SignatureList
,
class
InputList
>
void
static_check_typed_behavior_input
()
{
constexpr
bool
is_equal
=
util
::
tl_equal
<
SignatureList
,
InputList
>::
value
;
// note: it might be worth considering to allow a wildcard in the
// InputList if its return type is identical to all "missing"
// input types ... however, it might lead to unexpected results
// and would cause a lot of not-so-straightforward code here
static_assert
(
is_equal
,
"given pattern cannot be used to initialize "
"typed behavior (exact match needed)"
);
}
}
// namespace detail
template
<
typename
...
Signatures
>
class
typed_actor
;
...
...
@@ -64,15 +107,13 @@ class typed_behavior {
typedef
util
::
type_list
<
Signatures
...
>
signatures
;
template
<
typename
...
Cs
>
typed_behavior
(
match_expr
<
Cs
...
>
expr
)
{
static_asserts
(
expr
);
set
(
std
::
move
(
expr
));
template
<
typename
...
Cs
,
typename
...
Ts
>
typed_behavior
(
match_expr
<
Cs
...
>
expr
,
Ts
&&
...
args
)
{
set
(
match_expr_collect
(
std
::
move
(
expr
),
std
::
forward
<
Ts
>
(
args
)...));
}
template
<
typename
...
Cs
>
typed_behavior
&
operator
=
(
match_expr
<
Cs
...
>
expr
)
{
static_asserts
(
expr
);
set
(
std
::
move
(
expr
));
return
*
this
;
}
...
...
@@ -101,29 +142,24 @@ class typed_behavior {
behavior
&
unbox
()
{
return
m_bhvr
;
}
template
<
typename
...
Cs
>
void
static_asserts
(
const
match_expr
<
Cs
...
>&
)
{
void
set
(
match_expr
<
Cs
...
>&&
expr
)
{
// check for (the lack of) guards
static_assert
(
util
::
conjunction
<
detail
::
match_expr_has_no_guard
<
Cs
>::
value
...
>::
value
,
"typed actors are not allowed to use guard expressions"
);
static_assert
(
util
::
tl_is_distinct
<
// returning a match_hint from a message handler does
// not send anything back, so we can consider match_hint to be void
typedef
typename
util
::
tl_map
<
util
::
type_list
<
typename
detail
::
deduce_signature
<
Cs
>::
arg_types
...
>
>::
value
,
"typed actors are not allowed to define "
"multiple patterns with identical signature"
);
}
template
<
typename
...
Cs
>
void
set
(
match_expr
<
Cs
...
>&&
expr
)
{
m_bhvr
=
std
::
move
(
expr
);
using
input
=
util
::
type_list
<
typename
detail
::
deduce_signature
<
Cs
>::
type
...
>
;
// check whether the signature is an exact match
static_assert
(
util
::
tl_equal
<
signatures
,
input
>::
value
,
"'expr' does not match given signature"
);
>
,
detail
::
all_match_hints_to_void
>::
type
input
;
detail
::
static_check_typed_behavior_input
<
signatures
,
input
>
();
// final (type-erasure) step
m_bhvr
=
std
::
move
(
expr
);
}
behavior
m_bhvr
;
...
...
unit_testing/test_typed_spawn.cpp
View file @
3b25a510
...
...
@@ -35,6 +35,10 @@
using
namespace
std
;
using
namespace
cppa
;
/******************************************************************************
* simple request/response test *
******************************************************************************/
struct
my_request
{
int
a
;
int
b
;
};
typedef
typed_actor
<
replies_to
<
my_request
>::
with
<
bool
>>
server_type
;
...
...
@@ -55,7 +59,7 @@ server_type::behavior_type typed_server2(server_type::pointer) {
return
typed_server1
();
}
class
typed_server3
:
public
server_type
::
impl
{
class
typed_server3
:
public
server_type
::
base
{
public:
...
...
@@ -71,11 +75,13 @@ class typed_server3 : public server_type::impl {
void
client
(
event_based_actor
*
self
,
actor
parent
,
server_type
serv
)
{
self
->
sync_send
(
serv
,
my_request
{
0
,
0
}).
then
(
[](
bool
value
)
{
[](
bool
value
)
->
int
{
CPPA_CHECK_EQUAL
(
value
,
true
);
return
42
;
}
)
.
continue_with
([
=
]
{
.
continue_with
([
=
](
int
ival
)
{
CPPA_CHECK_EQUAL
(
ival
,
42
);
self
->
sync_send
(
serv
,
my_request
{
10
,
20
}).
then
(
[
=
](
bool
value
)
{
CPPA_CHECK_EQUAL
(
value
,
false
);
...
...
@@ -121,9 +127,111 @@ void test_typed_spawn(server_type ts) {
self
->
send_exit
(
ts
,
exit_reason
::
user_shutdown
);
}
/******************************************************************************
* test skipping of messages intentionally + using become() *
******************************************************************************/
struct
get_state_msg
{
};
typedef
typed_actor
<
replies_to
<
get_state_msg
>::
with
<
string
>
,
replies_to
<
string
>::
with
<
void
>
,
replies_to
<
float
>::
with
<
void
>
,
replies_to
<
int
>::
with
<
void
>
>
event_testee_type
;
class
event_testee
:
public
event_testee_type
::
base
{
public:
behavior_type
wait4string
()
{
return
{
on
<
get_state_msg
>
()
>>
[]
{
return
"wait4string"
;
},
on
<
string
>
()
>>
[
=
]
{
become
(
wait4int
());
},
(
on
<
float
>
()
||
on
<
int
>
())
>>
skip_message
};
}
behavior_type
wait4int
()
{
return
{
on
<
get_state_msg
>
()
>>
[]
{
return
"wait4int"
;
},
on
<
int
>
()
>>
[
=
]
{
become
(
wait4float
());
},
(
on
<
float
>
()
||
on
<
string
>
())
>>
[]
{
return
match_hint
::
skip
;
}
};
}
behavior_type
wait4float
()
{
return
{
on
<
get_state_msg
>
()
>>
[]
{
return
"wait4float"
;
},
on
<
float
>
()
>>
[
=
]
{
become
(
wait4string
());
},
(
on
<
string
>
()
||
on
<
int
>
())
>>
[]
{
return
match_hint
::
skip
;
}
};
}
behavior_type
make_behavior
()
override
{
return
wait4int
();
}
};
void
test_event_testee
()
{
scoped_actor
self
;
auto
et
=
self
->
spawn_typed
<
event_testee
>
();
string
result
;
self
->
send
(
et
,
1
);
self
->
send
(
et
,
2
);
self
->
send
(
et
,
3
);
self
->
send
(
et
,
.1
f
);
self
->
send
(
et
,
"hello event testee!"
);
self
->
send
(
et
,
.2
f
);
self
->
send
(
et
,
.3
f
);
self
->
send
(
et
,
"hello again event testee!"
);
self
->
send
(
et
,
"goodbye event testee!"
);
self
->
send
(
et
,
get_state_msg
{});
self
->
receive
(
on_arg_match
>>
[
&
](
const
string
&
str
)
{
result
=
str
;
},
after
(
chrono
::
minutes
(
1
))
>>
[
&
]()
{
CPPA_LOGF_ERROR
(
"event_testee does not reply"
);
throw
runtime_error
(
"event_testee does not reply"
);
}
);
self
->
send_exit
(
et
,
exit_reason
::
user_shutdown
);
self
->
await_all_other_actors_done
();
CPPA_CHECK_EQUAL
(
result
,
"wait4int"
);
}
/******************************************************************************
* put it all together *
******************************************************************************/
int
main
()
{
CPPA_TEST
(
test_typed_spawn
);
// announce stuff
announce_tag
<
get_state_msg
>
();
announce
<
my_request
>
(
&
my_request
::
a
,
&
my_request
::
b
);
// run test series with typed_server*
test_typed_spawn
(
spawn_typed
(
typed_server1
));
CPPA_CHECKPOINT
();
await_all_actors_done
();
...
...
@@ -141,6 +249,13 @@ int main() {
}
CPPA_CHECKPOINT
();
await_all_actors_done
();
// run test series with event_testee
test_event_testee
();
CPPA_CHECKPOINT
();
await_all_actors_done
();
// call it a day
shutdown
();
/*
auto sptr = spawn_typed_server();
...
...
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