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
1c447b62
Commit
1c447b62
authored
Sep 30, 2014
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add atom_constant for atom-based typed interfaces
parent
8351e0f3
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
577 additions
and
115 deletions
+577
-115
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/atom.hpp
libcaf_core/caf/atom.hpp
+4
-0
libcaf_core/caf/detail/message_data.hpp
libcaf_core/caf/detail/message_data.hpp
+1
-33
libcaf_core/caf/detail/message_iterator.hpp
libcaf_core/caf/detail/message_iterator.hpp
+36
-31
libcaf_core/caf/detail/pseudo_tuple.hpp
libcaf_core/caf/detail/pseudo_tuple.hpp
+6
-4
libcaf_core/caf/detail/try_match.hpp
libcaf_core/caf/detail/try_match.hpp
+108
-0
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+10
-0
libcaf_core/caf/detail/typed_actor_util.hpp
libcaf_core/caf/detail/typed_actor_util.hpp
+17
-9
libcaf_core/caf/match_expr.hpp
libcaf_core/caf/match_expr.hpp
+12
-11
libcaf_core/caf/message.hpp
libcaf_core/caf/message.hpp
+20
-10
libcaf_core/caf/replies_to.hpp
libcaf_core/caf/replies_to.hpp
+4
-2
libcaf_core/caf/typed_behavior.hpp
libcaf_core/caf/typed_behavior.hpp
+1
-1
libcaf_core/cppa/tuple_cast.hpp
libcaf_core/cppa/tuple_cast.hpp
+5
-2
libcaf_core/src/message.cpp
libcaf_core/src/message.cpp
+11
-0
libcaf_core/src/message_data.cpp
libcaf_core/src/message_data.cpp
+5
-1
libcaf_core/src/message_iterator.cpp
libcaf_core/src/message_iterator.cpp
+42
-0
libcaf_core/src/try_match.cpp
libcaf_core/src/try_match.cpp
+116
-0
libcaf_core/src/uniform_type_info_map.cpp
libcaf_core/src/uniform_type_info_map.cpp
+1
-4
unit_testing/test_atom.cpp
unit_testing/test_atom.cpp
+37
-7
unit_testing/test_remote_spawn.cpp
unit_testing/test_remote_spawn.cpp
+0
-0
unit_testing/test_spawn.cpp
unit_testing/test_spawn.cpp
+139
-0
No files found.
libcaf_core/CMakeLists.txt
View file @
1c447b62
...
@@ -59,6 +59,7 @@ set (LIBCAF_CORE_SRCS
...
@@ -59,6 +59,7 @@ set (LIBCAF_CORE_SRCS
src/message_builder.cpp
src/message_builder.cpp
src/message_data.cpp
src/message_data.cpp
src/message_handler.cpp
src/message_handler.cpp
src/message_iterator.cpp
src/node_id.cpp
src/node_id.cpp
src/ref_counted.cpp
src/ref_counted.cpp
src/response_promise.cpp
src/response_promise.cpp
...
@@ -74,6 +75,7 @@ set (LIBCAF_CORE_SRCS
...
@@ -74,6 +75,7 @@ set (LIBCAF_CORE_SRCS
src/string_algorithms.cpp
src/string_algorithms.cpp
src/string_serialization.cpp
src/string_serialization.cpp
src/sync_request_bouncer.cpp
src/sync_request_bouncer.cpp
src/try_match.cpp
src/uniform_type_info.cpp
src/uniform_type_info.cpp
src/uniform_type_info_map.cpp
)
src/uniform_type_info_map.cpp
)
...
...
libcaf_core/caf/atom.hpp
View file @
1c447b62
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#define CAF_ATOM_HPP
#define CAF_ATOM_HPP
#include <string>
#include <string>
#include <type_traits>
#include "caf/detail/atom_val.hpp"
#include "caf/detail/atom_val.hpp"
...
@@ -46,6 +47,9 @@ constexpr atom_value atom(char const (&str)[Size]) {
...
@@ -46,6 +47,9 @@ constexpr atom_value atom(char const (&str)[Size]) {
return
static_cast
<
atom_value
>
(
detail
::
atom_val
(
str
,
0xF
));
return
static_cast
<
atom_value
>
(
detail
::
atom_val
(
str
,
0xF
));
}
}
template
<
atom_value
Value
>
using
atom_constant
=
std
::
integral_constant
<
atom_value
,
Value
>
;
}
// namespace caf
}
// namespace caf
#endif // CAF_ATOM_HPP
#endif // CAF_ATOM_HPP
libcaf_core/caf/detail/message_data.hpp
View file @
1c447b62
...
@@ -31,7 +31,6 @@
...
@@ -31,7 +31,6 @@
#include "caf/uniform_type_info.hpp"
#include "caf/uniform_type_info.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/message_iterator.hpp"
#include "caf/detail/message_iterator.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -74,7 +73,7 @@ class message_data : public ref_counted {
...
@@ -74,7 +73,7 @@ class message_data : public ref_counted {
bool
equals
(
const
message_data
&
other
)
const
;
bool
equals
(
const
message_data
&
other
)
const
;
using
const_iterator
=
message_iterator
<
message_data
>
;
using
const_iterator
=
message_iterator
;
inline
const_iterator
begin
()
const
{
inline
const_iterator
begin
()
const
{
return
{
this
};
return
{
this
};
...
@@ -133,37 +132,6 @@ class message_data : public ref_counted {
...
@@ -133,37 +132,6 @@ class message_data : public ref_counted {
};
};
struct
full_eq_type
{
constexpr
full_eq_type
()
{}
template
<
class
Tuple
>
inline
bool
operator
()(
const
message_iterator
<
Tuple
>&
lhs
,
const
message_iterator
<
Tuple
>&
rhs
)
const
{
return
lhs
.
type
()
==
rhs
.
type
()
&&
lhs
.
type
()
->
equals
(
lhs
.
value
(),
rhs
.
value
());
}
};
struct
types_only_eq_type
{
constexpr
types_only_eq_type
()
{}
template
<
class
Tuple
>
inline
bool
operator
()(
const
message_iterator
<
Tuple
>&
lhs
,
const
uniform_type_info
*
rhs
)
const
{
return
lhs
.
type
()
==
rhs
;
}
template
<
class
Tuple
>
inline
bool
operator
()(
const
uniform_type_info
*
lhs
,
const
message_iterator
<
Tuple
>&
rhs
)
const
{
return
lhs
==
rhs
.
type
();
}
};
namespace
{
constexpr
full_eq_type
full_eq
;
constexpr
types_only_eq_type
types_only_eq
;
}
// namespace <anonymous>
std
::
string
get_tuple_type_names
(
const
detail
::
message_data
&
);
std
::
string
get_tuple_type_names
(
const
detail
::
message_data
&
);
}
// namespace detail
}
// namespace detail
...
...
libcaf_core/caf/detail/message_iterator.hpp
View file @
1c447b62
...
@@ -17,53 +17,41 @@
...
@@ -17,53 +17,41 @@
* http://www.boost.org/LICENSE_1_0.txt. *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
******************************************************************************/
#ifndef CAF_DETAIL_
TUPL
E_ITERATOR_HPP
#ifndef CAF_DETAIL_
MESSAG
E_ITERATOR_HPP
#define CAF_DETAIL_
TUPL
E_ITERATOR_HPP
#define CAF_DETAIL_
MESSAG
E_ITERATOR_HPP
#include <cstddef>
#include <cstddef>
#include "caf/
config
.hpp"
#include "caf/
fwd
.hpp"
namespace
caf
{
namespace
caf
{
namespace
detail
{
namespace
detail
{
template
<
class
Tuple
>
class
message_data
;
class
message_iterator
{
size_t
m_pos
;
const
Tuple
*
m_tuple
;
class
message_iterator
{
public:
public:
using
pointer
=
message_data
*
;
using
const_pointer
=
const
message_data
*
;
inline
message_iterator
(
const
Tuple
*
tup
,
size_t
pos
=
0
)
message_iterator
(
const_pointer
data
,
size_t
pos
=
0
);
:
m_pos
(
pos
),
m_tuple
(
tup
)
{}
message_iterator
(
const
message_iterator
&
)
=
default
;
message_iterator
(
const
message_iterator
&
)
=
default
;
message_iterator
&
operator
=
(
const
message_iterator
&
)
=
default
;
message_iterator
&
operator
=
(
const
message_iterator
&
)
=
default
;
inline
bool
operator
==
(
const
message_iterator
&
other
)
const
{
CAF_REQUIRE
(
other
.
m_tuple
==
other
.
m_tuple
);
return
other
.
m_pos
==
m_pos
;
}
inline
bool
operator
!=
(
const
message_iterator
&
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
message_iterator
&
operator
++
()
{
inline
message_iterator
&
operator
++
()
{
++
m_pos
;
++
m_pos
;
return
*
this
;
return
*
this
;
}
}
inline
message_iterator
&
operator
--
()
{
inline
message_iterator
&
operator
--
()
{
CAF_REQUIRE
(
m_pos
>
0
);
--
m_pos
;
--
m_pos
;
return
*
this
;
return
*
this
;
}
}
inline
message_iterator
operator
+
(
size_t
offset
)
{
inline
message_iterator
operator
+
(
size_t
offset
)
{
return
{
m_
tuple
,
m_pos
+
offset
};
return
{
m_
data
,
m_pos
+
offset
};
}
}
inline
message_iterator
&
operator
+=
(
size_t
offset
)
{
inline
message_iterator
&
operator
+=
(
size_t
offset
)
{
...
@@ -72,29 +60,46 @@ class message_iterator {
...
@@ -72,29 +60,46 @@ class message_iterator {
}
}
inline
message_iterator
operator
-
(
size_t
offset
)
{
inline
message_iterator
operator
-
(
size_t
offset
)
{
CAF_REQUIRE
(
m_pos
>=
offset
);
return
{
m_data
,
m_pos
-
offset
};
return
{
m_tuple
,
m_pos
-
offset
};
}
}
inline
message_iterator
&
operator
-=
(
size_t
offset
)
{
inline
message_iterator
&
operator
-=
(
size_t
offset
)
{
CAF_REQUIRE
(
m_pos
>=
offset
);
m_pos
-=
offset
;
m_pos
-=
offset
;
return
*
this
;
return
*
this
;
}
}
inline
size_t
position
()
const
{
return
m_pos
;
}
inline
size_t
position
()
const
{
return
m_pos
;
inline
const
void
*
value
()
const
{
return
m_tuple
->
at
(
m_pos
);
}
}
inline
const
uniform_type_info
*
type
()
const
{
inline
const
_pointer
data
()
const
{
return
m_
tuple
->
type_at
(
m_pos
)
;
return
m_
data
;
}
}
inline
message_iterator
&
operator
*
()
{
return
*
this
;
}
const
void
*
value
()
const
;
const
uniform_type_info
*
type
()
const
;
inline
message_iterator
&
operator
*
()
{
return
*
this
;
}
private:
size_t
m_pos
;
const
message_data
*
m_data
;
};
};
inline
bool
operator
==
(
const
message_iterator
&
lhs
,
const
message_iterator
&
rhs
)
{
return
lhs
.
data
()
==
rhs
.
data
()
&&
lhs
.
position
()
==
rhs
.
position
();
}
inline
bool
operator
!=
(
const
message_iterator
&
lhs
,
const
message_iterator
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
#endif // CAF_DETAIL_
TUPL
E_ITERATOR_HPP
#endif // CAF_DETAIL_
MESSAG
E_ITERATOR_HPP
libcaf_core/caf/detail/pseudo_tuple.hpp
View file @
1c447b62
...
@@ -47,15 +47,17 @@ template <size_t N, class... Ts>
...
@@ -47,15 +47,17 @@ template <size_t N, class... Ts>
const
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
&
const
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
&
get
(
const
detail
::
pseudo_tuple
<
Ts
...
>&
tv
)
{
get
(
const
detail
::
pseudo_tuple
<
Ts
...
>&
tv
)
{
static_assert
(
N
<
sizeof
...(
Ts
),
"N >= tv.size()"
);
static_assert
(
N
<
sizeof
...(
Ts
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
const
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
*>
(
auto
vp
=
tv
.
at
(
N
);
tv
.
at
(
N
));
CAF_REQUIRE
(
vp
!=
nullptr
);
return
*
reinterpret_cast
<
const
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
*>
(
vp
);
}
}
template
<
size_t
N
,
class
...
Ts
>
template
<
size_t
N
,
class
...
Ts
>
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
&
get
(
detail
::
pseudo_tuple
<
Ts
...
>&
tv
)
{
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
&
get
(
detail
::
pseudo_tuple
<
Ts
...
>&
tv
)
{
static_assert
(
N
<
sizeof
...(
Ts
),
"N >= tv.size()"
);
static_assert
(
N
<
sizeof
...(
Ts
),
"N >= tv.size()"
);
return
*
reinterpret_cast
<
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
*>
(
auto
vp
=
tv
.
mutable_at
(
N
);
tv
.
mutable_at
(
N
));
CAF_REQUIRE
(
vp
!=
nullptr
);
return
*
reinterpret_cast
<
typename
detail
::
type_at
<
N
,
Ts
...
>::
type
*>
(
vp
);
}
}
}
// namespace detail
}
// namespace detail
...
...
libcaf_core/caf/detail/
matcher
.hpp
→
libcaf_core/caf/detail/
try_match
.hpp
View file @
1c447b62
...
@@ -20,7 +20,9 @@
...
@@ -20,7 +20,9 @@
#ifndef CAF_DETAIL_MATCHES_HPP
#ifndef CAF_DETAIL_MATCHES_HPP
#define CAF_DETAIL_MATCHES_HPP
#define CAF_DETAIL_MATCHES_HPP
#include <array>
#include <numeric>
#include <numeric>
#include <typeinfo>
#include "caf/message.hpp"
#include "caf/message.hpp"
#include "caf/wildcard_position.hpp"
#include "caf/wildcard_position.hpp"
...
@@ -31,80 +33,75 @@
...
@@ -31,80 +33,75 @@
namespace
caf
{
namespace
caf
{
namespace
detail
{
namespace
detail
{
template
<
class
Pattern
,
class
FilteredPattern
>
bool
match_element
(
const
std
::
type_info
*
type
,
const
message_iterator
&
iter
,
struct
matcher
;
void
**
storage
);
template
<
class
...
Ts
,
class
...
Us
>
template
<
class
T
>
struct
matcher
<
type_list
<
Ts
...
>
,
type_list
<
Us
...
>>
{
bool
match_integral_constant_element
(
const
std
::
type_info
*
type
,
template
<
class
TupleIter
,
class
PatternIter
,
class
Push
,
class
Commit
,
const
message_iterator
&
iter
,
class
Rollback
>
void
**
storage
)
{
bool
operator
()(
TupleIter
tbegin
,
TupleIter
tend
,
PatternIter
pbegin
,
auto
value
=
T
::
value
;
PatternIter
pend
,
Push
&
push
,
Commit
&
commit
,
auto
uti
=
iter
.
type
();
Rollback
&
rollback
)
const
{
if
(
!
uti
->
equal_to
(
*
type
)
||
!
uti
->
equals
(
iter
.
value
(),
&
value
))
{
while
(
!
(
pbegin
==
pend
&&
tbegin
==
tend
))
{
return
false
;
if
(
pbegin
==
pend
)
{
}
// reached end of pattern while some values remain unmatched
if
(
storage
)
{
return
false
;
// This assignment implicitly casts `T*` to `integral_constant<T, V>*`.
}
// This type violation could theoretically cause undefined behavior.
if
(
*
pbegin
==
nullptr
)
{
// nullptr == wildcard (anything)
// However, `T::value` does have an address that is guaranteed to be valid
// perform submatching
// throughout the runtime of the program and the integral constant
++
pbegin
;
// objects does not have any members. Hence, this is nonetheless safe.
// always true at the end of the pattern
auto
ptr
=
reinterpret_cast
<
const
void
*>
(
&
T
::
value
);
if
(
pbegin
==
pend
)
{
// Again, this const cast is always safe because we will never derefence
return
true
;
// this pointer since `integral_constant<T, V>` has no members.
}
*
storage
=
const_cast
<
void
*>
(
ptr
);
// safe current mapping as fallback
}
commit
();
return
true
;
// iterate over tuple values until we found a match
}
for
(;
tbegin
!=
tend
;
++
tbegin
)
{
if
((
*
this
)(
tbegin
,
tend
,
pbegin
,
pend
,
push
,
commit
,
rollback
))
{
struct
meta_element
{
return
true
;
const
std
::
type_info
*
type
;
}
bool
(
*
fun
)(
const
std
::
type_info
*
,
const
message_iterator
&
,
void
**
);
// restore mapping to fallback (delete invalid mappings)
};
rollback
();
}
template
<
class
T
>
return
false
;
// no submatch found
struct
meta_element_factory
{
}
static
meta_element
create
()
{
// compare types
return
{
&
typeid
(
T
),
match_element
};
if
(
tbegin
.
type
()
!=
*
pbegin
)
{
// type mismatch
return
false
;
}
// next iteration
push
(
tbegin
);
++
tbegin
;
++
pbegin
;
}
return
true
;
// pbegin == pend && tbegin == tend
}
}
};
bool
operator
()(
const
message
&
tup
,
pseudo_tuple
<
Us
...
>*
out
)
const
{
template
<
class
T
,
T
V
>
auto
&
tarr
=
static_types_array
<
Ts
...
>::
arr
;
struct
meta_element_factory
<
std
::
integral_constant
<
T
,
V
>>
{
if
(
sizeof
...(
Us
)
==
0
)
{
static
meta_element
create
()
{
// this pattern only has wildcards and thus always matches
return
{
&
typeid
(
T
),
return
true
;
match_integral_constant_element
<
std
::
integral_constant
<
T
,
V
>>
};
}
if
(
tup
.
size
()
<
sizeof
...(
Us
))
{
return
false
;
}
if
(
out
)
{
size_t
pos
=
0
;
size_t
fallback_pos
=
0
;
auto
fpush
=
[
&
](
const
typename
message
::
const_iterator
&
iter
)
{
(
*
out
)[
pos
++
]
=
const_cast
<
void
*>
(
iter
.
value
());
};
auto
fcommit
=
[
&
]
{
fallback_pos
=
pos
;
};
auto
frollback
=
[
&
]
{
pos
=
fallback_pos
;
};
return
(
*
this
)(
tup
.
begin
(),
tup
.
end
(),
tarr
.
begin
(),
tarr
.
end
(),
fpush
,
fcommit
,
frollback
);
}
auto
no_push
=
[](
const
typename
message
::
const_iterator
&
)
{
};
auto
nop
=
[]
{
};
return
(
*
this
)(
tup
.
begin
(),
tup
.
end
(),
tarr
.
begin
(),
tarr
.
end
(),
no_push
,
nop
,
nop
);
}
}
};
};
template
<
>
struct
meta_element_factory
<
anything
>
{
static
meta_element
create
()
{
return
{
nullptr
,
nullptr
};
}
};
template
<
class
TypeList
>
struct
meta_elements
;
template
<
class
...
Ts
>
struct
meta_elements
<
type_list
<
Ts
...
>>
{
std
::
array
<
meta_element
,
sizeof
...(
Ts
)
>
arr
;
meta_elements
()
:
arr
{{
meta_element_factory
<
Ts
>::
create
()...}}
{
// nop
}
};
bool
try_match
(
const
message
&
msg
,
const
meta_element
*
pattern_begin
,
size_t
pattern_size
,
void
**
out
=
nullptr
);
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
1c447b62
...
@@ -481,6 +481,16 @@ struct is_optional<optional<T>> : std::true_type {
...
@@ -481,6 +481,16 @@ struct is_optional<optional<T>> : std::true_type {
// no members
// no members
};
};
template
<
class
T
>
struct
is_integral_constant
:
std
::
false_type
{
// no members
};
template
<
class
T
,
T
V
>
struct
is_integral_constant
<
std
::
integral_constant
<
T
,
V
>>
:
std
::
true_type
{
// no members
};
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
...
...
libcaf_core/caf/detail/typed_actor_util.hpp
View file @
1c447b62
...
@@ -138,7 +138,9 @@ struct type_checker<type_pair<Opt1, Opt2>, F1, F2> {
...
@@ -138,7 +138,9 @@ struct type_checker<type_pair<Opt1, Opt2>, F1, F2> {
template
<
class
A
,
class
B
,
template
<
class
,
class
>
class
Predicate
>
template
<
class
A
,
class
B
,
template
<
class
,
class
>
class
Predicate
>
struct
static_asserter
{
struct
static_asserter
{
static_assert
(
Predicate
<
A
,
B
>::
value
,
"exact match needed"
);
static
void
verify_match
()
{
static_assert
(
Predicate
<
A
,
B
>::
value
,
"exact match needed"
);
}
};
};
template
<
class
T
>
template
<
class
T
>
...
@@ -163,15 +165,21 @@ struct deduce_lifted_output_type<type_list<typed_continue_helper<R>>> {
...
@@ -163,15 +165,21 @@ struct deduce_lifted_output_type<type_list<typed_continue_helper<R>>> {
template
<
class
Signatures
,
typename
InputTypes
>
template
<
class
Signatures
,
typename
InputTypes
>
struct
deduce_output_type
{
struct
deduce_output_type
{
static
constexpr
int
input_pos
=
tl_find_if
<
static_assert
(
tl_find
<
Signatures
,
InputTypes
,
input_is
<
InputTypes
>::
template
eval
atom_value
>
::
value
;
>::
value
==
-
1
,
static_assert
(
input_pos
>=
0
,
"typed actor does not support given input"
);
"atom(...) notation is not sufficient for static type "
"checking, please use atom_constant instead in this context"
);
static
constexpr
int
input_pos
=
tl_find_if
<
Signatures
,
input_is
<
InputTypes
>::
template
eval
>
::
value
;
static_assert
(
input_pos
!=
-
1
,
"typed actor does not support given input"
);
using
signature
=
typename
tl_at
<
Signatures
,
input_pos
>::
type
;
using
signature
=
typename
tl_at
<
Signatures
,
input_pos
>::
type
;
using
type
=
using
type
=
detail
::
type_pair
<
typename
signature
::
output_opt1_types
,
detail
::
type_pair
<
typename
signature
::
output_opt1_types
,
typename
signature
::
output_opt2_types
>
;
typename
signature
::
output_opt2_types
>
;
};
};
template
<
class
...
Ts
>
template
<
class
...
Ts
>
...
...
libcaf_core/caf/match_expr.hpp
View file @
1c447b62
...
@@ -34,7 +34,7 @@
...
@@ -34,7 +34,7 @@
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/left_or_right.hpp"
#include "caf/detail/left_or_right.hpp"
#include "caf/detail/
matcher
.hpp"
#include "caf/detail/
try_match
.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/lifted_fun.hpp"
#include "caf/detail/lifted_fun.hpp"
#include "caf/detail/pseudo_tuple.hpp"
#include "caf/detail/pseudo_tuple.hpp"
...
@@ -227,10 +227,9 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
...
@@ -227,10 +227,9 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
}
}
auto
&
f
=
get
<
N
>
(
fs
);
auto
&
f
=
get
<
N
>
(
fs
);
using
ft
=
typename
std
::
decay
<
decltype
(
f
)
>::
type
;
using
ft
=
typename
std
::
decay
<
decltype
(
f
)
>::
type
;
detail
::
matcher
<
typename
ft
::
pattern
,
typename
ft
::
filtered_pattern
>
match
;
meta_elements
<
typename
ft
::
pattern
>
ms
;
typename
ft
::
intermediate_tuple
targs
;
typename
ft
::
intermediate_tuple
targs
;
if
(
match
(
msg
,
&
targs
))
{
if
(
try_match
(
msg
,
ms
.
arr
.
data
(),
ms
.
arr
.
size
(),
targs
.
data
))
{
//if (policy::prepare_invoke(targs, type_token, is_dynamic, ptr, tup)) {
auto
is
=
detail
::
get_indices
(
targs
);
auto
is
=
detail
::
get_indices
(
targs
);
auto
res
=
detail
::
apply_args
(
f
,
is
,
deduce_const
(
msg
,
targs
));
auto
res
=
detail
::
apply_args
(
f
,
is
,
deduce_const
(
msg
,
targs
));
if
(
unroll_expr_result_valid
(
res
))
{
if
(
unroll_expr_result_valid
(
res
))
{
...
@@ -240,19 +239,21 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
...
@@ -240,19 +239,21 @@ Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>, Msg& msg) {
return
none
;
return
none
;
}
}
template
<
class
PPFPs
,
class
Tuple
>
template
<
class
PPFPs
>
uint64_t
calc_bitmask
(
PPFPs
&
,
minus1l
,
const
std
::
type_info
&
,
const
Tupl
e
&
)
{
uint64_t
calc_bitmask
(
PPFPs
&
,
minus1l
,
const
std
::
type_info
&
,
const
messag
e
&
)
{
return
0x00
;
return
0x00
;
}
}
template
<
class
Case
,
long
N
,
class
Tuple
>
template
<
class
Case
,
long
N
>
uint64_t
calc_bitmask
(
Case
&
fs
,
long_constant
<
N
>
,
uint64_t
calc_bitmask
(
Case
&
fs
,
long_constant
<
N
>
,
const
std
::
type_info
&
tinf
,
const
Tuple
&
tup
)
{
const
std
::
type_info
&
tinf
,
const
message
&
msg
)
{
auto
&
f
=
get
<
N
>
(
fs
);
auto
&
f
=
get
<
N
>
(
fs
);
using
ft
=
typename
std
::
decay
<
decltype
(
f
)
>::
type
;
using
ft
=
typename
std
::
decay
<
decltype
(
f
)
>::
type
;
detail
::
matcher
<
typename
ft
::
pattern
,
typename
ft
::
filtered_pattern
>
match
;
meta_elements
<
typename
ft
::
pattern
>
ms
;
uint64_t
result
=
match
(
tup
,
nullptr
)
?
(
0x01
<<
N
)
:
0x00
;
uint64_t
result
=
try_match
(
msg
,
ms
.
arr
.
data
(),
ms
.
arr
.
size
(),
nullptr
)
return
result
|
calc_bitmask
(
fs
,
long_constant
<
N
-
1l
>
(),
tinf
,
tup
);
?
(
0x01
<<
N
)
:
0x00
;
return
result
|
calc_bitmask
(
fs
,
long_constant
<
N
-
1l
>
(),
tinf
,
msg
);
}
}
template
<
bool
IsManipulator
,
typename
T0
,
typename
T1
>
template
<
bool
IsManipulator
,
typename
T0
,
typename
T1
>
...
...
libcaf_core/caf/message.hpp
View file @
1c447b62
...
@@ -181,16 +181,12 @@ class message {
...
@@ -181,16 +181,12 @@ class message {
/**
/**
* Returns an iterator to the beginning.
* Returns an iterator to the beginning.
*/
*/
inline
const_iterator
begin
()
const
{
const_iterator
begin
()
const
;
return
m_vals
->
begin
();
}
/**
/**
* Returns an iterator to the end.
* Returns an iterator to the end.
*/
*/
inline
const_iterator
end
()
const
{
const_iterator
end
()
const
;
return
m_vals
->
end
();
}
/**
/**
* Returns a copy-on-write pointer to the internal data.
* Returns a copy-on-write pointer to the internal data.
...
@@ -285,6 +281,16 @@ inline bool operator!=(const message& lhs, const message& rhs) {
...
@@ -285,6 +281,16 @@ inline bool operator!=(const message& lhs, const message& rhs) {
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
template
<
class
T
>
struct
lift_message_element
{
using
type
=
T
;
};
template
<
class
T
,
T
V
>
struct
lift_message_element
<
std
::
integral_constant
<
T
,
V
>>
{
using
type
=
T
;
};
/**
/**
* Creates a new `message` containing the elements `args...`.
* Creates a new `message` containing the elements `args...`.
* @relates message
* @relates message
...
@@ -296,10 +302,14 @@ typename std::enable_if<
...
@@ -296,10 +302,14 @@ typename std::enable_if<
message
message
>::
type
>::
type
make_message
(
T
&&
arg
,
Ts
&&
...
args
)
{
make_message
(
T
&&
arg
,
Ts
&&
...
args
)
{
using
namespace
detail
;
using
storage
using
data
=
tuple_vals
<
typename
strip_and_convert
<
T
>::
type
,
=
detail
::
tuple_vals
<
typename
lift_message_element
<
typename
strip_and_convert
<
Ts
>::
type
...
>
;
typename
detail
::
strip_and_convert
<
T
>::
type
auto
ptr
=
new
data
(
std
::
forward
<
T
>
(
arg
),
std
::
forward
<
Ts
>
(
args
)...);
>::
type
,
typename
lift_message_element
<
typename
detail
::
strip_and_convert
<
Ts
>::
type
>::
type
...
>
;
auto
ptr
=
new
storage
(
std
::
forward
<
T
>
(
arg
),
std
::
forward
<
Ts
>
(
args
)...);
return
message
{
detail
::
message_data
::
ptr
{
ptr
}};
return
message
{
detail
::
message_data
::
ptr
{
ptr
}};
}
}
...
...
libcaf_core/caf/replies_to.hpp
View file @
1c447b62
...
@@ -74,10 +74,12 @@ struct typed_mpi<detail::type_list<Is...>,
...
@@ -74,10 +74,12 @@ struct typed_mpi<detail::type_list<Is...>,
static
std
::
string
static_type_name
()
{
static
std
::
string
static_type_name
()
{
std
::
string
input
[]
=
{
type_name_access
<
Is
>::
get
()...};
std
::
string
input
[]
=
{
type_name_access
<
Is
>::
get
()...};
std
::
string
output_opt1
[]
=
{
type_name_access
<
Ls
>::
get
()...};
std
::
string
output_opt1
[]
=
{
type_name_access
<
Ls
>::
get
()...};
std
::
string
output_opt2
[]
=
{
type_name_access
<
Rs
>::
get
()...};
// Rs... is allowed to be empty, hence we need to add a dummy element
// to make sure this array is not of size 0 (to prevent compiler errors)
std
::
string
output_opt2
[]
=
{
std
::
string
(),
type_name_access
<
Rs
>::
get
()...};
return
replies_to_type_name
(
sizeof
...(
Is
),
input
,
return
replies_to_type_name
(
sizeof
...(
Is
),
input
,
sizeof
...(
Ls
),
output_opt1
,
sizeof
...(
Ls
),
output_opt1
,
sizeof
...(
Rs
),
output_opt2
);
sizeof
...(
Rs
),
output_opt2
+
1
);
}
}
};
};
...
...
libcaf_core/caf/typed_behavior.hpp
View file @
1c447b62
...
@@ -233,7 +233,7 @@ class typed_behavior {
...
@@ -233,7 +233,7 @@ class typed_behavior {
detail
::
type_list
<
typename
detail
::
deduce_mpi
<
Cs
>::
type
...
>
,
detail
::
type_list
<
typename
detail
::
deduce_mpi
<
Cs
>::
type
...
>
,
detail
::
is_hidden_msg_handler
detail
::
is_hidden_msg_handler
>::
type
;
>::
type
;
detail
::
static_asserter
<
signatures
,
mpi
,
detail
::
ctm
>
asserter
;
detail
::
static_asserter
<
signatures
,
mpi
,
detail
::
ctm
>
::
verify_match
()
;
// final (type-erasure) step
// final (type-erasure) step
m_bhvr
=
std
::
move
(
expr
);
m_bhvr
=
std
::
move
(
expr
);
}
}
...
...
libcaf_core/cppa/tuple_cast.hpp
View file @
1c447b62
...
@@ -133,8 +133,11 @@ auto moving_tuple_cast(message& tup)
...
@@ -133,8 +133,11 @@ auto moving_tuple_cast(message& tup)
}
}
}
}
// same for nil, leading, and trailing
// same for nil, leading, and trailing
if
(
std
::
equal
(
sub
.
begin
(),
sub
.
end
(),
auto
eq
=
[](
const
detail
::
message_iterator
&
lhs
,
arr_pos
,
detail
::
types_only_eq
))
{
const
uniform_type_info
*
rhs
)
{
return
lhs
.
type
()
==
rhs
;
};
if
(
std
::
equal
(
sub
.
begin
(),
sub
.
end
(),
arr_pos
,
eq
))
{
return
result_type
::
from
(
sub
);
return
result_type
::
from
(
sub
);
}
}
return
none
;
return
none
;
...
...
libcaf_core/src/message.cpp
View file @
1c447b62
...
@@ -103,4 +103,15 @@ bool message::dynamically_typed() const {
...
@@ -103,4 +103,15 @@ bool message::dynamically_typed() const {
return
m_vals
?
m_vals
->
dynamically_typed
()
:
false
;
return
m_vals
?
m_vals
->
dynamically_typed
()
:
false
;
}
}
message
::
const_iterator
message
::
begin
()
const
{
return
m_vals
?
m_vals
->
begin
()
:
const_iterator
{
nullptr
,
0
};
}
/**
* Returns an iterator to the end.
*/
message
::
const_iterator
message
::
end
()
const
{
return
m_vals
?
m_vals
->
end
()
:
const_iterator
{
nullptr
,
0
};
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/message_data.cpp
View file @
1c447b62
...
@@ -27,9 +27,13 @@ message_data::message_data(bool is_dynamic) : m_is_dynamic(is_dynamic) {
...
@@ -27,9 +27,13 @@ message_data::message_data(bool is_dynamic) : m_is_dynamic(is_dynamic) {
}
}
bool
message_data
::
equals
(
const
message_data
&
other
)
const
{
bool
message_data
::
equals
(
const
message_data
&
other
)
const
{
auto
full_eq
=
[](
const
message_iterator
&
lhs
,
const
message_iterator
&
rhs
)
{
return
lhs
.
type
()
==
rhs
.
type
()
&&
lhs
.
type
()
->
equals
(
lhs
.
value
(),
rhs
.
value
());
};
return
this
==
&
other
return
this
==
&
other
||
(
size
()
==
other
.
size
()
||
(
size
()
==
other
.
size
()
&&
std
::
equal
(
begin
(),
end
(),
other
.
begin
(),
detail
::
full_eq
));
&&
std
::
equal
(
begin
(),
end
(),
other
.
begin
(),
full_eq
));
}
}
message_data
::
message_data
(
const
message_data
&
other
)
message_data
::
message_data
(
const
message_data
&
other
)
...
...
libcaf_core/src/message_iterator.cpp
0 → 100644
View file @
1c447b62
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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/detail/message_iterator.hpp"
#include "caf/detail/message_data.hpp"
namespace
caf
{
namespace
detail
{
message_iterator
::
message_iterator
(
const_pointer
data
,
size_t
pos
)
:
m_pos
(
pos
),
m_data
(
data
)
{
// nop
}
const
void
*
message_iterator
::
value
()
const
{
return
m_data
->
at
(
m_pos
);
}
const
uniform_type_info
*
message_iterator
::
type
()
const
{
return
m_data
->
type_at
(
m_pos
);
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/try_match.cpp
0 → 100644
View file @
1c447b62
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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/detail/try_match.hpp"
namespace
caf
{
namespace
detail
{
using
pattern_iterator
=
const
meta_element
*
;
bool
is_wildcard
(
const
meta_element
&
me
)
{
return
me
.
type
==
nullptr
;
}
bool
match_element
(
const
std
::
type_info
*
type
,
const
message_iterator
&
iter
,
void
**
storage
)
{
if
(
!
iter
.
type
()
->
equal_to
(
*
type
))
{
return
false
;
}
if
(
storage
)
{
*
storage
=
const_cast
<
void
*>
(
iter
.
value
());
}
return
true
;
}
class
set_commit_rollback
{
public:
using
pointer
=
void
**
;
set_commit_rollback
(
const
set_commit_rollback
&
)
=
delete
;
set_commit_rollback
&
operator
=
(
const
set_commit_rollback
&
)
=
delete
;
set_commit_rollback
(
pointer
ptr
)
:
m_data
(
ptr
),
m_pos
(
0
),
m_fallback_pos
(
0
)
{
// nop
}
inline
void
inc
()
{
++
m_pos
;
}
inline
pointer
current
()
{
return
m_data
?
&
m_data
[
m_pos
]
:
nullptr
;
}
inline
void
commit
()
{
m_fallback_pos
=
m_pos
;
}
inline
void
rollback
()
{
m_pos
=
m_fallback_pos
;
}
private:
pointer
m_data
;
size_t
m_pos
;
size_t
m_fallback_pos
;
};
bool
try_match
(
message_iterator
mbegin
,
message_iterator
mend
,
pattern_iterator
pbegin
,
pattern_iterator
pend
,
set_commit_rollback
&
storage
)
{
while
(
mbegin
!=
mend
)
{
if
(
pbegin
==
pend
)
{
return
false
;
}
if
(
is_wildcard
(
*
pbegin
))
{
// perform submatching
++
pbegin
;
// always true at the end of the pattern
if
(
pbegin
==
pend
)
{
return
true
;
}
// safe current mapping as fallback
storage
.
commit
();
// iterate over remaining values until we found a match
for
(;
mbegin
!=
mend
;
++
mbegin
)
{
if
(
try_match
(
mbegin
,
mend
,
pbegin
,
pend
,
storage
))
{
return
true
;
}
// restore mapping to fallback (delete invalid mappings)
storage
.
rollback
();
}
return
false
;
// no submatch found
}
// inspect current element
if
(
!
pbegin
->
fun
(
pbegin
->
type
,
mbegin
,
storage
.
current
()))
{
// type mismatch
return
false
;
}
// next iteration
storage
.
inc
();
++
mbegin
;
++
pbegin
;
}
// we found a match if we've inspected each element and consumed
// the whole pattern (or the remainder consists of wildcards only)
return
std
::
all_of
(
pbegin
,
pend
,
is_wildcard
);
}
bool
try_match
(
const
message
&
msg
,
pattern_iterator
pb
,
size_t
ps
,
void
**
out
)
{
set_commit_rollback
scr
{
out
};
auto
res
=
try_match
(
msg
.
begin
(),
msg
.
end
(),
pb
,
pb
+
ps
,
scr
);
return
res
;
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/uniform_type_info_map.cpp
View file @
1c447b62
...
@@ -650,10 +650,7 @@ class default_meta_message : public uniform_type_info {
...
@@ -650,10 +650,7 @@ class default_meta_message : public uniform_type_info {
return
false
;
return
false
;
}
}
bool
equals
(
const
void
*
instance1
,
const
void
*
instance2
)
const
override
{
bool
equals
(
const
void
*
instance1
,
const
void
*
instance2
)
const
override
{
auto
&
lhs
=
*
cast
(
instance1
);
return
*
cast
(
instance1
)
==
*
cast
(
instance2
);
auto
&
rhs
=
*
cast
(
instance2
);
full_eq_type
cmp
;
return
std
::
equal
(
lhs
.
begin
(),
lhs
.
end
(),
rhs
.
begin
(),
cmp
);
}
}
private:
private:
...
...
unit_testing/test_atom.cpp
View file @
1c447b62
...
@@ -21,6 +21,29 @@ using namespace caf;
...
@@ -21,6 +21,29 @@ using namespace caf;
namespace
{
namespace
{
constexpr
auto
s_foo
=
atom
(
"FooBar"
);
constexpr
auto
s_foo
=
atom
(
"FooBar"
);
using
abc_atom
=
atom_constant
<
atom
(
"abc"
)
>
;
}
using
testee
=
typed_actor
<
replies_to
<
abc_atom
>::
with
<
int
>>
;
testee
::
behavior_type
testee_impl
(
testee
::
pointer
self
)
{
return
{
[
=
](
abc_atom
)
{
self
->
quit
();
return
42
;
}
};
}
void
test_typed_atom_interface
()
{
scoped_actor
self
;
auto
tst
=
spawn_typed
(
testee_impl
);
self
->
sync_send
(
tst
,
abc_atom
()).
await
(
[](
int
i
)
{
CAF_CHECK_EQUAL
(
i
,
42
);
},
CAF_UNEXPECTED_MSG_CB_REF
(
self
)
);
}
}
template
<
atom_value
AtomValue
,
class
...
Types
>
template
<
atom_value
AtomValue
,
class
...
Types
>
...
@@ -36,7 +59,6 @@ struct send_to_self {
...
@@ -36,7 +59,6 @@ struct send_to_self {
m_self
->
send
(
m_self
,
std
::
forward
<
Ts
>
(
args
)...);
m_self
->
send
(
m_self
,
std
::
forward
<
Ts
>
(
args
)...);
}
}
blocking_actor
*
m_self
;
blocking_actor
*
m_self
;
};
};
int
main
()
{
int
main
()
{
...
@@ -53,22 +75,19 @@ int main() {
...
@@ -53,22 +75,19 @@ int main() {
send_to_self
f
{
self
.
get
()};
send_to_self
f
{
self
.
get
()};
f
(
atom
(
"foo"
),
static_cast
<
uint32_t
>
(
42
));
f
(
atom
(
"foo"
),
static_cast
<
uint32_t
>
(
42
));
f
(
atom
(
":Attach"
),
atom
(
":Baz"
),
"cstring"
);
f
(
atom
(
":Attach"
),
atom
(
":Baz"
),
"cstring"
);
// m(atom("b"), atom("a"), atom("c"), 23.f, 1.f, 1.f);
f
(
1.
f
);
f
(
1.
f
);
f
(
atom
(
"a"
),
atom
(
"b"
),
atom
(
"c"
),
23.
f
);
f
(
atom
(
"a"
),
atom
(
"b"
),
atom
(
"c"
),
23.
f
);
bool
matched_pattern
[
3
]
=
{
false
,
false
,
false
};
bool
matched_pattern
[
3
]
=
{
false
,
false
,
false
};
int
i
=
0
;
int
i
=
0
;
CAF_CHECKPOINT
();
for
(
i
=
0
;
i
<
3
;
++
i
)
{
for
(
i
=
0
;
i
<
3
;
++
i
)
{
self
->
receive
(
self
->
receive
(
//}
// self->receive_for(i, 3) (
on
(
atom
(
"foo"
),
arg_match
)
>>
[
&
](
uint32_t
value
)
{
on
(
atom
(
"foo"
),
arg_match
)
>>
[
&
](
uint32_t
value
)
{
CAF_CHECKPOINT
();
CAF_CHECKPOINT
();
matched_pattern
[
0
]
=
true
;
matched_pattern
[
0
]
=
true
;
CAF_CHECK_EQUAL
(
value
,
42
);
CAF_CHECK_EQUAL
(
value
,
42
);
},
},
on
(
atom
(
":Attach"
),
atom
(
":Baz"
),
arg_match
)
>>
on
(
atom
(
":Attach"
),
atom
(
":Baz"
),
arg_match
)
>>
[
&
](
const
string
&
str
)
{
[
&
](
const
string
&
str
)
{
CAF_CHECKPOINT
();
CAF_CHECKPOINT
();
matched_pattern
[
1
]
=
true
;
matched_pattern
[
1
]
=
true
;
CAF_CHECK_EQUAL
(
str
,
"cstring"
);
CAF_CHECK_EQUAL
(
str
,
"cstring"
);
...
@@ -83,6 +102,17 @@ int main() {
...
@@ -83,6 +102,17 @@ int main() {
self
->
receive
(
self
->
receive
(
// "erase" message { atom("b"), atom("a"), atom("c"), 23.f }
// "erase" message { atom("b"), atom("a"), atom("c"), 23.f }
others
()
>>
CAF_CHECKPOINT_CB
(),
others
()
>>
CAF_CHECKPOINT_CB
(),
after
(
std
::
chrono
::
seconds
(
0
))
>>
CAF_UNEXPECTED_TOUT_CB
());
after
(
std
::
chrono
::
seconds
(
0
))
>>
CAF_UNEXPECTED_TOUT_CB
()
);
atom_value
x
=
atom
(
"abc"
);
atom_value
y
=
abc_atom
();
CAF_CHECK_EQUAL
(
x
,
y
);
auto
msg
=
make_message
(
abc_atom
());
self
->
send
(
self
,
msg
);
self
->
receive
(
on
(
atom
(
"abc"
))
>>
CAF_CHECKPOINT_CB
(),
others
()
>>
CAF_UNEXPECTED_MSG_CB_REF
(
self
)
);
test_typed_atom_interface
();
return
CAF_TEST_RESULT
();
return
CAF_TEST_RESULT
();
}
}
unit_testing/test_remote_spawn.cpp
0 → 100644
View file @
1c447b62
unit_testing/test_spawn.cpp
View file @
1c447b62
...
@@ -630,6 +630,141 @@ void counting_actor(event_based_actor* self) {
...
@@ -630,6 +630,141 @@ void counting_actor(event_based_actor* self) {
CAF_CHECK_EQUAL
(
self
->
mailbox
().
count
(),
200
);
CAF_CHECK_EQUAL
(
self
->
mailbox
().
count
(),
200
);
}
}
// tests attach_functor() inside of an actor's constructor
void
test_constructor_attach
()
{
class
testee
:
public
event_based_actor
{
public:
testee
(
actor
buddy
)
:
m_buddy
(
buddy
)
{
attach_functor
([
=
](
uint32_t
reason
)
{
send
(
m_buddy
,
atom
(
"done"
),
reason
);
});
}
behavior
make_behavior
()
{
return
{
on
(
atom
(
"die"
))
>>
[
=
]
{
quit
(
exit_reason
::
user_shutdown
);
}
};
}
private:
actor
m_buddy
;
};
class
spawner
:
public
event_based_actor
{
public:
spawner
()
:
m_downs
(
0
)
{
}
behavior
make_behavior
()
{
m_testee
=
spawn
<
testee
,
monitored
>
(
this
);
return
{
[
=
](
const
down_msg
&
msg
)
{
CAF_CHECK_EQUAL
(
msg
.
reason
,
exit_reason
::
user_shutdown
);
if
(
++
m_downs
==
2
)
{
quit
(
msg
.
reason
);
}
},
on
(
atom
(
"done"
),
arg_match
)
>>
[
=
](
uint32_t
reason
)
{
CAF_CHECK_EQUAL
(
reason
,
exit_reason
::
user_shutdown
);
if
(
++
m_downs
==
2
)
{
quit
(
reason
);
}
},
others
()
>>
[
=
]
{
forward_to
(
m_testee
);
}
};
}
private:
int
m_downs
;
actor
m_testee
;
};
anon_send
(
spawn
<
spawner
>
(),
atom
(
"die"
));
}
class
exception_testee
:
public
event_based_actor
{
public:
exception_testee
()
{
set_exception_handler
([](
const
std
::
exception_ptr
&
eptr
)
->
optional
<
uint32_t
>
{
return
exit_reason
::
user_defined
+
2
;
});
}
behavior
make_behavior
()
override
{
return
{
others
()
>>
[]
{
throw
std
::
runtime_error
(
"whatever"
);
}
};
}
};
void
test_custom_exception_handler
()
{
auto
handler
=
[](
const
std
::
exception_ptr
&
eptr
)
->
optional
<
uint32_t
>
{
try
{
std
::
rethrow_exception
(
eptr
);
}
catch
(
std
::
runtime_error
&
)
{
return
exit_reason
::
user_defined
;
}
catch
(...)
{
// "fall through"
}
return
exit_reason
::
user_defined
+
1
;
};
scoped_actor
self
;
auto
testee1
=
self
->
spawn
<
monitored
>
([
=
](
event_based_actor
*
eb_self
)
{
eb_self
->
set_exception_handler
(
handler
);
throw
std
::
runtime_error
(
"ping"
);
});
auto
testee2
=
self
->
spawn
<
monitored
>
([
=
](
event_based_actor
*
eb_self
)
{
eb_self
->
set_exception_handler
(
handler
);
throw
std
::
logic_error
(
"pong"
);
});
auto
testee3
=
self
->
spawn
<
exception_testee
,
monitored
>
();
self
->
send
(
testee3
,
"foo"
);
// receive all down messages
auto
i
=
0
;
self
->
receive_for
(
i
,
3
)(
[
&
](
const
down_msg
&
dm
)
{
if
(
dm
.
source
==
testee1
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
user_defined
);
}
else
if
(
dm
.
source
==
testee2
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
user_defined
+
1
);
}
else
if
(
dm
.
source
==
testee3
)
{
CAF_CHECK_EQUAL
(
dm
.
reason
,
exit_reason
::
user_defined
+
2
);
}
else
{
CAF_CHECK
(
false
);
// report error
}
}
);
}
using
abc_atom
=
atom_constant
<
atom
(
"abc"
)
>
;
using
typed_testee
=
typed_actor
<
replies_to
<
abc_atom
>::
with
<
std
::
string
>>
;
typed_testee
::
behavior_type
testee
(
typed_testee
::
pointer
self
)
{
return
{
[](
abc_atom
)
{
CAF_PRINT
(
"received abc_atom"
);
return
"abc"
;
}
};
}
void
test_typed_testee
()
{
CAF_PRINT
(
"test_typed_testee"
);
scoped_actor
self
;
auto
x
=
spawn_typed
(
testee
);
self
->
sync_send
(
x
,
abc_atom
()).
await
(
[](
const
std
::
string
&
str
)
{
CAF_CHECK_EQUAL
(
str
,
"abc"
);
}
);
self
->
send_exit
(
x
,
exit_reason
::
user_shutdown
);
}
}
// namespace <anonymous>
}
// namespace <anonymous>
int
main
()
{
int
main
()
{
...
@@ -641,6 +776,10 @@ int main() {
...
@@ -641,6 +776,10 @@ int main() {
CAF_CHECKPOINT
();
CAF_CHECKPOINT
();
await_all_actors_done
();
await_all_actors_done
();
CAF_CHECKPOINT
();
CAF_CHECKPOINT
();
test_typed_testee
();
CAF_CHECKPOINT
();
await_all_actors_done
();
CAF_CHECKPOINT
();
// test setting exit reasons for scoped actors
// test setting exit reasons for scoped actors
{
// lifetime scope of self
{
// lifetime scope of self
scoped_actor
self
;
scoped_actor
self
;
...
...
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