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
f676aa81
Commit
f676aa81
authored
Apr 14, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement type-erased views
parent
37b1c2dc
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
421 additions
and
127 deletions
+421
-127
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+2
-2
libcaf_core/caf/deep_to_string.hpp
libcaf_core/caf/deep_to_string.hpp
+6
-0
libcaf_core/caf/detail/try_serialize.hpp
libcaf_core/caf/detail/try_serialize.hpp
+3
-3
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+37
-9
libcaf_core/caf/message_builder.hpp
libcaf_core/caf/message_builder.hpp
+1
-1
libcaf_core/caf/type_erased_tuple.hpp
libcaf_core/caf/type_erased_tuple.hpp
+135
-4
libcaf_core/caf/type_erased_value.hpp
libcaf_core/caf/type_erased_value.hpp
+107
-99
libcaf_core/src/type_erased_tuple.cpp
libcaf_core/src/type_erased_tuple.cpp
+23
-0
libcaf_core/src/uniform_type_info_map.cpp
libcaf_core/src/uniform_type_info_map.cpp
+1
-1
libcaf_core/test/serialization.cpp
libcaf_core/test/serialization.cpp
+106
-8
No files found.
libcaf_core/caf/actor_system_config.hpp
View file @
f676aa81
...
...
@@ -127,9 +127,9 @@ public:
"T must provide default and copy constructors"
);
static_assert
(
detail
::
is_serializable
<
T
>::
value
,
"T must be serializable"
);
type_names_by_rtti_
.
emplace
(
std
::
type_index
(
typeid
(
T
)),
name
);
value_factories_by_name_
.
emplace
(
std
::
move
(
name
),
&
make_type_erased
<
T
>
);
value_factories_by_name_
.
emplace
(
std
::
move
(
name
),
&
make_type_erased
_value
<
T
>
);
value_factories_by_rtti_
.
emplace
(
std
::
type_index
(
typeid
(
T
)),
&
make_type_erased
<
T
>
);
&
make_type_erased
_value
<
T
>
);
return
*
this
;
}
...
...
libcaf_core/caf/deep_to_string.hpp
View file @
f676aa81
...
...
@@ -24,6 +24,7 @@
#include <tuple>
#include <string>
#include <utility>
#include <functional>
#include <type_traits>
#include "caf/atom.hpp"
...
...
@@ -38,6 +39,11 @@ public:
// nop
}
template
<
class
T
>
std
::
string
operator
()(
const
std
::
reference_wrapper
<
T
>&
x
)
const
{
return
(
*
this
)(
x
.
get
());
}
std
::
string
operator
()(
const
char
*
cstr
)
const
;
inline
std
::
string
operator
()(
char
*
cstr
)
const
{
...
...
libcaf_core/caf/detail/try_serialize.hpp
View file @
f676aa81
...
...
@@ -23,13 +23,13 @@
namespace
caf
{
namespace
detail
{
template
<
class
Processor
,
class
U
>
auto
try_serialize
(
Processor
&
proc
,
U
*
x
)
->
decltype
(
proc
&
*
x
)
{
template
<
class
Processor
,
class
T
>
auto
try_serialize
(
Processor
&
proc
,
T
*
x
)
->
decltype
(
proc
&
*
x
)
{
proc
&
*
x
;
}
template
<
class
Processor
>
void
try_serialize
(
Processor
&
,
const
void
*
)
{
void
try_serialize
(
Processor
&
,
void
*
)
{
// nop
}
...
...
libcaf_core/caf/fwd.hpp
View file @
f676aa81
...
...
@@ -25,22 +25,26 @@
namespace
caf
{
// 1-class templates
// -- 1 param templates --------------------------------------------------------
template
<
class
>
class
maybe
;
template
<
class
>
class
optional
;
template
<
class
>
class
intrusive_ptr
;
template
<
class
>
class
weak_intrusive_ptr
;
template
<
class
>
class
typed_continue_helper
;
// 2-class templates
// -- 3 param templates --------------------------------------------------------
template
<
class
,
class
,
int
>
class
actor_cast_access
;
// variadic templates
// -- variadic templates -------------------------------------------------------
template
<
class
...
>
class
delegated
;
template
<
class
...
>
class
typed_actor
;
template
<
class
...
>
class
typed_response_promise
;
// classes
// -- classes ------------------------------------------------------------------
class
actor
;
class
group
;
class
error
;
...
...
@@ -70,15 +74,18 @@ class continue_helper;
class
mailbox_element
;
class
message_handler
;
class
response_promise
;
class
event_based_actor
;
class
binary_serializer
;
class
event_based_actor
;
class
type_erased_tuple
;
class
type_erased_value
;
class
actor_control_block
;
class
binary_deserializer
;
class
actor_system_config
;
class
uniform_type_info_map
;
class
forwarding_actor_proxy
;
// structs
// -- structs ------------------------------------------------------------------
struct
unit_t
;
struct
anything
;
struct
exit_msg
;
...
...
@@ -90,12 +97,16 @@ struct invalid_actor_addr_t;
struct
illegal_message_element
;
struct
prohibit_top_level_spawn_marker
;
// enums
// -- enums --------------------------------------------------------------------
enum
class
atom_value
:
uint64_t
;
// aliases
// -- aliases ------------------------------------------------------------------
using
actor_id
=
uint64_t
;
// -- I/O classes --------------------------------------------------------------
namespace
io
{
class
broker
;
...
...
@@ -109,18 +120,24 @@ struct header;
}
// namespace io
// -- OpenCL classes -----------------------------------------------------------
namespace
opencl
{
class
manager
;
}
// namespace opencl
// -- RIAC classes -------------------------------------------------------------
namespace
riac
{
class
probe
;
}
// namespace riac
// -- scheduler classes --------------------------------------------------------
namespace
scheduler
{
class
abstract_worker
;
...
...
@@ -128,6 +145,8 @@ class abstract_coordinator;
}
// namespace scheduler
// -- detail classes -----------------------------------------------------------
namespace
detail
{
class
disposer
;
...
...
@@ -137,8 +156,17 @@ class dynamic_message_data;
}
// namespace detail
using
strong_actor_ptr
=
intrusive_ptr
<
actor_control_block
>
;
// -- weak pointer aliases -----------------------------------------------------
using
weak_actor_ptr
=
weak_intrusive_ptr
<
actor_control_block
>
;
// -- intrusive pointer aliases ------------------------------------------------
using
strong_actor_ptr
=
intrusive_ptr
<
actor_control_block
>
;
// -- unique pointer aliases ---------------------------------------------------
using
type_erased_value_ptr
=
std
::
unique_ptr
<
type_erased_value
>
;
using
mailbox_element_ptr
=
std
::
unique_ptr
<
mailbox_element
,
detail
::
disposer
>
;
}
// namespace caf
...
...
libcaf_core/caf/message_builder.hpp
View file @
f676aa81
...
...
@@ -62,7 +62,7 @@ public:
typename
std
::
decay
<
T
>::
type
>::
type
>::
type
;
return
emplace
(
make_type_erased
<
type
>
(
std
::
forward
<
T
>
(
x
)));
return
emplace
(
make_type_erased
_value
<
type
>
(
std
::
forward
<
T
>
(
x
)));
}
/// Converts the buffer to an actual message object without
...
...
libcaf_core/caf/type_erased_tuple.hpp
View file @
f676aa81
...
...
@@ -20,49 +20,78 @@
#ifndef CAF_TYPE_ERASED_COLLECTION_HPP
#define CAF_TYPE_ERASED_COLLECTION_HPP
#include <tuple>
#include <cstddef>
#include <cstdint>
#include <typeinfo>
#include "caf/fwd.hpp"
#include "caf/type_erased_value.hpp"
#include "caf/detail/type_nr.hpp"
namespace
caf
{
/// Represents a tuple of type-erased values.
class
type_erased_tuple
{
public:
// -- member types -----------------------------------------------------------
using
rtti_pair
=
std
::
pair
<
uint16_t
,
const
std
::
type_info
*>
;
// -- constructors, destructors, and assignment operators --------------------
virtual
~
type_erased_tuple
();
//
pure virtual modifiers
//
-- pure virtual modifiers -------------------------------------------------
/// Returns a mutable pointer to the element at position `pos`.
virtual
void
*
get_mutable
(
size_t
pos
)
=
0
;
/// Load the content for the element at position `pos` from `source`.
virtual
void
load
(
size_t
pos
,
deserializer
&
source
)
=
0
;
//
pure virtual observers
//
-- modifiers --------------------------------------------------------------
/// Load the content for the tuple from `source`.
void
load
(
deserializer
&
source
);
// -- pure virtual observers -------------------------------------------------
/// Returns the size of this tuple.
virtual
size_t
size
()
const
=
0
;
/// Returns a type hint for the element types.
virtual
uint32_t
type_token
()
const
=
0
;
/// Returns the type number and `std::type_info` object for
/// the element at position `pos`.
virtual
rtti_pair
type
(
size_t
pos
)
const
=
0
;
/// Returns the element at position `pos`.
virtual
const
void
*
get
(
size_t
pos
)
const
=
0
;
/// Returns a string representation of the element at position `pos`.
virtual
std
::
string
stringify
(
size_t
pos
)
const
=
0
;
/// Saves the element at position `pos` to `sink`.
virtual
void
save
(
size_t
pos
,
serializer
&
sink
)
const
=
0
;
// observers
// -- observers --------------------------------------------------------------
/// Returns a string representation of the tuple.
std
::
string
stringify
()
const
;
/// Saves the content of the tuple to `sink`.
void
save
(
serializer
&
sink
)
const
;
/// Checks whether the type of the stored value matches
/// the type nr and type info object.
bool
matches
(
size_t
pos
,
uint16_t
tnr
,
const
std
::
type_info
*
tinf
)
const
;
//
inline observers
//
-- inline observers -------------------------------------------------------
/// Returns the type number for the element at position `pos`.
inline
uint16_t
type_nr
(
size_t
pos
)
const
{
return
type
(
pos
).
first
;
}
...
...
@@ -73,6 +102,108 @@ public:
}
};
/// @relates type_erased_tuple
template
<
class
Processor
>
typename
std
::
enable_if
<
Processor
::
is_saving
::
value
>::
type
serialize
(
Processor
&
proc
,
type_erased_tuple
&
x
)
{
x
.
save
(
proc
);
}
/// @relates type_erased_tuple
template
<
class
Processor
>
typename
std
::
enable_if
<
Processor
::
is_loading
::
value
>::
type
serialize
(
Processor
&
proc
,
type_erased_tuple
&
x
)
{
x
.
load
(
proc
);
}
/// @relates type_erased_tuple
inline
std
::
string
to_string
(
const
type_erased_tuple
&
x
)
{
return
x
.
stringify
();
}
template
<
class
...
Ts
>
class
type_erased_tuple_view
:
public
type_erased_tuple
{
public:
// -- member types -----------------------------------------------------------
template
<
size_t
X
>
using
num_token
=
std
::
integral_constant
<
size_t
,
X
>
;
// -- constructors, destructors, and assignment operators --------------------
type_erased_tuple_view
(
Ts
&
...
xs
)
:
xs_
(
xs
...)
{
init
();
}
type_erased_tuple_view
(
const
type_erased_tuple_view
&
other
)
:
xs_
(
other
.
xs_
)
{
init
();
}
// -- overridden modifiers ---------------------------------------------------
void
*
get_mutable
(
size_t
pos
)
override
{
return
ptrs_
[
pos
]
->
get_mutable
();
}
void
load
(
size_t
pos
,
deserializer
&
source
)
override
{
ptrs_
[
pos
]
->
load
(
source
);
}
// -- overridden observers ---------------------------------------------------
size_t
size
()
const
override
{
return
sizeof
...(
Ts
);
}
uint32_t
type_token
()
const
override
{
return
detail
::
make_type_token
<
Ts
...
>
();
}
rtti_pair
type
(
size_t
pos
)
const
override
{
return
ptrs_
[
pos
]
->
type
();
}
const
void
*
get
(
size_t
pos
)
const
override
{
return
ptrs_
[
pos
]
->
get
();
}
std
::
string
stringify
(
size_t
pos
)
const
override
{
return
ptrs_
[
pos
]
->
stringify
();
}
void
save
(
size_t
pos
,
serializer
&
sink
)
const
override
{
return
ptrs_
[
pos
]
->
save
(
sink
);
}
private:
// -- pointer "lookup table" utility -----------------------------------------
template
<
size_t
N
>
void
init
(
num_token
<
N
>
,
num_token
<
N
>
)
{
// end of recursion
}
template
<
size_t
P
,
size_t
N
>
void
init
(
num_token
<
P
>
,
num_token
<
N
>
last
)
{
ptrs_
[
P
]
=
&
std
::
get
<
P
>
(
xs_
);
init
(
num_token
<
P
+
1
>
{},
last
);
}
void
init
()
{
init
(
num_token
<
0
>
{},
num_token
<
sizeof
...(
Ts
)
>
{});
}
// -- data members -----------------------------------------------------------
std
::
tuple
<
type_erased_value_impl
<
std
::
reference_wrapper
<
Ts
>>
...
>
xs_
;
type_erased_value
*
ptrs_
[
sizeof
...(
Ts
)];
};
template
<
class
...
Ts
>
type_erased_tuple_view
<
Ts
...
>
make_type_erased_tuple_view
(
Ts
&
...
xs
)
{
return
{
xs
...};
}
}
// namespace caf
#endif // CAF_TYPE_ERASED_COLLECTION_HPP
libcaf_core/caf/type_erased_value.hpp
View file @
f676aa81
...
...
@@ -22,7 +22,9 @@
#include <cstdint>
#include <typeinfo>
#include <functional>
#include "caf/fwd.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/detail/type_nr.hpp"
...
...
@@ -31,18 +33,18 @@
namespace
caf
{
class
type_erased_value
;
using
type_erased_value_ptr
=
std
::
unique_ptr
<
type_erased_value
>
;
/// Represents a single type-erased value.
class
type_erased_value
{
public:
// -- member types -----------------------------------------------------------
using
rtti_pair
=
std
::
pair
<
uint16_t
,
const
std
::
type_info
*>
;
// -- constructors, destructors, and assignment operators --------------------
virtual
~
type_erased_value
();
//
pure virtual modifiers
//
-- pure virtual modifiers -------------------------------------------------
/// Returns a mutable pointer to the stored value.
virtual
void
*
get_mutable
()
=
0
;
...
...
@@ -50,7 +52,7 @@ public:
/// Load the content for the stored value from `source`.
virtual
void
load
(
deserializer
&
source
)
=
0
;
//
pure virtual observers
//
-- pure virtual observers -------------------------------------------------
/// Returns the type number and type information object for the stored value.
virtual
rtti_pair
type
()
const
=
0
;
...
...
@@ -67,13 +69,13 @@ public:
/// Returns a copy of the stored value.
virtual
type_erased_value_ptr
copy
()
const
=
0
;
//
observers
//
-- observers --------------------------------------------------------------
/// Checks whether the type of the stored value matches
/// the type nr and type info object.
bool
matches
(
uint16_t
tnr
,
const
std
::
type_info
*
tinf
)
const
;
//
inline observers
//
-- inline observers -------------------------------------------------------
/// Returns the type number for the stored value.
inline
uint16_t
type_nr
()
const
{
...
...
@@ -86,162 +88,168 @@ public:
}
};
/// @relates type_erased_value_impl
template
<
class
Processor
>
typename
std
::
enable_if
<
Processor
::
is_saving
::
value
>::
type
serialize
(
Processor
&
proc
,
type_erased_value
&
x
)
{
x
.
save
(
proc
);
}
/// @relates type_erased_value_impl
template
<
class
Processor
>
typename
std
::
enable_if
<
Processor
::
is_loading
::
value
>::
type
serialize
(
Processor
&
proc
,
type_erased_value
&
x
)
{
x
.
load
(
proc
);
}
/// @relates type_erased_value_impl
inline
std
::
string
to_string
(
const
type_erased_value
&
x
)
{
return
x
.
stringify
();
}
/// @relates type_erased_value
/// Default implementation for single type-erased values.
template
<
class
T
>
struct
type_erased_value_impl
:
public
type_erased_value
{
T
x
;
class
type_erased_value_impl
:
public
type_erased_value
{
public:
// -- constructors, destructors, and assignment operators --------------------
template
<
class
...
Ts
>
type_erased_value_impl
(
Ts
&&
...
xs
)
:
x
(
std
::
forward
<
Ts
>
(
xs
)...)
{
type_erased_value_impl
(
Ts
&&
...
xs
)
:
x
_
(
std
::
forward
<
Ts
>
(
xs
)...)
{
// nop
}
type_erased_value_impl
(
const
T
&
value
)
:
x
(
value
)
{
// nop
template
<
class
U
,
size_t
N
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
T
,
U
[
N
]>
::
value
>::
type
>
type_erased_value_impl
(
const
U
(
&
ys
)[
N
])
{
array_copy
(
x_
,
ys
);
}
void
*
get_mutable
()
override
{
return
&
x
;
template
<
class
U
,
size_t
N
,
class
=
typename
std
::
enable_if
<
std
::
is_same
<
T
,
U
[
N
]>
::
value
>::
type
>
type_erased_value_impl
(
const
U
(
&&
ys
)[
N
])
{
array_copy
(
x_
,
ys
);
}
const
void
*
get
()
const
override
{
return
&
x
;
type_erased_value_impl
(
type_erased_value_impl
&&
other
)
:
type_erased_value_impl
(
std
::
move
(
other
.
x_
))
{
// nop
}
void
save
(
serializer
&
sink
)
const
override
{
detail
::
try_serialize
(
sink
,
const_cast
<
T
*>
(
&
x
));
type_erased_value_impl
(
const
type_erased_value_impl
&
other
)
:
type_erased_value_impl
(
other
.
x_
)
{
// nop
}
void
load
(
deserializer
&
source
)
override
{
detail
::
try_serialize
(
source
,
&
x
);
}
// -- overridden modifiers ---------------------------------------------------
std
::
string
stringify
()
const
override
{
return
deep_to_string
(
x
);
void
*
get_mutable
()
override
{
return
addr_of
(
x_
);
}
type_erased_value_ptr
copy
()
const
override
{
return
type_erased_value_ptr
{
new
type_erased_value_impl
(
x
)}
;
void
load
(
deserializer
&
source
)
override
{
detail
::
try_serialize
(
source
,
addr_of
(
x_
))
;
}
// -- overridden observers ---------------------------------------------------
rtti_pair
type
()
const
override
{
auto
nr
=
detail
::
type_nr
<
T
>::
value
;
return
{
nr
,
&
typeid
(
T
)};
}
};
template
<
class
T
,
size_t
N
>
struct
type_erased_value_impl
<
T
[
N
]
>
:
public
type_erased_value
{
using
array_type
=
T
[
N
];
array_type
xs
;
type_erased_value_impl
(
const
T
(
&
ys
)[
N
])
{
array_copy
(
xs
,
ys
);
const
void
*
get
()
const
override
{
// const is restored when returning from the function
return
addr_of
(
const_cast
<
T
&>
(
x_
));
}
type_erased_value_impl
()
{
// nop
void
save
(
serializer
&
sink
)
const
override
{
detail
::
try_serialize
(
sink
,
addr_of
(
x_
));
}
void
*
get_mutable
()
override
{
T
*
tmp
=
xs
;
return
reinterpret_cast
<
void
*>
(
tmp
);
std
::
string
stringify
()
const
override
{
return
deep_to_string
(
x_
);
}
const
void
*
get
()
const
override
{
const
T
*
tmp
=
xs
;
return
reinterpret_cast
<
const
void
*>
(
tmp
);
type_erased_value_ptr
copy
()
const
override
{
return
type_erased_value_ptr
{
new
type_erased_value_impl
(
x_
)};
}
void
save
(
serializer
&
sink
)
const
override
{
array_serialize
(
sink
,
const_cast
<
array_type
&>
(
xs
));
}
private:
// -- address-of-member utility ----------------------------------------------
void
load
(
deserializer
&
source
)
override
{
array_serialize
(
source
,
xs
);
template
<
class
U
>
static
inline
U
*
addr_of
(
const
U
&
x
)
{
return
const_cast
<
U
*>
(
&
x
);
}
std
::
string
stringify
()
const
override
{
return
deep_to_string
(
xs
);
template
<
class
U
,
size_t
S
>
static
inline
U
*
addr_of
(
const
U
(
&
x
)[
S
])
{
return
const_cast
<
U
*>
(
static_cast
<
const
U
*>
(
x
));
}
type_erased_value_ptr
copy
()
const
override
{
return
new
type_erased_value_impl
(
xs
);
template
<
class
U
>
static
inline
U
*
addr_of
(
std
::
reference_wrapper
<
U
>&
x
)
{
return
&
x
.
get
();
}
rtti_pair
type
()
const
override
{
auto
nr
=
detail
::
type_nr
<
T
>::
value
;
return
{
nr
,
&
typeid
(
T
)}
;
template
<
class
U
>
static
inline
U
*
addr_of
(
const
std
::
reference_wrapper
<
U
>&
x
)
{
return
&
x
.
get
()
;
}
template
<
class
U
,
size_t
Len
>
static
bool
array_cmp_impl
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
],
std
::
true_type
)
{
for
(
size_t
i
=
0
;
i
<
Len
;
++
i
)
if
(
!
array_cmp
(
lhs
[
i
],
rhs
[
i
]))
return
false
;
return
true
;
}
// -- typeid utility ---------------------------------------------------------
template
<
class
U
,
size_t
Len
>
static
bool
array_cmp_impl
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
],
std
::
false_type
)
{
for
(
size_t
i
=
0
;
i
<
Len
;
++
i
)
if
(
!
detail
::
safe_equal
(
lhs
[
i
],
rhs
[
i
]))
return
false
;
return
true
;
template
<
class
U
>
static
inline
const
std
::
type_info
*
typeid_of
(
U
&
)
{
return
&
typeid
(
U
);
}
template
<
class
U
,
size_t
Len
>
static
bool
array_cmp
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
])
{
std
::
integral_constant
<
bool
,
std
::
is_array
<
U
>::
value
>
token
;
return
array_cmp_impl
(
lhs
,
rhs
,
token
);
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
>
static
void
array_copy_impl
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
],
std
::
true_type
)
{
static
void
array_copy_impl
(
U
(
&
x
)[
Len
],
const
U
(
&
y
)[
Len
],
std
::
true_type
)
{
for
(
size_t
i
=
0
;
i
<
Len
;
++
i
)
array_copy
(
lhs
[
i
],
rhs
[
i
]);
array_copy
(
x
[
i
],
y
[
i
]);
}
template
<
class
U
,
size_t
Len
>
static
void
array_copy_impl
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
],
std
::
false_type
)
{
std
::
copy
(
rhs
,
rhs
+
Len
,
lhs
);
static
void
array_copy_impl
(
U
(
&
x
)[
Len
],
const
U
(
&
y
)[
Len
],
std
::
false_type
)
{
std
::
copy
(
y
,
y
+
Len
,
x
);
}
template
<
class
U
,
size_t
Len
>
static
void
array_copy
(
U
(
&
lhs
)[
Len
],
const
U
(
&
rhs
)[
Len
])
{
std
::
integral_constant
<
bool
,
std
::
is_array
<
U
>::
value
>
token
;
array_copy_impl
(
lhs
,
rhs
,
token
);
}
template
<
class
P
,
class
U
,
size_t
Len
>
static
void
array_serialize_impl
(
P
&
proc
,
U
(
&
ys
)[
Len
],
std
::
true_type
)
{
for
(
auto
&
y
:
ys
)
array_serialize
(
proc
,
y
);
static
void
array_copy
(
U
(
&
x
)[
Len
],
const
U
(
&
y
)[
Len
])
{
std
::
integral_constant
<
bool
,
std
::
is_array
<
U
>::
value
>
token
;
array_copy_impl
(
x
,
y
,
token
);
}
template
<
class
P
,
class
U
,
size_t
Len
>
static
void
array_serialize_impl
(
P
&
proc
,
U
(
&
ys
)[
Len
],
std
::
false_type
)
{
for
(
auto
&
y
:
ys
)
proc
&
y
;
}
// -- data members -----------------------------------------------------------
template
<
class
P
,
class
U
,
size_t
Len
>
static
void
array_serialize
(
P
&
proc
,
U
(
&
ys
)[
Len
])
{
std
::
integral_constant
<
bool
,
std
::
is_array
<
U
>::
value
>
token
;
array_serialize_impl
(
proc
,
ys
,
token
);
}
T
x_
;
};
/// @relates type_erased_value
/// Creates a type-erased value of type `T` from `xs`.
template
<
class
T
,
class
...
Ts
>
type_erased_value_ptr
make_type_erased
(
Ts
&&
...
xs
)
{
type_erased_value_ptr
make_type_erased
_value
(
Ts
&&
...
xs
)
{
type_erased_value_ptr
result
;
result
.
reset
(
new
type_erased_value_impl
<
T
>
(
std
::
forward
<
Ts
>
(
xs
)...));
return
result
;
}
/// @relates type_erased_value
/// Creates a type-erased view for `x`.
template
<
class
T
>
type_erased_value_impl
<
std
::
reference_wrapper
<
T
>>
make_type_erased_view
(
T
&
x
)
{
return
{
std
::
ref
(
x
)};
}
}
// namespace caf
#endif // CAF_TYPE_ERASED_VALUE_HPP
libcaf_core/src/type_erased_tuple.cpp
View file @
f676aa81
...
...
@@ -27,6 +27,29 @@ type_erased_tuple::~type_erased_tuple() {
// nop
}
void
type_erased_tuple
::
load
(
deserializer
&
source
)
{
for
(
size_t
i
=
0
;
i
<
size
();
++
i
)
load
(
i
,
source
);
}
std
::
string
type_erased_tuple
::
stringify
()
const
{
if
(
size
()
==
0
)
return
"()"
;
std
::
string
result
=
"("
;
result
+=
stringify
(
0
);
for
(
size_t
i
=
1
;
i
<
size
();
++
i
)
{
result
+=
", "
;
result
+=
stringify
(
i
);
}
result
+=
')'
;
return
result
;
}
void
type_erased_tuple
::
save
(
serializer
&
sink
)
const
{
for
(
size_t
i
=
0
;
i
<
size
();
++
i
)
save
(
i
,
sink
);
}
bool
type_erased_tuple
::
matches
(
size_t
pos
,
uint16_t
nr
,
const
std
::
type_info
*
ptr
)
const
{
CAF_ASSERT
(
pos
<
size
());
...
...
libcaf_core/src/uniform_type_info_map.cpp
View file @
f676aa81
...
...
@@ -108,7 +108,7 @@ void fill_builtins(builtins& arr, List, size_t pos) {
using
type
=
typename
detail
::
tl_head
<
List
>::
type
;
typename
detail
::
tl_tail
<
List
>::
type
next
;
arr
[
pos
].
first
=
detail
::
numbered_type_names
[
pos
];
arr
[
pos
].
second
=
&
make_type_erased
<
type
>
;
arr
[
pos
].
second
=
&
make_type_erased
_value
<
type
>
;
fill_builtins
(
arr
,
next
,
pos
+
1
);
}
...
...
libcaf_core/test/serialization.cpp
View file @
f676aa81
...
...
@@ -49,8 +49,10 @@
#include "caf/serializer.hpp"
#include "caf/ref_counted.hpp"
#include "caf/deserializer.hpp"
#include "caf/actor_system.hpp"
#include "caf/proxy_registry.hpp"
#include "caf/message_handler.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/primitive_variant.hpp"
#include "caf/binary_serializer.hpp"
#include "caf/binary_deserializer.hpp"
...
...
@@ -141,6 +143,7 @@ struct fixture {
{
4
,
5
,
6
,
7
}
},
};
int
ra
[
3
]
=
{
1
,
2
,
3
};
actor_system
system
;
scoped_execution_unit
context
;
...
...
@@ -171,6 +174,25 @@ struct fixture {
apply
(
bd
,
x
,
xs
...);
}
// serializes `x` and then deserializes and returns the serialized value
template
<
class
T
>
T
roundtrip
(
const
T
&
x
)
{
T
result
;
deserialize
(
serialize
(
x
),
result
);
return
result
;
}
// converts `x` to a message, serialize it, then deserializes it, and
// finally returns unboxed value
template
<
class
T
>
T
msg_roundtrip
(
const
T
&
x
)
{
message
result
;
auto
tmp
=
make_message
(
x
);
deserialize
(
serialize
(
tmp
),
result
);
CAF_REQUIRE
(
result
.
match_elements
<
T
>
());
return
result
.
get_as
<
T
>
(
0
);
}
fixture
()
:
system
(
actor_system_config
{}
.
add_message_type
<
test_enum
>
(
"test_enum"
)
...
...
@@ -269,13 +291,19 @@ CAF_TEST(custom_struct) {
CAF_TEST
(
atoms
)
{
atom_value
x
;
auto
foo
=
atom
(
"foo"
);
CAF_CHECK
(
foo
==
roundtrip
(
foo
));
CAF_CHECK
(
foo
==
msg_roundtrip
(
foo
));
using
bar_atom
=
atom_constant
<
atom
(
"bar"
)
>
;
auto
buf
=
serialize
(
foo
);
deserialize
(
buf
,
x
);
CAF_CHECK
(
x
==
foo
);
buf
=
serialize
(
bar_atom
::
value
);
CAF_CHECK
(
bar_atom
::
value
==
roundtrip
(
atom
(
"bar"
)));
CAF_CHECK
(
bar_atom
::
value
==
msg_roundtrip
(
atom
(
"bar"
)));
}
CAF_TEST
(
raw_arrays
)
{
auto
buf
=
serialize
(
ra
);
int
x
[
3
];
deserialize
(
buf
,
x
);
CAF_CHECK
(
x
==
bar_atom
::
value
);
for
(
auto
i
=
0
;
i
<
3
;
++
i
)
CAF_CHECK
(
ra
[
i
]
==
x
[
i
]);
}
CAF_TEST
(
arrays
)
{
...
...
@@ -292,18 +320,58 @@ CAF_TEST(arrays) {
CAF_TEST
(
empty_non_pods
)
{
test_empty_non_pod
x
;
auto
buf
=
serialize
(
x
);
CAF_REQUIRE
(
buf
.
empty
());
deserialize
(
buf
,
x
);
CAF_CHECK
(
true
);
}
std
::
string
hexstr
(
const
std
::
vector
<
char
>&
buf
)
{
using
namespace
std
;
ostringstream
oss
;
oss
<<
hex
;
oss
.
fill
(
'0'
);
for
(
auto
&
c
:
buf
)
{
oss
.
width
(
2
);
oss
<<
int
{
c
};
}
return
oss
.
str
();
}
CAF_TEST
(
messages
)
{
auto
buf
=
serialize
(
msg
);
// serialize original message which uses tuple_vals internally and
// deserialize into a message which uses type_erased_value pointers
message
x
;
deserialize
(
buf
,
x
);
auto
buf1
=
serialize
(
msg
);
deserialize
(
buf1
,
x
);
CAF_CHECK
(
to_string
(
msg
)
==
to_string
(
x
));
CAF_CHECK
(
is_message
(
x
).
equal
(
i32
,
te
,
str
,
rs
));
// serialize fully dynamic message again (do another roundtrip)
message
y
;
auto
buf2
=
serialize
(
x
);
CAF_CHECK
(
buf1
==
buf2
);
deserialize
(
buf2
,
y
);
CAF_CHECK
(
to_string
(
msg
)
==
to_string
(
y
));
CAF_CHECK
(
is_message
(
y
).
equal
(
i32
,
te
,
str
,
rs
));
}
/*
CAF_TEST(actor_addr_via_message) {
auto testee = system.spawn([] {});
auto addr = actor_cast<actor_addr>(testee);
auto addr_msg = make_message(addr);
// serialize original message which uses tuple_vals and
// deserialize into a message which uses message builder
message x;
deserialize(serialize(addr_msg), x);
CAF_CHECK(to_string(addr_msg) == to_string(x));
CAF_CHECK(is_message(x).equal(addr));
// serialize fully dynamic message again (do another roundtrip)
message y;
deserialize(serialize(x), y);
CAF_CHECK(to_string(addr_msg) == to_string(y));
CAF_CHECK(is_message(y).equal(addr));
}
*/
CAF_TEST
(
multiple_messages
)
{
auto
m
=
make_message
(
rs
,
te
);
auto
buf
=
serialize
(
te
,
m
,
msg
);
...
...
@@ -317,4 +385,34 @@ CAF_TEST(multiple_messages) {
CAF_CHECK
(
is_message
(
m2
).
equal
(
i32
,
te
,
str
,
rs
));
}
CAF_TEST
(
type_erased_value
)
{
auto
buf
=
serialize
(
str
);
type_erased_value_ptr
ptr
{
new
type_erased_value_impl
<
std
::
string
>
};
binary_deserializer
bd
{
&
context
,
buf
.
data
(),
buf
.
size
()};
ptr
->
load
(
bd
);
CAF_CHECK
(
str
==
*
reinterpret_cast
<
const
std
::
string
*>
(
ptr
->
get
()));
}
CAF_TEST
(
type_erased_view
)
{
auto
str_view
=
make_type_erased_view
(
str
);
auto
buf
=
serialize
(
str_view
);
std
::
string
res
;
deserialize
(
buf
,
res
);
CAF_CHECK
(
str
==
res
);
}
CAF_TEST
(
type_erased_tuple
)
{
auto
tview
=
make_type_erased_tuple_view
(
str
,
i32
);
CAF_CHECK
(
to_string
(
tview
)
==
deep_to_string
(
std
::
make_tuple
(
str
,
i32
)));
auto
buf
=
serialize
(
tview
);
CAF_REQUIRE
(
buf
.
size
()
>
0
);
std
::
string
tmp1
;
int32_t
tmp2
;
deserialize
(
buf
,
tmp1
,
tmp2
);
CAF_CHECK
(
tmp1
==
str
);
CAF_CHECK
(
tmp2
==
i32
);
deserialize
(
buf
,
tview
);
CAF_CHECK
(
to_string
(
tview
)
==
deep_to_string
(
std
::
make_tuple
(
str
,
i32
)));
}
CAF_TEST_FIXTURE_SCOPE_END
()
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