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
779d9171
Commit
779d9171
authored
Feb 19, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow spawning composable states directly
parent
63e96260
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
297 additions
and
244 deletions
+297
-244
libcaf_core/caf/actor_system.hpp
libcaf_core/caf/actor_system.hpp
+30
-23
libcaf_core/caf/composable_state_based_actor.hpp
libcaf_core/caf/composable_state_based_actor.hpp
+54
-0
libcaf_core/caf/infer_handle.hpp
libcaf_core/caf/infer_handle.hpp
+38
-2
libcaf_core/caf/typed_actor_pointer.hpp
libcaf_core/caf/typed_actor_pointer.hpp
+1
-1
libcaf_core/test/composable_states.cpp
libcaf_core/test/composable_states.cpp
+174
-0
libcaf_core/test/typed_spawn.cpp
libcaf_core/test/typed_spawn.cpp
+0
-218
No files found.
libcaf_core/caf/actor_system.hpp
View file @
779d9171
...
@@ -37,6 +37,7 @@
...
@@ -37,6 +37,7 @@
#include "caf/string_algorithms.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/scoped_execution_unit.hpp"
#include "caf/scoped_execution_unit.hpp"
#include "caf/uniform_type_info_map.hpp"
#include "caf/uniform_type_info_map.hpp"
#include "caf/composable_state_based_actor.hpp"
#include "caf/prohibit_top_level_spawn_marker.hpp"
#include "caf/prohibit_top_level_spawn_marker.hpp"
#include "caf/detail/spawn_fwd.hpp"
#include "caf/detail/spawn_fwd.hpp"
...
@@ -242,7 +243,7 @@ public:
...
@@ -242,7 +243,7 @@ public:
/// @param cfg To-be-filled config for the actor.
/// @param cfg To-be-filled config for the actor.
/// @param xs Constructor arguments for `C`.
/// @param xs Constructor arguments for `C`.
template
<
class
C
,
spawn_options
Os
,
class
...
Ts
>
template
<
class
C
,
spawn_options
Os
,
class
...
Ts
>
typename
infer_handle_from_class
<
C
>::
type
infer_handle_from_class_t
<
C
>
spawn_class
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
{
spawn_class
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
{
return
spawn_impl
<
C
,
Os
>
(
cfg
,
detail
::
spawn_fwd
<
Ts
>
(
xs
)...);
return
spawn_impl
<
C
,
Os
>
(
cfg
,
detail
::
spawn_fwd
<
Ts
>
(
xs
)...);
}
}
...
@@ -252,26 +253,30 @@ public:
...
@@ -252,26 +253,30 @@ public:
/// to opt-out of the cooperative scheduling.
/// to opt-out of the cooperative scheduling.
/// @param xs Constructor arguments for `C`.
/// @param xs Constructor arguments for `C`.
template
<
class
C
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
template
<
class
C
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
typename
infer_handle_from_class
<
C
>::
type
spawn
(
Ts
&&
...
xs
)
{
infer_handle_from_class_t
<
C
>
spawn
(
Ts
&&
...
xs
)
{
check_invariants
<
C
>
();
check_invariants
<
C
>
();
actor_config
cfg
;
actor_config
cfg
;
return
spawn_impl
<
C
,
Os
>
(
cfg
,
detail
::
spawn_fwd
<
Ts
>
(
xs
)...);
return
spawn_impl
<
C
,
Os
>
(
cfg
,
detail
::
spawn_fwd
<
Ts
>
(
xs
)...);
}
}
template
<
class
S
,
spawn_options
Os
=
no_spawn_options
>
infer_handle_from_state_t
<
S
>
spawn
()
{
return
spawn
<
composable_state_based_actor
<
S
>
,
Os
>
();
}
/// Called by `spawn_functor` to apply static assertions and
/// Called by `spawn_functor` to apply static assertions and
/// store an initialization function in `cfg` before calling `spawn_class`.
/// store an initialization function in `cfg` before calling `spawn_class`.
/// @param cfg To-be-filled config for the actor.
/// @param cfg To-be-filled config for the actor.
/// @param fun Function object for the actor's behavior; will be moved.
/// @param fun Function object for the actor's behavior; will be moved.
/// @param xs Arguments for `fun`.
/// @param xs Arguments for `fun`.
template
<
spawn_options
Os
,
class
C
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
,
class
C
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_class
<
C
>::
type
infer_handle_from_class_t
<
C
>
spawn_functor_impl
(
actor_config
&
cfg
,
F
&
fun
,
Ts
&&
...
xs
)
{
spawn_functor_impl
(
actor_config
&
cfg
,
F
&
fun
,
Ts
&&
...
xs
)
{
constexpr
bool
has_blocking_base
=
constexpr
bool
is_blocking
=
std
::
is_base_of
<
blocking_actor
,
C
>::
value
;
std
::
is_base_of
<
blocking_actor
,
C
>::
value
;
static_assert
(
is_blocking
||
!
has_blocking_api_flag
(
Os
),
static_assert
(
has_blocking_base
||
!
has_blocking_api_flag
(
Os
),
"blocking functor-based actors "
"blocking functor-based actors "
"need to be spawned using the blocking_api flag"
);
"need to be spawned using the blocking_api flag"
);
static_assert
(
!
has_blocking_base
||
has_blocking_api_flag
(
Os
),
static_assert
(
!
is_blocking
||
has_blocking_api_flag
(
Os
),
"non-blocking functor-based actors "
"non-blocking functor-based actors "
"cannot be spawned using the blocking_api flag"
);
"cannot be spawned using the blocking_api flag"
);
detail
::
init_fun_factory
<
C
,
F
>
fac
;
detail
::
init_fun_factory
<
C
,
F
>
fac
;
...
@@ -286,9 +291,9 @@ public:
...
@@ -286,9 +291,9 @@ public:
/// @param fun Function object for the actor's behavior; will be moved.
/// @param fun Function object for the actor's behavior; will be moved.
/// @param xs Arguments for `fun`.
/// @param xs Arguments for `fun`.
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
infer_handle_from_fun_t
<
F
>
spawn_functor
(
actor_config
&
cfg
,
F
&
fun
,
Ts
&&
...
xs
)
{
spawn_functor
(
actor_config
&
cfg
,
F
&
fun
,
Ts
&&
...
xs
)
{
using
impl
=
typename
infer_handle_from_fun
<
F
>::
impl
;
using
impl
=
infer_impl_from_fun_t
<
F
>
;
return
spawn_functor_impl
<
Os
,
impl
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_functor_impl
<
Os
,
impl
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
...
@@ -297,15 +302,16 @@ public:
...
@@ -297,15 +302,16 @@ public:
/// The behavior of `spawn` can be modified by setting `Os`, e.g.,
/// The behavior of `spawn` can be modified by setting `Os`, e.g.,
/// to opt-out of the cooperative scheduling.
/// to opt-out of the cooperative scheduling.
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
infer_handle_from_fun_t
<
F
>
spawn
(
F
fun
,
Ts
&&
...
xs
)
{
spawn
(
F
fun
,
Ts
&&
...
xs
)
{
check_invariants
<
typename
infer_handle_from_fun
<
F
>::
impl
>
();
check_invariants
<
infer_impl_from_fun_t
<
F
>
>
();
actor_config
cfg
;
actor_config
cfg
;
return
spawn_functor
<
Os
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_functor
<
Os
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
Iter
,
class
F
,
class
...
Ts
>
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
typename
infer_handle_from_class
<
T
>::
type
class
Iter
,
class
F
,
class
...
Ts
>
infer_handle_from_class_t
<
T
>
spawn_in_groups_impl
(
actor_config
&
cfg
,
Iter
first
,
Iter
second
,
Ts
&&
...
xs
)
{
spawn_in_groups_impl
(
actor_config
&
cfg
,
Iter
first
,
Iter
second
,
Ts
&&
...
xs
)
{
check_invariants
<
T
>
();
check_invariants
<
T
>
();
auto
irange
=
make_input_range
(
first
,
second
);
auto
irange
=
make_input_range
(
first
,
second
);
...
@@ -313,11 +319,12 @@ public:
...
@@ -313,11 +319,12 @@ public:
return
spawn_class
<
T
,
Os
>
(
cfg
,
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_class
<
T
,
Os
>
(
cfg
,
std
::
forward
<
Ts
>
(
xs
)...);
}
}
template
<
spawn_options
Os
=
no_spawn_options
,
class
Iter
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
typename
infer_handle_from_fun
<
F
>::
type
class
Iter
,
class
F
,
class
...
Ts
>
infer_handle_from_fun_t
<
F
>
spawn_in_groups_impl
(
actor_config
&
cfg
,
Iter
first
,
Iter
second
,
spawn_in_groups_impl
(
actor_config
&
cfg
,
Iter
first
,
Iter
second
,
F
&
fun
,
Ts
&&
...
xs
)
{
F
&
fun
,
Ts
&&
...
xs
)
{
check_invariants
<
typename
infer_handle_from_fun
<
F
>::
impl
>
();
check_invariants
<
infer_impl_from_fun_t
<
F
>
>
();
auto
irange
=
make_input_range
(
first
,
second
);
auto
irange
=
make_input_range
(
first
,
second
);
cfg
.
groups
=
&
irange
;
cfg
.
groups
=
&
irange
;
return
spawn_functor
<
Os
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_functor
<
Os
>
(
cfg
,
fun
,
std
::
forward
<
Ts
>
(
xs
)...);
...
@@ -325,7 +332,7 @@ public:
...
@@ -325,7 +332,7 @@ public:
/// Returns a new functor-based actor subscribed to all groups in `gs`.
/// Returns a new functor-based actor subscribed to all groups in `gs`.
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
infer_handle_from_fun_t
<
F
>
spawn_in_groups
(
std
::
initializer_list
<
group
>
gs
,
F
fun
,
Ts
&&
...
xs
)
{
spawn_in_groups
(
std
::
initializer_list
<
group
>
gs
,
F
fun
,
Ts
&&
...
xs
)
{
actor_config
cfg
;
actor_config
cfg
;
return
spawn_in_groups_impl
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
fun
,
return
spawn_in_groups_impl
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
fun
,
...
@@ -334,7 +341,7 @@ public:
...
@@ -334,7 +341,7 @@ public:
/// Returns a new functor-based actor subscribed to all groups in `gs`.
/// Returns a new functor-based actor subscribed to all groups in `gs`.
template
<
spawn_options
Os
=
no_spawn_options
,
class
Gs
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
class
Gs
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
infer_handle_from_fun_t
<
F
>
spawn_in_groups
(
const
Gs
&
gs
,
F
fun
,
Ts
&&
...
xs
)
{
spawn_in_groups
(
const
Gs
&
gs
,
F
fun
,
Ts
&&
...
xs
)
{
actor_config
cfg
;
actor_config
cfg
;
return
spawn_in_groups_impl
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
fun
,
return
spawn_in_groups_impl
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
fun
,
...
@@ -343,14 +350,14 @@ public:
...
@@ -343,14 +350,14 @@ public:
/// Returns a new functor-based actor subscribed to all groups in `gs`.
/// Returns a new functor-based actor subscribed to all groups in `gs`.
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
infer_handle_from_fun_t
<
F
>
spawn_in_group
(
const
group
&
grp
,
F
fun
,
Ts
&&
...
xs
)
{
spawn_in_group
(
const
group
&
grp
,
F
fun
,
Ts
&&
...
xs
)
{
return
spawn_in_groups
({
grp
},
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_in_groups
({
grp
},
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
xs
)...);
}
}
/// Returns a new class-based actor subscribed to all groups in `gs`.
/// Returns a new class-based actor subscribed to all groups in `gs`.
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
typename
infer_handle_from_class
<
T
>::
type
infer_handle_from_class_t
<
T
>
spawn_in_groups
(
std
::
initializer_list
<
group
>
gs
,
Ts
&&
...
xs
)
{
spawn_in_groups
(
std
::
initializer_list
<
group
>
gs
,
Ts
&&
...
xs
)
{
actor_config
cfg
;
actor_config
cfg
;
return
spawn_in_groups_impl
<
T
>
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
return
spawn_in_groups_impl
<
T
>
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
...
@@ -359,7 +366,7 @@ public:
...
@@ -359,7 +366,7 @@ public:
/// Returns a new class-based actor subscribed to all groups in `gs`.
/// Returns a new class-based actor subscribed to all groups in `gs`.
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
Gs
,
class
...
Ts
>
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
Gs
,
class
...
Ts
>
typename
infer_handle_from_class
<
T
>::
type
infer_handle_from_class_t
<
T
>
spawn_in_groups
(
const
Gs
&
gs
,
Ts
&&
...
xs
)
{
spawn_in_groups
(
const
Gs
&
gs
,
Ts
&&
...
xs
)
{
actor_config
cfg
;
actor_config
cfg
;
return
spawn_in_groups_impl
<
T
>
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
return
spawn_in_groups_impl
<
T
>
(
cfg
,
gs
.
begin
(),
gs
.
end
(),
...
@@ -368,7 +375,7 @@ public:
...
@@ -368,7 +375,7 @@ public:
/// Returns a new class-based actor subscribed to all groups in `gs`.
/// Returns a new class-based actor subscribed to all groups in `gs`.
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
typename
infer_handle_from_class
<
T
>::
type
infer_handle_from_class_t
<
T
>
spawn_in_group
(
const
group
&
grp
,
Ts
&&
...
xs
)
{
spawn_in_group
(
const
group
&
grp
,
Ts
&&
...
xs
)
{
return
spawn_in_groups
<
T
>
({
grp
},
std
::
forward
<
Ts
>
(
xs
)...);
return
spawn_in_groups
<
T
>
({
grp
},
std
::
forward
<
Ts
>
(
xs
)...);
}
}
...
@@ -400,7 +407,7 @@ private:
...
@@ -400,7 +407,7 @@ private:
}
}
template
<
class
C
,
spawn_options
Os
,
class
...
Ts
>
template
<
class
C
,
spawn_options
Os
,
class
...
Ts
>
typename
infer_handle_from_class
<
C
>::
type
infer_handle_from_class_t
<
C
>
spawn_impl
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
{
spawn_impl
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
{
static_assert
(
!
std
::
is_base_of
<
blocking_actor
,
C
>::
value
static_assert
(
!
std
::
is_base_of
<
blocking_actor
,
C
>::
value
||
has_blocking_api_flag
(
Os
),
||
has_blocking_api_flag
(
Os
),
...
...
libcaf_core/caf/composable_state_based_actor.hpp
0 → 100644
View file @
779d9171
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_COMPOSABLE_STATE_BASED_ACTOR_HPP
#define CAF_COMPOSABLE_STATE_BASED_ACTOR_HPP
#include "caf/stateful_actor.hpp"
namespace
caf
{
/// Implementation class for spawning composable states directly as actors.
template
<
class
State
>
class
composable_state_based_actor
:
public
stateful_actor
<
State
,
typename
State
::
actor_base
>
{
public:
static_assert
(
!
std
::
is_abstract
<
State
>::
value
,
"State is abstract, please make sure to override all "
"virtual operator() member functions"
);
using
super
=
stateful_actor
<
State
,
typename
State
::
actor_base
>
;
composable_state_based_actor
(
actor_config
&
cfg
)
:
super
(
cfg
)
{
// nop
}
using
behavior_type
=
typename
State
::
behavior_type
;
behavior_type
make_behavior
()
override
{
this
->
state
.
init_selfptr
(
this
);
behavior
tmp
;
this
->
state
.
init_behavior
(
tmp
);
return
behavior_type
{
typename
behavior_type
::
unsafe_init
{},
std
::
move
(
tmp
)};
}
};
}
// namespace caf
#endif // CAF_COMPOSABLE_STATE_BASED_ACTOR_HPP
libcaf_core/caf/infer_handle.hpp
View file @
779d9171
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
#include "caf/actor_addr.hpp"
#include "caf/actor_addr.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/abstract_composable_state.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -143,6 +143,7 @@ struct infer_handle_from_fun_impl<Result,
...
@@ -143,6 +143,7 @@ struct infer_handle_from_fun_impl<Result,
static
constexpr
spawn_mode
mode
=
spawn_mode
::
function_with_selfptr
;
static
constexpr
spawn_mode
mode
=
spawn_mode
::
function_with_selfptr
;
};
};
/// Deduces an actor handle type from a function or function object.
template
<
class
F
,
class
Trait
=
typename
detail
::
get_callable_trait
<
F
>
::
type
>
template
<
class
F
,
class
Trait
=
typename
detail
::
get_callable_trait
<
F
>
::
type
>
struct
infer_handle_from_fun
{
struct
infer_handle_from_fun
{
using
result_type
=
typename
Trait
::
result_type
;
using
result_type
=
typename
Trait
::
result_type
;
...
@@ -156,6 +157,14 @@ struct infer_handle_from_fun {
...
@@ -156,6 +157,14 @@ struct infer_handle_from_fun {
static
constexpr
spawn_mode
mode
=
delegate
::
mode
;
static
constexpr
spawn_mode
mode
=
delegate
::
mode
;
};
};
/// @relates infer_handle_from_fun
template
<
class
T
>
using
infer_handle_from_fun_t
=
typename
infer_handle_from_fun
<
T
>::
type
;
/// @relates infer_handle_from_fun
template
<
class
T
>
using
infer_impl_from_fun_t
=
typename
infer_handle_from_fun
<
T
>::
impl
;
template
<
class
T
>
template
<
class
T
>
struct
infer_handle_from_behavior
{
struct
infer_handle_from_behavior
{
using
type
=
actor
;
using
type
=
actor
;
...
@@ -166,7 +175,9 @@ struct infer_handle_from_behavior<typed_behavior<Sigs...>> {
...
@@ -166,7 +175,9 @@ struct infer_handle_from_behavior<typed_behavior<Sigs...>> {
using
type
=
typed_actor
<
Sigs
...
>
;
using
type
=
typed_actor
<
Sigs
...
>
;
};
};
template
<
class
T
>
/// Deduces `actor` for dynamically typed actors, otherwise `typed_actor<...>`
/// is deduced.
template
<
class
T
,
bool
=
std
::
is_base_of
<
abstract_actor
,
T
>
::
value
>
struct
infer_handle_from_class
{
struct
infer_handle_from_class
{
using
type
=
using
type
=
typename
infer_handle_from_behavior
<
typename
infer_handle_from_behavior
<
...
@@ -175,6 +186,31 @@ struct infer_handle_from_class {
...
@@ -175,6 +186,31 @@ struct infer_handle_from_class {
static
constexpr
spawn_mode
mode
=
spawn_mode
::
clazz
;
static
constexpr
spawn_mode
mode
=
spawn_mode
::
clazz
;
};
};
template
<
class
T
>
struct
infer_handle_from_class
<
T
,
false
>
{
// nop; this enables SFINAE for spawn to differentiate between
// spawns using actor classes or composable states
};
/// @relates infer_handle_from_class
template
<
class
T
>
using
infer_handle_from_class_t
=
typename
infer_handle_from_class
<
T
>::
type
;
template
<
class
T
,
bool
=
std
::
is_base_of
<
abstract_composable_state
,
T
>
::
value
>
struct
infer_handle_from_state
{
using
type
=
typename
T
::
handle_type
;
};
template
<
class
T
>
struct
infer_handle_from_state
<
T
,
false
>
{
// nop; this enables SFINAE for spawn to differentiate between
// spawns using actor classes or composable states
};
/// @relates infer_handle_from_state
template
<
class
T
>
using
infer_handle_from_state_t
=
typename
infer_handle_from_state
<
T
>::
type
;
}
// namespace caf
}
// namespace caf
#endif // CAF_INFER_HANDLE_HPP
#endif // CAF_INFER_HANDLE_HPP
...
...
libcaf_core/caf/typed_actor_pointer.hpp
View file @
779d9171
...
@@ -37,7 +37,7 @@ public:
...
@@ -37,7 +37,7 @@ public:
"cannot create a pointer view to an unrelated actor type"
);
"cannot create a pointer view to an unrelated actor type"
);
}
}
typed_actor_pointer
(
const
nullptr_t
&
)
:
view_
(
nullptr
)
{
typed_actor_pointer
(
const
std
::
nullptr_t
&
)
:
view_
(
nullptr
)
{
// nop
// nop
}
}
...
...
libcaf_core/test/composable_states.cpp
0 → 100644
View file @
779d9171
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE composable_states
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp"
using
namespace
std
;
using
namespace
caf
;
namespace
{
using
i3_actor
=
typed_actor
<
replies_to
<
int
,
int
,
int
>::
with
<
int
>>
;
using
d_actor
=
typed_actor
<
replies_to
<
double
>::
with
<
double
,
double
>>
;
using
foo_actor
=
i3_actor
::
extend_with
<
d_actor
>
;
class
foo_actor_state
:
public
composable_state
<
foo_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
+
y
+
z
;
}
result
<
double
,
double
>
operator
()(
double
x
)
override
{
return
{
x
,
x
};
}
};
class
i3_actor_state
:
public
composable_state
<
i3_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
+
y
+
z
;
}
};
class
d_actor_state
:
public
composable_state
<
d_actor
>
{
public:
result
<
double
,
double
>
operator
()(
double
x
)
override
{
return
{
x
,
x
};
}
};
class
i3_actor_state2
:
public
composable_state
<
i3_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
*
(
y
*
z
);
}
};
struct
foo_actor_state2
:
composed_state
<
i3_actor_state2
,
i3_actor_state
,
d_actor_state
>
{
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
-
y
-
z
;
}
};
using
add_atom
=
atom_constant
<
atom
(
"Add"
)
>
;
using
get_name_atom
=
atom_constant
<
atom
(
"GetName"
)
>
;
// "base" interface
using
named_actor
=
typed_actor
<
replies_to
<
get_name_atom
>::
with
<
std
::
string
>>
;
// a simple dictionary
using
dict
=
named_actor
::
extend
<
replies_to
<
get_atom
,
std
::
string
>::
with
<
std
::
string
>
,
replies_to
<
put_atom
,
std
::
string
,
std
::
string
>::
with
<
void
>>
;
// a simple calculator
using
calc
=
named_actor
::
extend
<
replies_to
<
add_atom
,
int
,
int
>::
with
<
int
>>
;
class
dict_state
:
public
composable_state
<
dict
>
{
public:
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"dictionary"
;
}
result
<
std
::
string
>
operator
()(
get_atom
,
const
std
::
string
&
key
)
override
{
auto
i
=
values_
.
find
(
key
);
if
(
i
==
values_
.
end
())
return
""
;
return
i
->
second
;
}
result
<
void
>
operator
()(
put_atom
,
const
std
::
string
&
key
,
const
std
::
string
&
value
)
override
{
values_
[
key
]
=
value
;
return
unit
;
}
protected:
std
::
unordered_map
<
std
::
string
,
std
::
string
>
values_
;
};
class
calc_state
:
public
composable_state
<
calc
>
{
public:
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"calculator"
;
}
result
<
int
>
operator
()(
add_atom
,
int
x
,
int
y
)
override
{
return
x
+
y
;
}
};
class
dict_calc_state
:
public
composed_state
<
dict_state
,
calc_state
>
{
public:
// composed_state<...> will mark this operator pure virtual, because
// of conflicting declarations in dict_state and calc_state
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"calculating dictionary"
;
}
};
}
// namespace <anonymous>
CAF_TEST
(
composable_states
)
{
actor_system
sys
;
//auto x1 = sys.spawn<stateful_impl<foo_actor_state>>();
auto
x1
=
sys
.
spawn
<
foo_actor_state
>
();
scoped_actor
self
{
sys
};
self
->
request
(
x1
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
7
);
}
);
self
->
send_exit
(
x1
,
exit_reason
::
kill
);
//auto x2 = sys.spawn<stateful_impl<composed_state<i3_actor_state, d_actor_state>>>();
auto
x2
=
sys
.
spawn
<
composed_state
<
i3_actor_state
,
d_actor_state
>>
();
self
->
request
(
x2
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
7
);
}
);
self
->
request
(
x2
,
1.0
).
receive
(
[](
double
y1
,
double
y2
)
{
CAF_CHECK
(
y1
==
1.0
);
CAF_CHECK
(
y1
==
y2
);
}
);
self
->
send_exit
(
x2
,
exit_reason
::
kill
);
//auto x3 = sys.spawn<stateful_impl<foo_actor_state2>>();
auto
x3
=
sys
.
spawn
<
foo_actor_state2
>
();
self
->
request
(
x3
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
-
5
);
}
);
self
->
send_exit
(
x3
,
exit_reason
::
kill
);
//auto x4 = sys.spawn<stateful_impl<dict_calc_state>>();
auto
x4
=
sys
.
spawn
<
dict_calc_state
>
();
self
->
request
(
x4
,
add_atom
::
value
,
10
,
20
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
30
);
}
);
self
->
send_exit
(
x4
,
exit_reason
::
kill
);
}
libcaf_core/test/typed_spawn.cpp
View file @
779d9171
...
@@ -72,224 +72,6 @@ static_assert(! std::is_convertible<dummy3, dummy5>::value,
...
@@ -72,224 +72,6 @@ static_assert(! std::is_convertible<dummy3, dummy5>::value,
static_assert
(
!
std
::
is_convertible
<
dummy4
,
dummy5
>::
value
,
static_assert
(
!
std
::
is_convertible
<
dummy4
,
dummy5
>::
value
,
"handle is assignable to broader definition"
);
"handle is assignable to broader definition"
);
// mockup
using
caf
::
detail
::
type_list
;
using
caf
::
detail
::
tl_apply
;
using
caf
::
detail
::
tl_union
;
using
caf
::
detail
::
tl_intersect
;
using
i3_actor
=
typed_actor
<
replies_to
<
int
,
int
,
int
>::
with
<
int
>>
;
using
d_actor
=
typed_actor
<
replies_to
<
double
>::
with
<
double
,
double
>>
;
using
foo_actor
=
i3_actor
::
extend_with
<
d_actor
>
;
class
foo_actor_state
:
public
composable_state
<
foo_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
+
y
+
z
;
}
result
<
double
,
double
>
operator
()(
double
x
)
override
{
return
{
x
,
x
};
}
};
class
i3_actor_state
:
public
composable_state
<
i3_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
+
y
+
z
;
}
};
class
d_actor_state
:
public
composable_state
<
d_actor
>
{
public:
result
<
double
,
double
>
operator
()(
double
x
)
override
{
return
{
x
,
x
};
}
};
struct
match_case_filter
{
template
<
class
...
Xs
,
class
...
Ts
>
void
operator
()(
std
::
tuple
<
Xs
...
>&
tup
,
Ts
&
...
xs
)
const
{
std
::
integral_constant
<
size_t
,
0
>
next_pos
;
detail
::
type_list
<>
next_token
;
(
*
this
)(
next_pos
,
tup
,
next_token
,
xs
...);
}
template
<
size_t
P
,
class
Tuple
,
class
...
Consumed
>
void
operator
()(
std
::
integral_constant
<
size_t
,
P
>
,
Tuple
&
,
detail
::
type_list
<
Consumed
...
>
)
const
{
// end of recursion
}
template
<
size_t
P
,
class
Tuple
,
class
...
Consumed
,
class
T
,
class
...
Ts
>
typename
std
::
enable_if
<
detail
::
tl_index_of
<
detail
::
type_list
<
Consumed
...
>
,
T
>::
value
==
-
1
>::
type
operator
()(
std
::
integral_constant
<
size_t
,
P
>
,
Tuple
&
tup
,
detail
::
type_list
<
Consumed
...
>
,
T
&
x
,
Ts
&
...
xs
)
const
{
get
<
P
>
(
tup
)
=
std
::
move
(
x
);
std
::
integral_constant
<
size_t
,
P
+
1
>
next_pos
;
detail
::
type_list
<
Consumed
...,
T
>
next_token
;
(
*
this
)(
next_pos
,
tup
,
next_token
,
xs
...);
}
template
<
size_t
P
,
class
Tuple
,
class
...
Consumed
,
class
T
,
class
...
Ts
>
typename
std
::
enable_if
<
detail
::
tl_index_of
<
detail
::
type_list
<
Consumed
...
>
,
T
>::
value
!=
-
1
>::
type
operator
()(
std
::
integral_constant
<
size_t
,
P
>
pos
,
Tuple
&
tup
,
detail
::
type_list
<
Consumed
...
>
token
,
T
&
,
Ts
&
...
xs
)
const
{
(
*
this
)(
pos
,
tup
,
token
,
xs
...);
}
};
using
detail
::
type_list
;
class
i3_actor_state2
:
public
composable_state
<
i3_actor
>
{
public:
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
*
(
y
*
z
);
}
};
struct
foo_actor_state2
:
composed_state
<
i3_actor_state2
,
i3_actor_state
,
d_actor_state
>
{
result
<
int
>
operator
()(
int
x
,
int
y
,
int
z
)
override
{
return
x
-
y
-
z
;
}
};
using
add_atom
=
atom_constant
<
atom
(
"Add"
)
>
;
using
get_name_atom
=
atom_constant
<
atom
(
"GetName"
)
>
;
// "base" interface
using
named_actor
=
typed_actor
<
replies_to
<
get_name_atom
>::
with
<
std
::
string
>>
;
// a simple dictionary
using
dict
=
named_actor
::
extend
<
replies_to
<
get_atom
,
std
::
string
>::
with
<
std
::
string
>
,
replies_to
<
put_atom
,
std
::
string
,
std
::
string
>::
with
<
void
>>
;
// a simple calculator
using
calc
=
named_actor
::
extend
<
replies_to
<
add_atom
,
int
,
int
>::
with
<
int
>>
;
class
dict_state
:
public
composable_state
<
dict
>
{
public:
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"dictionary"
;
}
result
<
std
::
string
>
operator
()(
get_atom
,
const
std
::
string
&
key
)
override
{
auto
i
=
values_
.
find
(
key
);
if
(
i
==
values_
.
end
())
return
""
;
return
i
->
second
;
}
result
<
void
>
operator
()(
put_atom
,
const
std
::
string
&
key
,
const
std
::
string
&
value
)
override
{
values_
[
key
]
=
value
;
return
unit
;
}
protected:
std
::
unordered_map
<
std
::
string
,
std
::
string
>
values_
;
};
class
calc_state
:
public
composable_state
<
calc
>
{
public:
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"calculator"
;
}
result
<
int
>
operator
()(
add_atom
,
int
x
,
int
y
)
override
{
return
x
+
y
;
}
};
class
dict_calc_state
:
public
composed_state
<
dict_state
,
calc_state
>
{
public:
// composed_state<...> will mark this operator pure virtual, because
// of conflicting declarations in dict_state and calc_state
result
<
std
::
string
>
operator
()(
get_name_atom
)
override
{
return
"calculating dictionary"
;
}
};
template
<
class
State
>
class
stateful_impl
:
public
stateful_actor
<
State
,
typename
State
::
actor_base
>
{
public:
static_assert
(
!
std
::
is_abstract
<
State
>::
value
,
"State is abstract, please make sure to override all "
"virtual operator() member functions"
);
using
super
=
stateful_actor
<
State
,
typename
State
::
actor_base
>
;
stateful_impl
(
actor_config
&
cfg
)
:
super
(
cfg
)
{
// nop
}
using
behavior_type
=
typename
State
::
behavior_type
;
behavior_type
make_behavior
()
override
{
this
->
state
.
init_selfptr
(
this
);
behavior
tmp
;
this
->
state
.
init_behavior
(
tmp
);
return
behavior_type
{
typename
behavior_type
::
unsafe_init
{},
std
::
move
(
tmp
)};
}
};
}
// namespace <anonymous>
CAF_TEST
(
foobarz
)
{
actor_system
sys
;
auto
x1
=
sys
.
spawn
<
stateful_impl
<
foo_actor_state
>>
();
scoped_actor
self
{
sys
};
self
->
request
(
x1
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
7
);
}
);
self
->
send_exit
(
x1
,
exit_reason
::
kill
);
auto
x2
=
sys
.
spawn
<
stateful_impl
<
composed_state
<
i3_actor_state
,
d_actor_state
>>>
();
self
->
request
(
x2
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
7
);
}
);
self
->
request
(
x2
,
1.0
).
receive
(
[](
double
y1
,
double
y2
)
{
CAF_CHECK
(
y1
==
1.0
);
CAF_CHECK
(
y1
==
y2
);
}
);
self
->
send_exit
(
x2
,
exit_reason
::
kill
);
auto
x3
=
sys
.
spawn
<
stateful_impl
<
foo_actor_state2
>>
();
self
->
request
(
x3
,
1
,
2
,
4
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
-
5
);
}
);
self
->
send_exit
(
x3
,
exit_reason
::
kill
);
auto
x4
=
sys
.
spawn
<
stateful_impl
<
dict_calc_state
>>
();
self
->
request
(
x4
,
add_atom
::
value
,
10
,
20
).
receive
(
[](
int
y
)
{
CAF_CHECK
(
y
==
30
);
}
);
self
->
send_exit
(
x4
,
exit_reason
::
kill
);
}
namespace
{
/******************************************************************************
/******************************************************************************
* simple request/response test *
* simple request/response test *
******************************************************************************/
******************************************************************************/
...
...
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