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
e828088f
Commit
e828088f
authored
Jun 07, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use type_erased_tuple for matching
parent
4a9a47e1
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
230 additions
and
190 deletions
+230
-190
libcaf_core/caf/behavior.hpp
libcaf_core/caf/behavior.hpp
+10
-4
libcaf_core/caf/detail/behavior_impl.hpp
libcaf_core/caf/detail/behavior_impl.hpp
+7
-6
libcaf_core/caf/detail/try_match.hpp
libcaf_core/caf/detail/try_match.hpp
+5
-7
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+10
-0
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+1
-0
libcaf_core/caf/match_case.hpp
libcaf_core/caf/match_case.hpp
+29
-57
libcaf_core/caf/message.hpp
libcaf_core/caf/message.hpp
+6
-1
libcaf_core/caf/message_builder.hpp
libcaf_core/caf/message_builder.hpp
+10
-0
libcaf_core/caf/message_handler.hpp
libcaf_core/caf/message_handler.hpp
+6
-2
libcaf_core/caf/type_erased_tuple.hpp
libcaf_core/caf/type_erased_tuple.hpp
+1
-1
libcaf_core/caf/type_erased_value.hpp
libcaf_core/caf/type_erased_value.hpp
+15
-14
libcaf_core/src/behavior_impl.cpp
libcaf_core/src/behavior_impl.cpp
+35
-8
libcaf_core/src/local_actor.cpp
libcaf_core/src/local_actor.cpp
+1
-1
libcaf_core/src/message.cpp
libcaf_core/src/message.cpp
+7
-0
libcaf_core/src/try_match.cpp
libcaf_core/src/try_match.cpp
+12
-25
libcaf_core/test/composable_behavior.cpp
libcaf_core/test/composable_behavior.cpp
+2
-2
libcaf_core/test/match.cpp
libcaf_core/test/match.cpp
+72
-61
libcaf_core/test/message_lifetime.cpp
libcaf_core/test/message_lifetime.cpp
+1
-1
No files found.
libcaf_core/caf/behavior.hpp
View file @
e828088f
...
...
@@ -97,14 +97,20 @@ public:
}
/// Runs this handler and returns its (optional) result.
inline
optional
<
message
>
operator
()(
message
&
x
)
{
return
impl_
?
impl_
->
invoke
(
x
)
:
none
;
inline
optional
<
message
>
operator
()(
message
&
x
s
)
{
return
impl_
?
impl_
->
invoke
(
x
s
)
:
none
;
}
/// Runs this handler with callback.
inline
match_case
::
result
operator
()(
detail
::
invoke_result_visitor
&
f
,
message
&
x
)
{
return
impl_
?
impl_
->
invoke
(
f
,
x
)
:
match_case
::
no_match
;
type_erased_tuple
&
xs
)
{
return
impl_
?
impl_
->
invoke
(
f
,
xs
)
:
match_case
::
no_match
;
}
/// Runs this handler with callback.
inline
match_case
::
result
operator
()(
detail
::
invoke_result_visitor
&
f
,
message
&
xs
)
{
return
impl_
?
impl_
->
invoke
(
f
,
xs
)
:
match_case
::
no_match
;
}
/// Checks whether this behavior is not empty.
...
...
libcaf_core/caf/detail/behavior_impl.hpp
View file @
e828088f
...
...
@@ -68,16 +68,17 @@ public:
behavior_impl
(
duration
tout
=
duration
{});
virtual
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&
);
virtual
match_case
::
result
invoke
_empty
(
detail
::
invoke_result_visitor
&
f
);
inline
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&&
arg
)
{
message
tmp
(
std
::
move
(
arg
));
return
invoke
(
f
,
tmp
);
}
virtual
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
type_erased_tuple
&
xs
);
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&
xs
);
optional
<
message
>
invoke
(
message
&
);
optional
<
message
>
invoke
(
type_erased_tuple
&
);
virtual
void
handle_timeout
();
inline
const
duration
&
timeout
()
const
{
...
...
libcaf_core/caf/detail/try_match.hpp
View file @
e828088f
...
...
@@ -38,14 +38,12 @@ struct meta_element {
atom_value
v
;
uint16_t
typenr
;
const
std
::
type_info
*
type
;
bool
(
*
fun
)(
const
meta_element
&
,
const
type_erased_tuple
*
,
size_t
,
void
**
);
bool
(
*
fun
)(
const
meta_element
&
,
const
type_erased_tuple
&
,
size_t
);
};
bool
match_element
(
const
meta_element
&
,
const
type_erased_tuple
*
,
size_t
,
void
**
);
bool
match_element
(
const
meta_element
&
,
const
type_erased_tuple
&
,
size_t
);
bool
match_atom_constant
(
const
meta_element
&
,
const
type_erased_tuple
*
,
size_t
,
void
**
);
bool
match_atom_constant
(
const
meta_element
&
,
const
type_erased_tuple
&
,
size_t
);
template
<
class
T
,
uint16_t
TN
=
type_nr
<
T
>
::
value
>
struct
meta_element_factory
{
...
...
@@ -80,8 +78,8 @@ struct meta_elements<type_list<Ts...>> {
}
};
bool
try_match
(
const
type_erased_tuple
*
xs
,
const
meta_element
*
pattern_begin
,
size_t
pattern_size
,
void
**
out
);
bool
try_match
(
const
type_erased_tuple
&
xs
,
const
meta_element
*
pattern_begin
,
size_t
pattern_size
);
}
// namespace detail
}
// namespace caf
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
e828088f
...
...
@@ -705,6 +705,16 @@ template <class F, class T>
using
is_handler_for_ef
=
typename
std
::
enable_if
<
is_handler_for
<
F
,
T
>::
value
>::
type
;
template
<
class
T
>
struct
strip_reference_wrapper
{
using
type
=
T
;
};
template
<
class
T
>
struct
strip_reference_wrapper
<
std
::
reference_wrapper
<
T
>>
{
using
type
=
T
;
};
}
// namespace detail
}
// namespace caf
...
...
libcaf_core/caf/fwd.hpp
View file @
e828088f
...
...
@@ -27,6 +27,7 @@ namespace caf {
// -- 1 param templates --------------------------------------------------------
template
<
class
>
class
param
;
template
<
class
>
class
optional
;
template
<
class
>
class
intrusive_ptr
;
template
<
class
>
class
behavior_type_of
;
...
...
libcaf_core/caf/match_case.hpp
View file @
e828088f
...
...
@@ -20,6 +20,7 @@
#ifndef CAF_MATCH_CASE_HPP
#define CAF_MATCH_CASE_HPP
#include <tuple>
#include <type_traits>
#include "caf/none.hpp"
...
...
@@ -55,7 +56,9 @@ public:
virtual
~
match_case
();
virtual
result
invoke
(
detail
::
invoke_result_visitor
&
,
type_erased_tuple
*
)
=
0
;
/// Tries to invoke this match case with the contents of `xs`.
virtual
result
invoke
(
detail
::
invoke_result_visitor
&
rv
,
type_erased_tuple
&
xs
)
=
0
;
inline
uint32_t
type_token
()
const
{
return
token_
;
...
...
@@ -65,38 +68,6 @@ private:
uint32_t
token_
;
};
template
<
class
T
>
T
&&
unopt
(
T
&&
v
,
typename
std
::
enable_if
<
std
::
is_rvalue_reference
<
T
&&>::
value
>::
type
*
=
0
)
{
return
std
::
move
(
v
);
}
template
<
class
T
>
T
&
unopt
(
T
&
v
)
{
return
v
;
}
template
<
class
T
>
T
&
unopt
(
optional
<
T
>&
v
)
{
return
*
v
;
}
struct
has_none
{
inline
bool
operator
()()
const
{
return
false
;
}
template
<
class
T
,
class
...
Ts
>
bool
operator
()(
const
T
&
,
const
Ts
&
...
xs
)
const
{
return
(
*
this
)(
xs
...);
}
template
<
class
T
,
class
...
Ts
>
bool
operator
()(
const
optional
<
T
>&
x
,
const
Ts
&
...
xs
)
const
{
return
!
x
||
(
*
this
)(
xs
...);
}
};
template
<
bool
IsVoid
,
class
F
>
class
lfinvoker
{
public:
...
...
@@ -106,7 +77,7 @@ public:
template
<
class
...
Ts
>
typename
detail
::
get_callable_trait
<
F
>::
result_type
operator
()(
Ts
&&
...
xs
)
{
return
fun_
(
unopt
(
std
::
forward
<
Ts
>
(
xs
)
)...);
return
fun_
(
std
::
forward
<
Ts
>
(
xs
)...);
}
private:
...
...
@@ -122,7 +93,7 @@ public:
template
<
class
...
Ts
>
unit_t
operator
()(
Ts
&&
...
xs
)
{
fun_
(
unopt
(
std
::
forward
<
Ts
>
(
xs
)
)...);
fun_
(
std
::
forward
<
Ts
>
(
xs
)...);
return
unit
;
}
...
...
@@ -166,12 +137,15 @@ public:
"down_msg not allowed in message handlers, "
"did you mean to use set_down_handler()?"
);
using
intermediate_tuple
=
using
decayed_arg_types
=
typename
detail
::
tl_map
<
arg_types
,
std
::
decay
>::
type
;
using
intermediate_pseudo_tuple
=
typename
detail
::
tl_apply
<
typename
detail
::
tl_map
<
arg_types
,
std
::
decay
>::
type
,
decayed_arg_types
,
detail
::
pseudo_tuple
>::
type
;
...
...
@@ -185,27 +159,25 @@ public:
}
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
type_erased_tuple
*
xs
)
override
{
intermediate_tuple
it
{
xs
?
xs
->
shared
()
:
false
};
type_erased_tuple
&
xs
)
override
{
detail
::
meta_elements
<
pattern
>
ms
;
message
tmp
;
// check if try_match() reports success
if
(
!
detail
::
try_match
(
xs
,
ms
.
arr
.
data
(),
ms
.
arr
.
size
()
,
it
.
data
))
if
(
!
detail
::
try_match
(
xs
,
ms
.
arr
.
data
(),
ms
.
arr
.
size
()))
return
match_case
::
no_match
;
// detach msg before invoking fun_ if needed
if
(
is_manipulator
&&
it
.
shared_access
)
{
tmp
=
message
::
from
(
xs
);
tmp
.
force_unshare
();
it
.
shared_access
=
false
;
// update pointers in our intermediate tuple
for
(
size_t
i
=
0
;
i
<
tmp
.
size
();
++
i
)
{
// msg is guaranteed to be detached, hence we don't need to
// check this condition over and over again via get_mutable
it
[
i
]
=
const_cast
<
void
*>
(
tmp
.
at
(
i
));
}
}
typename
detail
::
il_indices
<
decayed_arg_types
>::
type
indices
;
lfinvoker
<
std
::
is_same
<
result_type
,
void
>::
value
,
F
>
fun
{
fun_
};
auto
fun_res
=
apply_args
(
fun
,
detail
::
get_indices
(
it
),
it
);
message
tmp
;
intermediate_pseudo_tuple
tup
{
xs
.
shared
()};
if
(
is_manipulator
&&
tup
.
shared_access
)
{
tmp
=
message
::
copy_from
(
&
xs
);
tup
.
shared_access
=
false
;
for
(
size_t
i
=
0
;
i
<
tmp
.
size
();
++
i
)
tup
[
i
]
=
const_cast
<
void
*>
(
tmp
.
at
(
i
));
}
else
{
for
(
size_t
i
=
0
;
i
<
xs
.
size
();
++
i
)
tup
[
i
]
=
const_cast
<
void
*>
(
xs
.
get
(
i
));
}
auto
fun_res
=
apply_args
(
fun
,
indices
,
tup
);
return
f
.
visit
(
fun_res
)
?
match_case
::
match
:
match_case
::
skip
;
}
...
...
libcaf_core/caf/message.hpp
View file @
e828088f
...
...
@@ -272,13 +272,18 @@ public:
return
size
()
==
sizeof
...(
Ts
)
&&
match_elements_impl
(
p0
,
tlist
);
}
inline
std
::
pair
<
uint16_t
,
const
std
::
type_info
*>
type
(
size_t
pos
)
const
{
return
vals_
->
type
(
pos
);
}
message
&
operator
+=
(
const
message
&
x
);
/// Creates a message object from `ptr`.
static
message
from
(
const
type_erased_tuple
*
ptr
);
/// @cond PRIVATE
static
message
copy_from
(
const
type_erased_tuple
*
ptr
);
/// @cond PRIVATE
using
raw_ptr
=
detail
::
message_data
*
;
using
data_ptr
=
detail
::
message_data
::
cow_ptr
;
...
...
libcaf_core/caf/message_builder.hpp
View file @
e828088f
...
...
@@ -67,6 +67,16 @@ public:
return
emplace
(
make_type_erased_value
<
type
>
(
std
::
forward
<
T
>
(
x
)));
}
inline
message_builder
&
append_all
()
{
return
*
this
;
}
template
<
class
T
,
class
...
Ts
>
message_builder
&
append_all
(
T
&&
x
,
Ts
&&
...
xs
)
{
append
(
std
::
forward
<
T
>
(
x
));
return
append_all
(
std
::
forward
<
Ts
>
(
xs
)...);
}
/// Converts the buffer to an actual message object without
/// invalidating this message builder (nor clearing it).
message
to_message
()
const
;
...
...
libcaf_core/caf/message_handler.hpp
View file @
e828088f
...
...
@@ -93,6 +93,11 @@ public:
return
(
impl_
)
?
impl_
->
invoke
(
arg
)
:
none
;
}
/// Runs this handler and returns its (optional) result.
inline
optional
<
message
>
operator
()(
type_erased_tuple
&
xs
)
{
return
impl_
?
impl_
->
invoke
(
xs
)
:
none
;
}
/// Returns a new handler that concatenates this handler
/// with a new handler from `xs...`.
template
<
class
...
Ts
>
...
...
@@ -110,9 +115,8 @@ public:
if
(
!
tmp
)
{
return
*
this
;
}
if
(
impl_
)
{
if
(
impl_
)
return
impl_
->
or_else
(
tmp
.
as_behavior_impl
());
}
return
tmp
.
as_behavior_impl
();
}
...
...
libcaf_core/caf/type_erased_tuple.hpp
View file @
e828088f
...
...
@@ -215,7 +215,7 @@ private:
// -- data members -----------------------------------------------------------
std
::
tuple
<
type_erased_value_impl
<
std
::
reference_wrapper
<
Ts
>>
...
>
xs_
;
type_erased_value
*
ptrs_
[
sizeof
...(
Ts
)];
type_erased_value
*
ptrs_
[
sizeof
...(
Ts
)
==
0
?
1
:
sizeof
...(
Ts
)
];
};
template
<
class
...
Ts
>
...
...
libcaf_core/caf/type_erased_value.hpp
View file @
e828088f
...
...
@@ -112,6 +112,10 @@ inline std::string to_string(const type_erased_value& x) {
template
<
class
T
>
class
type_erased_value_impl
:
public
type_erased_value
{
public:
// -- member types -----------------------------------------------------------
using
value_type
=
typename
detail
::
strip_reference_wrapper
<
T
>::
type
;
// -- constructors, destructors, and assignment operators --------------------
template
<
class
...
Ts
>
...
...
@@ -153,9 +157,18 @@ public:
// -- overridden observers ---------------------------------------------------
static
rtti_pair
type
(
std
::
integral_constant
<
uint16_t
,
0
>
)
{
return
{
0
,
&
typeid
(
value_type
)};
}
template
<
uint16_t
V
>
static
rtti_pair
type
(
std
::
integral_constant
<
uint16_t
,
V
>
)
{
return
{
V
,
nullptr
};
}
rtti_pair
type
()
const
override
{
auto
nr
=
caf
::
type_nr
<
T
>::
value
;
return
{
nr
,
&
typeid
(
T
)}
;
std
::
integral_constant
<
uint16_t
,
caf
::
type_nr
<
value_type
>::
value
>
token
;
return
type
(
token
)
;
}
const
void
*
get
()
const
override
{
...
...
@@ -198,18 +211,6 @@ private:
return
&
x
.
get
();
}
// -- typeid utility ---------------------------------------------------------
template
<
class
U
>
static
inline
const
std
::
type_info
*
typeid_of
(
U
&
)
{
return
&
typeid
(
U
);
}
template
<
class
U
>
static
inline
const
std
::
type_info
*
typeid_of
(
std
::
reference_wrapper
<
U
>&
)
{
return
&
typeid
(
U
);
}
// -- array copying utility --------------------------------------------------
template
<
class
U
,
size_t
Len
>
...
...
libcaf_core/src/behavior_impl.cpp
View file @
e828088f
...
...
@@ -28,9 +28,10 @@ namespace {
class
combinator
final
:
public
behavior_impl
{
public:
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&
arg
)
override
{
auto
x
=
first
->
invoke
(
f
,
arg
);
return
x
==
match_case
::
no_match
?
second
->
invoke
(
f
,
arg
)
:
x
;
match_case
::
result
invoke
(
detail
::
invoke_result_visitor
&
f
,
type_erased_tuple
&
xs
)
override
{
auto
x
=
first
->
invoke
(
f
,
xs
);
return
x
==
match_case
::
no_match
?
second
->
invoke
(
f
,
xs
)
:
x
;
}
void
handle_timeout
()
override
{
...
...
@@ -89,12 +90,18 @@ behavior_impl::behavior_impl(duration tout)
// nop
}
match_case
::
result
behavior_impl
::
invoke_empty
(
detail
::
invoke_result_visitor
&
f
)
{
auto
xs
=
make_type_erased_tuple_view
();
return
invoke
(
f
,
xs
);
}
match_case
::
result
behavior_impl
::
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&
msg
)
{
auto
msg_token
=
msg
.
type_token
();
type_erased_tuple
&
xs
)
{
auto
msg_token
=
xs
.
type_token
();
for
(
auto
i
=
begin_
;
i
!=
end_
;
++
i
)
if
(
i
->
type_token
==
msg_token
)
switch
(
i
->
ptr
->
invoke
(
f
,
msg
.
cvals
().
get
()
))
{
switch
(
i
->
ptr
->
invoke
(
f
,
xs
))
{
case
match_case
:
:
no_match
:
break
;
case
match_case
:
:
match
:
...
...
@@ -105,12 +112,32 @@ match_case::result behavior_impl::invoke(detail::invoke_result_visitor& f,
return
match_case
::
no_match
;
}
optional
<
message
>
behavior_impl
::
invoke
(
message
&
x
)
{
optional
<
message
>
behavior_impl
::
invoke
(
message
&
x
s
)
{
maybe_message_visitor
f
;
invoke
(
f
,
x
);
// the following const-cast is safe, because invoke() is aware of
// copy-on-write and does not modify x if it's shared
if
(
!
xs
.
empty
())
invoke
(
f
,
*
const_cast
<
message_data
*>
(
xs
.
cvals
().
get
()));
else
invoke_empty
(
f
);
return
std
::
move
(
f
.
value
);
}
optional
<
message
>
behavior_impl
::
invoke
(
type_erased_tuple
&
xs
)
{
maybe_message_visitor
f
;
invoke
(
f
,
xs
);
return
std
::
move
(
f
.
value
);
}
match_case
::
result
behavior_impl
::
invoke
(
detail
::
invoke_result_visitor
&
f
,
message
&
xs
)
{
// the following const-cast is safe, because invoke() is aware of
// copy-on-write and does not modify x if it's shared
if
(
!
xs
.
empty
())
return
invoke
(
f
,
*
const_cast
<
message_data
*>
(
xs
.
cvals
().
get
()));
return
invoke_empty
(
f
);
}
void
behavior_impl
::
handle_timeout
()
{
// nop
}
...
...
libcaf_core/src/local_actor.cpp
View file @
e828088f
...
...
@@ -463,7 +463,7 @@ void local_actor::handle_response(mailbox_element_ptr& ptr,
});
local_actor_invoke_result_visitor
visitor
{
this
};
auto
invoke_error
=
[
&
](
error
err
)
{
auto
tmp
=
make_
message
(
err
);
auto
tmp
=
make_
type_erased_tuple_view
(
err
);
if
(
ref_fun
(
visitor
,
tmp
)
==
match_case
::
no_match
)
{
CAF_LOG_WARNING
(
"multiplexed response failure occured:"
<<
CAF_ARG
(
id
()));
...
...
libcaf_core/src/message.cpp
View file @
e828088f
...
...
@@ -79,6 +79,13 @@ message message::from(const type_erased_tuple* ptr) {
return
mb
.
move_to_message
();
}
message
message
::
copy_from
(
const
type_erased_tuple
*
ptr
)
{
message_builder
mb
;
for
(
size_t
i
=
0
;
i
<
ptr
->
size
();
++
i
)
mb
.
emplace
(
ptr
->
copy
(
i
));
return
mb
.
move_to_message
();
}
bool
message
::
match_element
(
size_t
pos
,
uint16_t
typenr
,
const
std
::
type_info
*
rtti
)
const
{
return
vals_
->
matches
(
pos
,
typenr
,
rtti
);
...
...
libcaf_core/src/try_match.cpp
View file @
e828088f
...
...
@@ -24,43 +24,30 @@ namespace detail {
using
pattern_iterator
=
const
meta_element
*
;
bool
match_element
(
const
meta_element
&
me
,
const
type_erased_tuple
*
xs
,
size_t
pos
,
void
**
storage
)
{
bool
match_element
(
const
meta_element
&
me
,
const
type_erased_tuple
&
xs
,
size_t
pos
)
{
CAF_ASSERT
(
me
.
typenr
!=
0
||
me
.
type
!=
nullptr
);
if
(
!
xs
->
matches
(
pos
,
me
.
typenr
,
me
.
type
))
return
false
;
*
storage
=
const_cast
<
void
*>
(
xs
->
get
(
pos
));
return
true
;
return
xs
.
matches
(
pos
,
me
.
typenr
,
me
.
type
);
}
bool
match_atom_constant
(
const
meta_element
&
me
,
const
type_erased_tuple
*
xs
,
size_t
pos
,
void
**
storage
)
{
bool
match_atom_constant
(
const
meta_element
&
me
,
const
type_erased_tuple
&
xs
,
size_t
pos
)
{
CAF_ASSERT
(
me
.
typenr
==
type_nr
<
atom_value
>::
value
);
if
(
!
xs
->
matches
(
pos
,
type_nr
<
atom_value
>::
value
,
nullptr
))
if
(
!
xs
.
matches
(
pos
,
type_nr
<
atom_value
>::
value
,
nullptr
))
return
false
;
auto
ptr
=
xs
->
get
(
pos
);
auto
ptr
=
xs
.
get
(
pos
);
if
(
me
.
v
!=
*
reinterpret_cast
<
const
atom_value
*>
(
ptr
))
return
false
;
// This assignment casts `atom_value` to `atom_constant<V>*`.
// This type violation could theoretically cause undefined behavior.
// However, `uti` does have an address that is guaranteed to be valid
// throughout the runtime of the program and the atom constant
// does not have any members. Hence, this is nonetheless safe since
// we are never actually going to dereference the pointer.
*
storage
=
const_cast
<
void
*>
(
ptr
);
return
true
;
}
bool
try_match
(
const
type_erased_tuple
*
xs
,
pattern_iterator
iter
,
size_t
ps
,
void
**
out
)
{
CAF_ASSERT
(
out
!=
nullptr
);
if
(
!
xs
)
return
ps
==
0
;
if
(
xs
->
size
()
!=
ps
)
bool
try_match
(
const
type_erased_tuple
&
xs
,
pattern_iterator
iter
,
size_t
ps
)
{
if
(
xs
.
size
()
!=
ps
)
return
false
;
for
(
size_t
i
=
0
;
i
<
ps
;
++
i
,
++
iter
,
++
out
)
for
(
size_t
i
=
0
;
i
<
ps
;
++
i
,
++
iter
)
// inspect current element
if
(
!
iter
->
fun
(
*
iter
,
xs
,
i
,
out
))
if
(
!
iter
->
fun
(
*
iter
,
xs
,
i
))
// type mismatch
return
false
;
return
true
;
...
...
libcaf_core/test/composable_behavior.cpp
View file @
e828088f
...
...
@@ -178,7 +178,7 @@ public:
}
result
<
counting_string
>
operator
()(
get_atom
,
param
<
counting_string
>
key
)
override
{
auto
i
=
values_
.
find
(
key
);
auto
i
=
values_
.
find
(
key
.
get
()
);
if
(
i
==
values_
.
end
())
return
""
;
return
i
->
second
;
...
...
@@ -186,7 +186,7 @@ public:
result
<
void
>
operator
()(
put_atom
,
param
<
counting_string
>
key
,
param
<
counting_string
>
value
)
override
{
if
(
values_
.
count
(
key
)
!=
0
)
if
(
values_
.
count
(
key
.
get
()
)
!=
0
)
return
unit
;
values_
.
emplace
(
key
.
move
(),
value
.
move
());
return
unit
;
...
...
libcaf_core/test/match.cpp
View file @
e828088f
...
...
@@ -33,83 +33,94 @@ using namespace std;
using
hi_atom
=
atom_constant
<
atom
(
"hi"
)
>
;
using
ho_atom
=
atom_constant
<
atom
(
"ho"
)
>
;
function
<
optional
<
string
>
(
const
string
&
)
>
starts_with
(
const
string
&
s
)
{
return
[
=
](
const
string
&
str
)
->
optional
<
string
>
{
if
(
str
.
size
()
>
s
.
size
()
&&
str
.
compare
(
0
,
s
.
size
(),
s
)
==
0
)
return
str
.
substr
(
s
.
size
());
return
none
;
};
}
namespace
{
optional
<
int
>
toint
(
const
string
&
str
)
{
char
*
endptr
=
nullptr
;
int
result
=
static_cast
<
int
>
(
strtol
(
str
.
c_str
(),
&
endptr
,
10
));
if
(
endptr
!=
nullptr
&&
*
endptr
==
'\0'
)
{
return
result
;
}
return
none
;
}
using
rtti_pair
=
std
::
pair
<
uint16_t
,
const
std
::
type_info
*>
;
namespace
{
std
::
string
to_string
(
const
rtti_pair
&
x
)
{
if
(
x
.
second
)
return
deep_to_string_as_tuple
(
x
.
first
,
x
.
second
->
name
());
return
deep_to_string_as_tuple
(
x
.
first
,
"<null>"
);
}
bool
s_invoked
[]
=
{
false
,
false
,
false
,
false
};
struct
fixture
{
using
array_type
=
std
::
array
<
bool
,
4
>
;
}
// namespace <anonymous>
fixture
()
{
}
void
reset
()
{
fill
(
begin
(
s_invoked
),
end
(
s_invoked
),
false
);
}
void
reset
()
{
for
(
auto
&
x
:
invoked
)
x
=
false
;
}
void
fill_mb
(
message_builder
&
)
{
// end of recursion
}
template
<
class
...
Ts
>
ptrdiff_t
invoke
(
message_handler
expr
,
Ts
...
xs
)
{
auto
msg1
=
make_message
(
xs
...);
auto
msg2
=
message_builder
{}.
append_all
(
xs
...).
move_to_message
();
auto
msg3
=
make_type_erased_tuple_view
(
xs
...);
CAF_CHECK_EQUAL
(
to_string
(
msg1
),
to_string
(
msg2
));
CAF_CHECK_EQUAL
(
to_string
(
msg1
),
to_string
(
msg3
));
CAF_CHECK_EQUAL
(
msg1
.
type_token
(),
msg2
.
type_token
());
CAF_CHECK_EQUAL
(
msg1
.
type_token
(),
msg3
.
type_token
());
std
::
vector
<
std
::
string
>
msg1_types
;
std
::
vector
<
std
::
string
>
msg2_types
;
std
::
vector
<
std
::
string
>
msg3_types
;
for
(
size_t
i
=
0
;
i
<
msg1
.
size
();
++
i
)
{
msg1_types
.
push_back
(
to_string
(
msg1
.
type
(
i
)));
msg2_types
.
push_back
(
to_string
(
msg2
.
type
(
i
)));
msg3_types
.
push_back
(
to_string
(
msg3
.
type
(
i
)));
}
CAF_CHECK_EQUAL
(
msg1_types
,
msg2_types
);
CAF_CHECK_EQUAL
(
msg1_types
,
msg3_types
);
set
<
ptrdiff_t
>
results
;
process
(
results
,
expr
,
msg1
,
msg2
,
msg3
);
if
(
results
.
size
()
>
1
)
{
CAF_ERROR
(
"different results reported: "
<<
deep_to_string
(
results
));
return
-
2
;
}
return
*
results
.
begin
();
}
template
<
class
T
,
class
...
Ts
>
void
fill_mb
(
message_builder
&
mb
,
const
T
&
x
,
const
Ts
&
...
xs
)
{
fill_mb
(
mb
.
append
(
x
),
xs
...);
}
void
process
(
std
::
set
<
ptrdiff_t
>&
,
message_handler
&
)
{
// end of recursion
}
template
<
class
...
Ts
>
ptrdiff_t
invoked
(
message_handler
expr
,
const
Ts
&
...
xs
)
{
vector
<
message
>
msgs
;
msgs
.
push_back
(
make_message
(
xs
...));
message_builder
mb
;
fill_mb
(
mb
,
xs
...);
msgs
.
push_back
(
mb
.
to_message
());
set
<
ptrdiff_t
>
results
;
for
(
auto
&
msg
:
msgs
)
{
expr
(
msg
);
auto
first
=
begin
(
s_invoked
);
auto
last
=
end
(
s_invoked
);
auto
i
=
find
(
begin
(
s_invoked
),
last
,
true
);
results
.
insert
(
i
!=
last
&&
count
(
i
,
last
,
true
)
==
1
?
distance
(
first
,
i
)
:
-
1
);
template
<
class
T
,
class
...
Ts
>
void
process
(
std
::
set
<
ptrdiff_t
>&
results
,
message_handler
&
expr
,
T
&
x
,
Ts
&
...
xs
)
{
expr
(
x
);
results
.
insert
(
invoked_res
());
reset
();
process
(
results
,
expr
,
xs
...);
}
if
(
results
.
size
()
>
1
)
{
CAF_ERROR
(
"make_message() yielded a different result than "
"message_builder(...).to_message()"
);
return
-
2
;
ptrdiff_t
invoked_res
()
{
auto
first
=
begin
(
invoked
);
auto
last
=
end
(
invoked
);
auto
i
=
find
(
first
,
last
,
true
);
return
i
!=
last
&&
count
(
i
,
last
,
true
)
==
1
?
distance
(
first
,
i
)
:
-
1
;
}
return
*
results
.
begin
();
}
function
<
void
()
>
f
(
int
idx
)
{
return
[
=
]
{
s_invoked
[
idx
]
=
true
;
};
}
array_type
invoked
;
};
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
atom_constants_tests
,
fixture
)
CAF_TEST
(
atom_constants
)
{
message_handler
expr
{
[](
hi_atom
)
{
s_
invoked
[
0
]
=
true
;
[
&
](
hi_atom
)
{
invoked
[
0
]
=
true
;
},
[](
ho_atom
)
{
s_
invoked
[
1
]
=
true
;
[
&
](
ho_atom
)
{
invoked
[
1
]
=
true
;
}
};
CAF_CHECK_EQUAL
(
invoke
d
(
expr
,
ok_atom
::
value
),
-
1
);
CAF_CHECK_EQUAL
(
invoke
d
(
expr
,
hi_atom
::
value
),
0
);
CAF_CHECK_EQUAL
(
invoke
d
(
expr
,
ho_atom
::
value
),
1
);
CAF_CHECK_EQUAL
(
invoke
(
expr
,
atom_value
{
ok_atom
::
value
}
),
-
1
);
CAF_CHECK_EQUAL
(
invoke
(
expr
,
atom_value
{
hi_atom
::
value
}
),
0
);
CAF_CHECK_EQUAL
(
invoke
(
expr
,
atom_value
{
ho_atom
::
value
}
),
1
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/message_lifetime.cpp
View file @
e828088f
...
...
@@ -112,9 +112,9 @@ CAF_TEST(message_lifetime_in_scoped_actor) {
CAF_CHECK_EQUAL
(
msg
.
cvals
()
->
get_reference_count
(),
1u
);
msg
=
make_message
(
42
);
self
->
send
(
self
,
msg
);
CAF_CHECK_EQUAL
(
msg
.
cvals
()
->
get_reference_count
(),
2u
);
self
->
receive
(
[
&
](
int
&
value
)
{
CAF_CHECK_EQUAL
(
msg
.
cvals
()
->
get_reference_count
(),
2u
);
CAF_CHECK_NOT_EQUAL
(
&
value
,
msg
.
at
(
0
));
value
=
10
;
}
...
...
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