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
fdce05dd
Unverified
Commit
fdce05dd
authored
Mar 19, 2020
by
Dominik Charousset
Committed by
GitHub
Mar 19, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1073
Enable states with non-default constructor
parents
99212ecc
d02e4173
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
250 additions
and
148 deletions
+250
-148
CHANGELOG.md
CHANGELOG.md
+9
-0
examples/message_passing/fan_out_request.cpp
examples/message_passing/fan_out_request.cpp
+0
-1
libcaf_core/caf/composable_behavior_based_actor.hpp
libcaf_core/caf/composable_behavior_based_actor.hpp
+3
-1
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+1
-0
libcaf_core/caf/infer_handle.hpp
libcaf_core/caf/infer_handle.hpp
+0
-1
libcaf_core/caf/stateful_actor.hpp
libcaf_core/caf/stateful_actor.hpp
+61
-62
libcaf_core/caf/type_nr.hpp
libcaf_core/caf/type_nr.hpp
+6
-0
libcaf_core/caf/typed_actor_pointer.hpp
libcaf_core/caf/typed_actor_pointer.hpp
+40
-17
libcaf_core/caf/typed_actor_view.hpp
libcaf_core/caf/typed_actor_view.hpp
+20
-18
libcaf_core/src/actor_registry.cpp
libcaf_core/src/actor_registry.cpp
+0
-1
libcaf_core/src/actor_system.cpp
libcaf_core/src/actor_system.cpp
+1
-0
libcaf_core/test/stateful_actor.cpp
libcaf_core/test/stateful_actor.cpp
+104
-43
libcaf_test/caf/test/dsl.hpp
libcaf_test/caf/test/dsl.hpp
+5
-4
No files found.
CHANGELOG.md
View file @
fdce05dd
...
...
@@ -68,6 +68,15 @@ is based on [Keep a Changelog](https://keepachangelog.com).
-
Our manual now uses
`reStructuredText`
instead of
`LaTeX`
. We hope this makes
extending the manual easier and lowers the barrier to entry for new
contributors.
-
A
`stateful_actor`
now forwards excess arguments to the
`State`
rather than to
the
`Base`
. This enables states with non-default constructors. When using
`stateful_actor<State>`
as pointer type in function-based actors, nothing
changes (i.e. the new API is backwards compatible for this case). However,
calling
`spawn<stateful_actor<State>>(xs...)`
now initializes the
`State`
with
the argument pack
`xs...`
(plus optionally a
`self`
pointer as first
argument). Furthermore, the state class can now provide a
`make_behavior`
member function to initialize the actor (this has no effect for function-based
actors).
### Removed
...
...
examples/message_passing/fan_out_request.cpp
View file @
fdce05dd
...
...
@@ -16,7 +16,6 @@
#include "caf/function_view.hpp"
#include "caf/policy/select_all.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/typed_actor.hpp"
#include "caf/typed_event_based_actor.hpp"
...
...
libcaf_core/caf/composable_behavior_based_actor.hpp
View file @
fdce05dd
...
...
@@ -33,7 +33,9 @@ public:
using
super
=
stateful_actor
<
State
,
Base
>
;
composable_behavior_based_actor
(
actor_config
&
cfg
)
:
super
(
cfg
)
{
template
<
class
...
Ts
>
explicit
composable_behavior_based_actor
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
:
super
(
cfg
,
std
::
forward
<
Ts
>
(
xs
)...)
{
// nop
}
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
fdce05dd
...
...
@@ -437,6 +437,7 @@ public:
CAF_HAS_MEMBER_TRAIT
(
size
);
CAF_HAS_MEMBER_TRAIT
(
data
);
CAF_HAS_MEMBER_TRAIT
(
make_behavior
);
/// Checks whether F is convertible to either `std::function<void (T&)>`
/// or `std::function<void (const T&)>`.
...
...
libcaf_core/caf/infer_handle.hpp
View file @
fdce05dd
...
...
@@ -21,7 +21,6 @@
#include "caf/abstract_composable_behavior.hpp"
#include "caf/actor.hpp"
#include "caf/actor_addr.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/typed_behavior.hpp"
namespace
caf
{
...
...
libcaf_core/caf/stateful_actor.hpp
View file @
fdce05dd
...
...
@@ -24,88 +24,87 @@
#include "caf/fwd.hpp"
#include "caf/sec.hpp"
#include "caf/logger.hpp"
#include "caf/detail/type_traits.hpp"
namespace
caf
{
namespace
caf
::
detail
{
/// An event-based actor with managed state. The state is constructed
/// before `make_behavior` will get called and destroyed after the
/// actor called `quit`. This state management brakes cycles and
/// allows actors to automatically release resources as soon
/// as possible.
template
<
class
State
,
class
Base
/* = event_based_actor (see fwd.hpp) */
>
class
stateful_actor
:
public
Base
{
/// Conditional base type for `stateful_actor` that overrides `make_behavior` if
/// `State::make_behavior()` exists.
template
<
class
State
,
class
Base
>
class
stateful_actor_base
:
public
Base
{
public:
template
<
class
...
Ts
>
explicit
stateful_actor
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
:
Base
(
cfg
,
std
::
forward
<
Ts
>
(
xs
)...),
state
(
state_
)
{
cr_state
(
this
);
}
~
stateful_actor
()
override
{
// nop
}
/// Destroys the state of this actor (no further overriding allowed).
void
on_exit
()
final
{
CAF_LOG_TRACE
(
""
);
state_
.
~
State
();
}
const
char
*
name
()
const
final
{
return
get_name
(
state_
);
}
/// A reference to the actor's state.
State
&
state
;
using
Base
::
Base
;
/// @cond PRIVATE
typename
Base
::
behavior_type
make_behavior
()
override
;
};
void
initialize
()
override
{
Base
::
initialize
();
}
/// Evaluates to either `stateful_actor_base<State, Base> `or `Base`, depending
/// on whether `State::make_behavior()` exists.
template
<
class
State
,
class
Base
>
using
stateful_actor_base_t
=
std
::
conditional_t
<
has_make_behavior_member
<
State
>::
value
,
stateful_actor_base
<
State
,
Base
>
,
Base
>
;
/// @endcond
}
// namespace caf::detail
private:
template
<
class
T
>
typename
std
::
enable_if
<
std
::
is_constructible
<
State
,
T
>::
value
>::
type
cr_state
(
T
arg
)
{
new
(
&
state_
)
State
(
arg
);
}
namespace
caf
{
template
<
class
T
>
typename
std
::
enable_if
<!
std
::
is_constructible
<
State
,
T
>::
value
>::
type
cr_state
(
T
)
{
new
(
&
state_
)
State
();
}
/// An event-based actor with managed state. The state is constructed with the
/// actor, but destroyed when the actor calls `quit`. This state management
/// brakes cycles and allows actors to automatically release resources as soon
/// as possible.
template
<
class
State
,
class
Base
/* = event_based_actor (see fwd.hpp) */
>
class
stateful_actor
:
public
detail
::
stateful_actor_base_t
<
State
,
Base
>
{
public:
using
super
=
detail
::
stateful_actor_base_t
<
State
,
Base
>
;
static
const
char
*
unbox_str
(
const
char
*
str
)
{
return
str
;
template
<
class
...
Ts
>
explicit
stateful_actor
(
actor_config
&
cfg
,
Ts
&&
...
xs
)
:
super
(
cfg
)
{
if
constexpr
(
std
::
is_constructible
<
State
,
Ts
&&
...
>::
value
)
new
(
&
state
)
State
(
std
::
forward
<
Ts
>
(
xs
)...);
else
new
(
&
state
)
State
(
this
,
std
::
forward
<
Ts
>
(
xs
)...);
}
template
<
class
U
>
static
const
char
*
unbox_str
(
const
U
&
str
)
{
return
str
.
c_str
();
~
stateful_actor
()
override
{
// nop
}
template
<
class
U
>
typename
std
::
enable_if
<
detail
::
has_name
<
U
>::
value
,
const
char
*>::
type
get_name
(
const
U
&
st
)
const
{
return
unbox_str
(
st
.
name
);
/// @copydoc local_actor::on_exit
/// @note when overriding this member function, make sure to call
/// `super::on_exit()` in order to clean up the state.
void
on_exit
()
override
{
state
.
~
State
();
}
template
<
class
U
>
typename
std
::
enable_if
<!
detail
::
has_name
<
U
>::
value
,
const
char
*>::
type
get_name
(
const
U
&
)
const
{
return
Base
::
name
();
const
char
*
name
()
const
override
{
if
constexpr
(
detail
::
has_name
<
State
>::
value
)
{
if
constexpr
(
std
::
is_convertible
<
decltype
(
state
.
name
),
const
char
*>::
value
)
return
state
.
name
;
else
return
state
.
name
.
c_str
();
}
else
{
return
Base
::
name
();
}
}
union
{
State
state_
;
/// The actor's state. This member lives inside a union since its lifetime
/// ends when the actor terminates while the actual actor object lives until
/// its reference count drops to zero.
State
state
;
};
};
}
// namespace caf
namespace
caf
::
detail
{
template
<
class
State
,
class
Base
>
typename
Base
::
behavior_type
stateful_actor_base
<
State
,
Base
>::
make_behavior
()
{
auto
dptr
=
static_cast
<
stateful_actor
<
State
,
Base
>*>
(
this
);
return
dptr
->
state
.
make_behavior
();
}
}
// namespace caf::detail
libcaf_core/caf/type_nr.hpp
View file @
fdce05dd
...
...
@@ -36,6 +36,12 @@
#define CAF_MSG_TYPE_ADD_ATOM(name) \
struct name {}; \
[[maybe_unused]] constexpr bool operator==(name, name) { \
return true; \
} \
[[maybe_unused]] constexpr bool operator!=(name, name) { \
return false; \
} \
template <class Inspector> \
auto inspect(Inspector& f, name&) { \
return f(meta::type_name("caf::" #name)); \
...
...
libcaf_core/caf/typed_actor_pointer.hpp
View file @
fdce05dd
...
...
@@ -19,6 +19,7 @@
#pragma once
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/typed_actor_view.hpp"
namespace
caf
{
...
...
@@ -33,22 +34,54 @@ public:
// nop
}
template
<
class
Supertype
>
explicit
typed_actor_pointer
(
Supertype
*
selfptr
)
:
view_
(
selfptr
)
{
using
namespace
caf
::
detail
;
static_assert
(
tl_subset_of
<
type_list
<
Sigs
...
>
,
typename
Supertype
::
signatures
>::
value
,
"cannot create a pointer view to an unrelated actor type"
);
template
<
class
Supertype
,
class
=
detail
::
enable_if_t
<
//
detail
::
tl_subset_of
<
detail
::
type_list
<
Sigs
...>,
typename
Supertype
::
signatures
>::
value
>>
typed_actor_pointer
(
Supertype
*
selfptr
)
:
view_
(
selfptr
)
{
// nop
}
explicit
typed_actor_pointer
(
std
::
nullptr_t
)
:
view_
(
nullptr
)
{
template
<
class
...
OtherSigs
,
class
=
detail
::
enable_if_t
<
//
detail
::
tl_subset_of
<
detail
::
type_list
<
Sigs
...>,
detail
::
type_list
<
OtherSigs
...
>>::
value
>>
typed_actor_pointer
(
typed_actor_pointer
<
OtherSigs
...
>
other
)
:
view_
(
other
.
internal_ptr
())
{
// nop
}
typed_actor_pointer
(
const
typed_actor_pointer
&
)
=
default
;
explicit
typed_actor_pointer
(
std
::
nullptr_t
)
:
view_
(
nullptr
)
{
// nop
}
typed_actor_pointer
&
operator
=
(
const
typed_actor_pointer
&
)
=
default
;
template
<
class
Supertype
>
typed_actor_pointer
&
operator
=
(
Supertype
*
ptr
)
{
using
namespace
detail
;
static_assert
(
tl_subset_of
<
type_list
<
Sigs
...
>
,
typename
Supertype
::
signatures
>::
value
,
"cannot assign pointer of unrelated actor type"
);
view_
.
reset
(
ptr
);
return
*
this
;
}
template
<
class
...
OtherSigs
,
class
=
detail
::
enable_if_t
<
//
detail
::
tl_subset_of
<
detail
::
type_list
<
Sigs
...>,
detail
::
type_list
<
OtherSigs
...
>>::
value
>>
typed_actor_pointer
&
operator
=
(
typed_actor_pointer
<
OtherSigs
...
>
other
)
{
using
namespace
detail
;
static_assert
(
tl_subset_of
<
type_list
<
Sigs
...
>
,
type_list
<
OtherSigs
...
>>::
value
,
"cannot assign pointer of unrelated actor type"
);
view_
.
reset
(
other
.
internal_ptr
());
return
*
this
;
}
typed_actor_view
<
Sigs
...
>*
operator
->
()
{
return
&
view_
;
}
...
...
@@ -75,16 +108,6 @@ public:
return
view_
.
internal_ptr
();
}
template
<
class
Supertype
>
typed_actor_pointer
&
operator
=
(
Supertype
*
ptr
)
{
using
namespace
caf
::
detail
;
static_assert
(
tl_subset_of
<
type_list
<
Sigs
...
>
,
typename
Supertype
::
signatures
>::
value
,
"cannot assign pointer of unrelated actor type"
);
view_
=
ptr
;
return
*
this
;
}
private:
typed_actor_view
<
Sigs
...
>
view_
;
};
...
...
libcaf_core/caf/typed_actor_view.hpp
View file @
fdce05dd
...
...
@@ -31,30 +31,24 @@ namespace caf {
/// Decorates a pointer to a @ref scheduled_actor with a statically typed actor
/// interface.
template
<
class
...
Sigs
>
class
typed_actor_view
:
public
extend
<
typed_actor_view_base
,
typed_actor_view
<
Sigs
...
>>::
template
with
<
mixin
::
sender
,
mixin
::
requester
>
{
class
typed_actor_view
:
public
extend
<
typed_actor_view_base
,
typed_actor_view
<
Sigs
...
>>::
template
with
<
mixin
::
sender
,
mixin
::
requester
>
{
public:
/// Stores the template parameter pack.
using
signatures
=
detail
::
type_list
<
Sigs
...
>
;
using
pointer
=
scheduled_actor
*
;
typed_actor_view
(
scheduled_actor
*
ptr
)
:
self_
(
ptr
)
{
explicit
typed_actor_view
(
scheduled_actor
*
ptr
)
:
self_
(
ptr
)
{
// nop
}
typed_actor_view
&
operator
=
(
scheduled_actor
*
ptr
)
{
self_
=
ptr
;
return
*
this
;
}
// -- spawn functions --------------------------------------------------------
/// @copydoc local_actor::spawn
template
<
class
T
,
spawn_options
Os
=
no_spawn_options
,
class
...
Ts
>
typename
infer_handle_from_class
<
T
>::
type
spawn
(
Ts
&&
...
xs
)
{
typename
infer_handle_from_class
<
T
>::
type
spawn
(
Ts
&&
...
xs
)
{
return
self_
->
spawn
<
T
,
Os
>
(
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
@@ -66,8 +60,7 @@ public:
/// @copydoc local_actor::spawn
template
<
spawn_options
Os
=
no_spawn_options
,
class
F
,
class
...
Ts
>
typename
infer_handle_from_fun
<
F
>::
type
spawn
(
F
fun
,
Ts
&&
...
xs
)
{
typename
infer_handle_from_fun
<
F
>::
type
spawn
(
F
fun
,
Ts
&&
...
xs
)
{
return
self_
->
spawn
<
Os
>
(
std
::
move
(
fun
),
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
@@ -208,10 +201,8 @@ public:
}
template
<
class
...
Ts
,
class
R
=
typename
detail
::
make_response_promise_helper
<
typename
std
::
decay
<
Ts
>
::
type
...
>::
type
>
class
R
=
typename
detail
::
make_response_promise_helper
<
typename
std
::
decay
<
Ts
>
::
type
...
>::
type
>
R
response
(
Ts
&&
...
xs
)
{
return
self_
->
response
(
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
@@ -230,6 +221,11 @@ public:
std
::
move
(
bhvr
));
}
template
<
class
Handle
,
class
...
Ts
>
auto
delegate
(
const
Handle
&
dest
,
Ts
&&
...
xs
)
{
return
self_
->
delegate
(
dest
,
std
::
forward
<
Ts
>
(
xs
)...);
}
/// Returns a pointer to the sender of the current message.
/// @pre `current_mailbox_element() != nullptr`
strong_actor_ptr
&
current_sender
()
{
...
...
@@ -244,7 +240,8 @@ public:
/// @private
actor_control_block
*
ctrl
()
const
noexcept
{
CAF_ASSERT
(
self_
!=
nullptr
);
return
actor_control_block
::
from
(
self_
);;
return
actor_control_block
::
from
(
self_
);
;
}
/// @private
...
...
@@ -252,6 +249,11 @@ public:
return
self_
;
}
/// @private
void
reset
(
scheduled_actor
*
ptr
)
{
self_
=
ptr
;
}
operator
scheduled_actor
*
()
const
noexcept
{
return
self_
;
}
...
...
libcaf_core/src/actor_registry.cpp
View file @
fdce05dd
...
...
@@ -31,7 +31,6 @@
#include "caf/exit_reason.hpp"
#include "caf/actor_system.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/uniform_type_info_map.hpp"
...
...
libcaf_core/src/actor_system.cpp
View file @
fdce05dd
...
...
@@ -32,6 +32,7 @@
#include "caf/scheduler/coordinator.hpp"
#include "caf/scheduler/test_coordinator.hpp"
#include "caf/send.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/to_string.hpp"
namespace
caf
{
...
...
libcaf_core/test/stateful_actor.cpp
View file @
fdce05dd
...
...
@@ -16,18 +16,18 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE stateful_actor
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/test/dsl.hpp"
#
define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); }
#
include "caf/event_based_actor.hpp"
using
namespace
std
;
using
namespace
caf
;
using
namespace
std
::
string_literals
;
namespace
{
using
typed_adder_actor
...
...
@@ -35,7 +35,6 @@ using typed_adder_actor
struct
counter
{
int
value
=
0
;
local_actor
*
self_
;
};
behavior
adder
(
stateful_actor
<
counter
>*
self
)
{
...
...
@@ -77,36 +76,32 @@ public:
}
};
struct
fixture
{
actor_system_config
cfg
;
actor_system
system
;
fixture
()
:
system
(
cfg
)
{
struct
fixture
:
test_coordinator_fixture
<>
{
fixture
()
{
// nop
}
template
<
class
ActorUnderTest
>
void
test_adder
(
ActorUnderTest
aut
)
{
scoped_actor
self
{
system
};
self
->
send
(
aut
,
add_atom_v
,
7
);
self
->
send
(
aut
,
add_atom_v
,
4
);
self
->
send
(
aut
,
add_atom_v
,
9
);
self
->
request
(
aut
,
infinite
,
get_atom_v
)
.
receive
([](
int
x
)
{
CAF_CHECK_EQUAL
(
x
,
20
);
},
ERROR_HANDLER
);
inject
((
add_atom
,
int
),
from
(
self
).
to
(
aut
).
with
(
add_atom_v
,
7
));
inject
((
add_atom
,
int
),
from
(
self
).
to
(
aut
).
with
(
add_atom_v
,
4
));
inject
((
add_atom
,
int
),
from
(
self
).
to
(
aut
).
with
(
add_atom_v
,
9
));
inject
((
get_atom
),
from
(
self
).
to
(
aut
).
with
(
get_atom_v
));
expect
((
int
),
from
(
aut
).
to
(
self
).
with
(
20
));
}
template
<
class
State
>
void
test_name
(
const
char
*
expected
)
{
auto
aut
=
system
.
spawn
([](
stateful_actor
<
State
>*
self
)
->
behavior
{
return
[
=
](
get_atom
)
{
self
->
quit
();
return
self
->
name
();
auto
aut
=
sys
.
spawn
([](
stateful_actor
<
State
>*
self
)
->
behavior
{
return
{
[
=
](
get_atom
)
{
self
->
quit
();
return
self
->
name
();
},
};
});
scoped_actor
self
{
system
};
self
->
request
(
aut
,
infinite
,
get_atom_v
)
.
receive
([
&
](
const
string
&
str
)
{
CAF_CHECK_EQUAL
(
str
,
expected
);
},
ERROR_HANDLER
);
inject
((
get_atom
),
from
(
self
).
to
(
aut
).
with
(
get_atom_v
));
expect
((
std
::
string
),
from
(
aut
).
to
(
self
).
with
(
expected
));
}
};
...
...
@@ -114,42 +109,108 @@ struct fixture {
CAF_TEST_FIXTURE_SCOPE
(
dynamic_stateful_actor_tests
,
fixture
)
CAF_TEST
(
dynamic_stateful_actor
)
{
CAF_REQUIRE
(
monitored
+
monitored
==
monitored
);
test_adder
(
system
.
spawn
(
adder
));
}
CAF_TEST
(
typed_stateful_actor
)
{
test_adder
(
system
.
spawn
(
typed_adder
));
CAF_TEST
(
stateful
actors
can
be
dynamically
typed
)
{
test_adder
(
sys
.
spawn
(
adder
));
test_adder
(
sys
.
spawn
<
typed_adder_class
>
());
}
CAF_TEST
(
dynamic_stateful_actor_class
)
{
test_adder
(
system
.
spawn
<
adder_class
>
());
CAF_TEST
(
stateful
actors
can
be
statically
typed
)
{
test_adder
(
sys
.
spawn
(
typed_adder
));
test_adder
(
sys
.
spawn
<
adder_class
>
());
}
CAF_TEST
(
typed_stateful_actor_class
)
{
test_adder
(
system
.
spawn
<
typed_adder_class
>
());
}
CAF_TEST
(
no_name
)
{
CAF_TEST
(
stateful
actors
without
explicit
name
use
the
name
of
the
parent
)
{
struct
state
{
// empty
};
test_name
<
state
>
(
"scheduled_actor"
);
}
CAF_TEST
(
char_
name
)
{
CAF_TEST
(
states
with
C
string
names
override
the
default
name
)
{
struct
state
{
const
char
*
name
=
"testee"
;
};
test_name
<
state
>
(
"testee"
);
}
CAF_TEST
(
st
ring_
name
)
{
CAF_TEST
(
st
ates
with
STL
string
names
override
the
default
name
)
{
struct
state
{
string
name
=
"testee2"
;
st
d
::
st
ring
name
=
"testee2"
;
};
test_name
<
state
>
(
"testee2"
);
}
CAF_TEST
(
states
can
accept
constructor
arguments
and
provide
a
behavior
)
{
struct
state_type
{
int
x
;
int
y
;
state_type
(
int
x
,
int
y
)
:
x
(
x
),
y
(
y
)
{
// nop
}
behavior
make_behavior
()
{
return
{
[
=
](
int
x
,
int
y
)
{
this
->
x
=
x
;
this
->
y
=
y
;
},
};
}
};
using
actor_type
=
stateful_actor
<
state_type
>
;
auto
testee
=
sys
.
spawn
<
actor_type
>
(
10
,
20
);
auto
&
state
=
deref
<
actor_type
>
(
testee
).
state
;
CAF_CHECK_EQUAL
(
state
.
x
,
10
);
CAF_CHECK_EQUAL
(
state
.
y
,
20
);
inject
((
int
,
int
),
to
(
testee
).
with
(
1
,
2
));
CAF_CHECK_EQUAL
(
state
.
x
,
1
);
CAF_CHECK_EQUAL
(
state
.
y
,
2
);
}
CAF_TEST
(
states
optionally
take
the
self
pointer
as
first
argument
)
{
struct
state_type
{
event_based_actor
*
self
;
int
x
;
const
char
*
name
=
"testee"
;
state_type
(
event_based_actor
*
self
,
int
x
)
:
self
(
self
),
x
(
x
)
{
// nop
}
behavior
make_behavior
()
{
return
{
[
=
](
get_atom
)
{
return
self
->
name
();
},
};
}
};
using
actor_type
=
stateful_actor
<
state_type
>
;
auto
testee
=
sys
.
spawn
<
actor_type
>
(
10
);
auto
&
state
=
deref
<
actor_type
>
(
testee
).
state
;
CAF_CHECK
(
state
.
self
==
&
deref
<
actor_type
>
(
testee
));
CAF_CHECK_EQUAL
(
state
.
x
,
10
);
inject
((
get_atom
),
from
(
self
).
to
(
testee
).
with
(
get_atom_v
));
expect
((
std
::
string
),
from
(
testee
).
to
(
self
).
with
(
"testee"
s
));
}
CAF_TEST
(
typed
actors
can
use
typed_actor_pointer
as
self
pointer
)
{
struct
state_type
{
using
self_pointer
=
typed_adder_actor
::
pointer_view
;
self_pointer
self
;
const
char
*
name
=
"testee"
;
int
value
;
state_type
(
self_pointer
self
,
int
x
)
:
self
(
self
),
value
(
x
)
{
// nop
}
auto
make_behavior
()
{
return
make_typed_behavior
([
=
](
add_atom
,
int
x
)
{
value
+=
x
;
},
[
=
](
get_atom
)
{
return
value
;
});
}
};
using
actor_type
=
typed_adder_actor
::
stateful_base
<
state_type
>
;
auto
testee
=
sys
.
spawn
<
actor_type
>
(
10
);
auto
&
state
=
deref
<
actor_type
>
(
testee
).
state
;
CAF_CHECK
(
state
.
self
==
&
deref
<
actor_type
>
(
testee
));
CAF_CHECK_EQUAL
(
state
.
value
,
10
);
inject
((
add_atom
,
int
),
from
(
self
).
to
(
testee
).
with
(
add_atom_v
,
1
));
inject
((
get_atom
),
from
(
self
).
to
(
testee
).
with
(
get_atom_v
));
expect
((
int
),
from
(
testee
).
to
(
self
).
with
(
11
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_test/caf/test/dsl.hpp
View file @
fdce05dd
...
...
@@ -458,12 +458,13 @@ public:
}
void
with
(
Ts
...
xs
)
{
if
(
src_
==
nullptr
)
CAF_FAIL
(
"missing .from() in inject() statement"
);
if
(
dest_
==
nullptr
)
CAF_FAIL
(
"missing .to() in inject() statement"
);
caf
::
send_as
(
caf
::
actor_cast
<
caf
::
actor
>
(
src_
),
caf
::
actor_cast
<
caf
::
actor
>
(
dest_
),
xs
...);
if
(
src_
==
nullptr
)
caf
::
anon_send
(
caf
::
actor_cast
<
caf
::
actor
>
(
dest_
),
xs
...);
else
caf
::
send_as
(
caf
::
actor_cast
<
caf
::
actor
>
(
src_
),
caf
::
actor_cast
<
caf
::
actor
>
(
dest_
),
xs
...);
CAF_REQUIRE
(
sched_
.
prioritize
(
dest_
));
auto
dest_ptr
=
&
sched_
.
next_job
<
caf
::
abstract_actor
>
();
auto
ptr
=
dest_ptr
->
peek_at_next_mailbox_element
();
...
...
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