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
6a058c4d
Commit
6a058c4d
authored
Sep 10, 2012
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'unstable' of github.com:Neverlord/libcppa into unstable
parents
8f79f160
9e7db021
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
903 additions
and
563 deletions
+903
-563
CMakeLists.txt
CMakeLists.txt
+1
-0
cppa.files
cppa.files
+3
-0
cppa/actor.hpp
cppa/actor.hpp
+5
-0
cppa/cppa.hpp
cppa/cppa.hpp
+3
-1
cppa/detail/decorated_names_map.hpp
cppa/detail/decorated_names_map.hpp
+57
-0
cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/default_uniform_type_info_impl.hpp
+1
-4
cppa/detail/ipv4_acceptor.hpp
cppa/detail/ipv4_acceptor.hpp
+2
-1
cppa/detail/pair_member.hpp
cppa/detail/pair_member.hpp
+53
-8
cppa/detail/singleton_manager.hpp
cppa/detail/singleton_manager.hpp
+3
-0
cppa/group.hpp
cppa/group.hpp
+3
-2
cppa/uniform_type_info.hpp
cppa/uniform_type_info.hpp
+14
-0
examples/announce_example_5.cpp
examples/announce_example_5.cpp
+3
-8
examples/group_chat.cpp
examples/group_chat.cpp
+98
-143
examples/group_server.cpp
examples/group_server.cpp
+13
-38
examples/type_plugins.hpp
examples/type_plugins.hpp
+30
-0
src/decorated_names_map.cpp
src/decorated_names_map.cpp
+125
-0
src/group.cpp
src/group.cpp
+2
-2
src/ipv4_acceptor.cpp
src/ipv4_acceptor.cpp
+10
-2
src/middleman.cpp
src/middleman.cpp
+46
-6
src/self.cpp
src/self.cpp
+8
-0
src/singleton_manager.cpp
src/singleton_manager.cpp
+8
-0
src/string_serialization.cpp
src/string_serialization.cpp
+88
-61
src/thread_mapped_actor.cpp
src/thread_mapped_actor.cpp
+1
-1
src/to_uniform_name.cpp
src/to_uniform_name.cpp
+139
-155
src/unicast_network.cpp
src/unicast_network.cpp
+10
-6
src/uniform_type_info.cpp
src/uniform_type_info.cpp
+90
-96
unit_testing/test__remote_actor.cpp
unit_testing/test__remote_actor.cpp
+1
-1
unit_testing/test__serialization.cpp
unit_testing/test__serialization.cpp
+86
-28
No files found.
CMakeLists.txt
View file @
6a058c4d
...
...
@@ -131,6 +131,7 @@ set(LIBCPPA_SRC
src/uniform_type_info.cpp
src/yield_interface.cpp
src/context_switching_actor.cpp
src/decorated_names_map.cpp
)
set
(
boost_context third_party/boost_context
)
...
...
cppa.files
View file @
6a058c4d
...
...
@@ -272,3 +272,6 @@ examples/group_chat.cpp
cppa/opt.hpp
src/opt.cpp
cppa/detail/opt_impls.hpp
examples/type_plugins.hpp
cppa/detail/decorated_names_map.hpp
src/decorated_names_map.cpp
cppa/actor.hpp
View file @
6a058c4d
...
...
@@ -202,6 +202,11 @@ class actor : public channel {
*/
typedef
intrusive_ptr
<
actor
>
actor_ptr
;
class
self_type
;
bool
operator
==
(
const
actor_ptr
&
lhs
,
const
self_type
&
rhs
);
bool
operator
!=
(
const
self_type
&
lhs
,
const
actor_ptr
&
rhs
);
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
...
...
cppa/cppa.hpp
View file @
6a058c4d
...
...
@@ -751,9 +751,11 @@ inline void await_all_others_done() {
* The connection is automatically closed if the lifetime of @p whom ends.
* @param whom Actor that should be published at @p port.
* @param port Unused TCP port.
* @param addr The IP address to listen to, or @p INADDR_ANY if @p addr is
* @p nullptr.
* @throws bind_failure
*/
void
publish
(
actor_ptr
whom
,
std
::
uint16_t
port
);
void
publish
(
actor_ptr
whom
,
std
::
uint16_t
port
,
const
char
*
addr
=
nullptr
);
/**
* @brief Publishes @p whom using @p acceptor to handle incoming connections.
...
...
cppa/detail/decorated_names_map.hpp
0 → 100644
View file @
6a058c4d
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_DECORATED_NAMES_MAP_HPP
#define CPPA_DECORATED_NAMES_MAP_HPP
#include <map>
#include <string>
namespace
cppa
{
namespace
detail
{
class
decorated_names_map
{
public:
decorated_names_map
();
// returns either a decorated version of @p demangled_name or
// @p demangled_name itself
const
std
::
string
&
decorate
(
const
std
::
string
&
demangled_name
)
const
;
private:
std
::
map
<
std
::
string
,
std
::
string
>
m_map
;
};
}
}
// namespace cppa::detail
#endif // DECORATED_NAMES_MAP_HPP
cppa/detail/default_uniform_type_info_impl.hpp
View file @
6a058c4d
...
...
@@ -319,10 +319,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
std
::
string
cname
=
d
->
seek_object
();
if
(
cname
!=
this
->
name
())
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
this
->
assert_type_name
(
d
);
d
->
begin_object
(
this
->
name
());
for
(
auto
&
m
:
m_members
)
{
m
.
deserialize
(
obj
,
d
);
...
...
cppa/detail/ipv4_acceptor.hpp
View file @
6a058c4d
...
...
@@ -42,7 +42,8 @@ class ipv4_acceptor : public util::acceptor {
public:
static
std
::
unique_ptr
<
util
::
acceptor
>
create
(
std
::
uint16_t
port
);
static
std
::
unique_ptr
<
util
::
acceptor
>
create
(
std
::
uint16_t
port
,
const
char
*
addr
);
~
ipv4_acceptor
();
...
...
cppa/detail/pair_member.hpp
View file @
6a058c4d
...
...
@@ -36,24 +36,24 @@
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/detail/type_to_ptype.hpp"
#include "cppa/util/is_builtin.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/type_to_ptype.hpp"
namespace
cppa
{
namespace
detail
{
template
<
typename
T1
,
typename
T2
>
class
pair_member
:
public
util
::
abstract_uniform_type_info
<
std
::
pair
<
T1
,
T2
>>
{
template
<
typename
T1
,
typename
T2
,
bool
PrimitiveTypes
>
// default: true
struct
pair_member_impl
{
static
constexpr
primitive_type
ptype1
=
type_to_ptype
<
T1
>::
ptype
;
static
constexpr
primitive_type
ptype2
=
type_to_ptype
<
T2
>::
ptype
;
static_assert
(
ptype1
!=
pt_null
,
"T1 is not a primitive type"
);
static_assert
(
ptype2
!=
pt_null
,
"T2 is not a primitive type"
);
typedef
std
::
pair
<
T1
,
T2
>
pair_type
;
public:
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
auto
&
p
=
*
reinterpret_cast
<
const
pair_type
*>
(
obj
);
primitive_variant
values
[
2
]
=
{
p
.
first
,
p
.
second
};
...
...
@@ -71,6 +71,51 @@ class pair_member : public util::abstract_uniform_type_info<std::pair<T1,T2>> {
};
template
<
typename
T1
,
typename
T2
>
struct
pair_member_impl
<
T1
,
T2
,
false
>
{
typedef
std
::
pair
<
T1
,
T2
>
pair_type
;
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
auto
&
arr
=
static_types_array
<
T1
,
T2
>::
arr
;
auto
&
p
=
*
reinterpret_cast
<
const
pair_type
*>
(
obj
);
arr
[
0
]
->
serialize
(
&
p
.
first
,
s
);
arr
[
1
]
->
serialize
(
&
p
.
second
,
s
);
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
auto
&
arr
=
static_types_array
<
T1
,
T2
>::
arr
;
auto
&
p
=
*
reinterpret_cast
<
pair_type
*>
(
obj
);
arr
[
0
]
->
deserialize
(
&
p
.
first
,
d
);
arr
[
1
]
->
deserialize
(
&
p
.
second
,
d
);
}
};
template
<
typename
T1
,
typename
T2
>
class
pair_member
:
public
util
::
abstract_uniform_type_info
<
std
::
pair
<
T1
,
T2
>>
{
static_assert
(
util
::
is_builtin
<
T1
>::
value
,
"T1 is not a builtin type"
);
static_assert
(
util
::
is_builtin
<
T1
>::
value
,
"T2 is not a builtin type"
);
public:
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
impl
.
serialize
(
obj
,
s
);
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
impl
.
deserialize
(
obj
,
d
);
}
private:
pair_member_impl
<
T1
,
T2
,
util
::
is_primitive
<
T1
>::
value
&&
util
::
is_primitive
<
T2
>::
value
>
impl
;
};
}
}
// namespace cppa::detail
#endif // CPPA_PAIR_MEMBER_HPP
cppa/detail/singleton_manager.hpp
View file @
6a058c4d
...
...
@@ -45,6 +45,7 @@ class group_manager;
class
abstract_tuple
;
class
actor_registry
;
class
network_manager
;
class
decorated_names_map
;
class
uniform_type_info_map
;
class
singleton_manager
{
...
...
@@ -70,6 +71,8 @@ class singleton_manager {
static
empty_tuple
*
get_empty_tuple
();
static
decorated_names_map
*
get_decorated_names_map
();
};
}
}
// namespace cppa::detail
...
...
cppa/group.hpp
View file @
6a058c4d
...
...
@@ -195,11 +195,12 @@ class group : public channel {
typedef
intrusive_ptr
<
group
>
group_ptr
;
/**
* @brief Makes *all* local groups accessible via network on @p port.
* @brief Makes *all* local groups accessible via network on address @p addr
* and @p port.
* @throws bind_failure
* @throws network_error
*/
void
publish_local_groups_at
(
std
::
uint16_t
port
);
void
publish_local_groups_at
(
std
::
uint16_t
port
,
const
char
*
addr
=
nullptr
);
}
// namespace cppa
...
...
cppa/uniform_type_info.hpp
View file @
6a058c4d
...
...
@@ -234,8 +234,22 @@ class uniform_type_info {
*/
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
=
0
;
/**
* @brief Checks wheter <tt>src->seek_object()</tt>
* returns @p tname and throws an exception if not.
* @throws std::logic_error
*/
static
void
assert_type_name
(
deserializer
*
src
,
const
std
::
string
&
tname
);
protected:
/**
* @brief Checks wheter <tt>src->seek_object()</tt>
* returns {@link name()} and throws an exception if not.
* @throws std::logic_error
*/
void
assert_type_name
(
deserializer
*
src
)
const
;
uniform_type_info
(
const
std
::
string
&
uniform_name
);
/**
...
...
examples/announce_example_5.cpp
View file @
6a058c4d
...
...
@@ -100,18 +100,13 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> {
}
void
deserialize
(
void
*
ptr
,
deserializer
*
source
)
const
{
// seek_object() gets the uniform name of the next object in the
// stream without modifying the deserializer
std
::
string
cname
=
source
->
seek_object
();
// this name has to be our type name
if
(
cname
!=
name
())
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
// throws an exception if the next object in source is not a tree
assert_type_name
(
source
);
// ptr is guaranteed to be a pointer of type tree
auto
tree_ptr
=
reinterpret_cast
<
tree
*>
(
ptr
);
tree_ptr
->
root
.
children
.
clear
();
// workflow is analogous to serialize: begin_object() ... end_object()
source
->
begin_object
(
cname
);
source
->
begin_object
(
name
()
);
// recursively deserialize nodes, beginning with root
deserialize_node
(
tree_ptr
->
root
,
source
);
source
->
end_object
();
...
...
examples/group_chat.cpp
View file @
6a058c4d
#include <set>
#include <map>
#include <vector>
#include <dlfcn.h>
#include <iostream>
#include <sstream>
#include <time.h>
#include <cstdlib>
#include "cppa/opt.hpp"
#include "cppa/cppa.hpp"
#include "type_plugins.hpp"
using
namespace
std
;
using
namespace
cppa
;
using
namespace
cppa
::
placeholders
;
auto
on_opt
(
char
short_opt
,
const
char
*
long_opt
)
->
decltype
(
on
(
""
,
val
<
string
>
)
||
on
(
function
<
option
<
string
>
(
const
string
&
)
>
()))
{
const
char
short_flag_arr
[]
=
{
'-'
,
short_opt
,
'\0'
};
const
char
*
lhs_str
=
short_flag_arr
;
string
prefix
=
"--"
;
prefix
+=
long_opt
;
prefix
+=
"="
;
function
<
option
<
string
>
(
const
string
&
)
>
kvp
=
[
prefix
](
const
string
&
input
)
->
option
<
string
>
{
if
(
input
.
compare
(
0
,
prefix
.
size
(),
prefix
)
==
0
// accept '-key=' as well
||
input
.
compare
(
1
,
prefix
.
size
(),
prefix
)
==
0
)
{
return
input
.
substr
(
prefix
.
size
());
}
return
{};
};
return
on
(
lhs_str
,
val
<
string
>
)
||
on
(
kvp
);
struct
line
{
string
str
;
};
istream
&
operator
>>
(
istream
&
is
,
line
&
l
)
{
getline
(
is
,
l
.
str
);
return
is
;
}
auto
on_void_opt
(
char
short_opt
,
const
char
*
long_opt
)
->
decltype
(
on
<
string
>
().
when
(
cppa
::
placeholders
::
_x1
.
in
(
vector
<
string
>
())))
{
const
char
short_flag_arr
[]
=
{
'-'
,
short_opt
,
'\0'
};
vector
<
string
>
opt_strs
=
{
short_flag_arr
};
opt_strs
.
push_back
(
string
(
"-"
)
+
long_opt
);
string
str
=
"-"
;
str
+=
opt_strs
.
back
();
opt_strs
.
push_back
(
std
::
move
(
str
));
return
on
<
string
>
().
when
(
cppa
::
placeholders
::
_x1
.
in
(
opt_strs
));
any_tuple
s_last_line
;
any_tuple
split_line
(
const
line
&
l
)
{
vector
<
string
>
result
;
stringstream
strs
(
l
.
str
);
string
tmp
;
while
(
getline
(
strs
,
tmp
,
' '
))
{
if
(
!
tmp
.
empty
())
result
.
push_back
(
std
::
move
(
tmp
));
}
s_last_line
=
any_tuple
::
view
(
std
::
move
(
result
));
return
s_last_line
;
}
class
client
:
public
event_based_actor
{
string
m_username
;
actor_ptr
m_printer
;
public:
client
(
const
string
&
name
,
actor_ptr
printer
)
:
m_name
(
name
),
m_printer
(
printer
)
{
}
protected:
void
init
()
{
become
(
// local commands
on
(
atom
(
"broadcast"
),
arg_match
)
>>
[
=
](
const
string
&
message
)
{
for
(
auto
&
dest
:
joined_groups
())
{
send
(
dest
,
m_
user
name
+
": "
+
message
);
send
(
dest
,
m_name
+
": "
+
message
);
}
},
on
(
atom
(
"join"
),
arg_match
)
>>
[
=
](
const
group_ptr
&
what
)
{
...
...
@@ -62,6 +62,7 @@ class client : public event_based_actor {
}
},
on
(
atom
(
"quit"
))
>>
[
=
]
{
// ignore quit messages from remote actors
auto
s
=
self
->
last_sender
();
if
(
s
->
is_proxy
())
{
reply
(
"nice try"
);
...
...
@@ -75,14 +76,16 @@ class client : public event_based_actor {
if
(
last_sender
()
!=
this
)
forward_to
(
m_printer
);
},
others
()
>>
[
=
]()
{
send
(
m_printer
,
string
(
"[!!!] unexpected message: '"
)
+
to_string
(
last_dequeued
()));
send
(
m_printer
,
"*** unexpected message: '"
+
to_string
(
last_dequeued
()));
}
);
}
p
ublic
:
p
rivate
:
client
(
const
string
&
username
,
actor_ptr
printer
)
:
m_username
(
username
),
m_printer
(
printer
)
{
}
string
m_name
;
actor_ptr
m_printer
;
};
...
...
@@ -93,141 +96,93 @@ class print_actor : public event_based_actor {
self
->
quit
();
},
on_arg_match
>>
[](
const
string
&
str
)
{
cout
<<
(
str
+
"
\n
"
)
;
cout
<<
str
<<
endl
;
}
);
}
};
inline
vector
<
std
::
string
>
split
(
const
string
&
str
,
char
delim
)
{
vector
<
std
::
string
>
result
;
stringstream
strs
{
str
};
string
tmp
;
while
(
std
::
getline
(
strs
,
tmp
,
delim
))
result
.
push_back
(
tmp
);
return
result
;
}
template
<
typename
Iterator
>
inline
std
::
string
join
(
Iterator
first
,
Iterator
last
,
char
delim
)
{
std
::
string
result
;
if
(
first
!=
last
)
{
result
+=
*
first
++
;
for
(;
first
!=
last
;
++
first
)
{
result
+=
delim
;
result
+=
*
first
++
;
}
}
return
result
;
}
inline
std
::
string
join
(
const
vector
<
string
>&
vec
,
char
delim
)
{
return
join
(
begin
(
vec
),
end
(
vec
),
delim
);
}
template
<
typename
T
>
auto
conv
(
const
string
&
str
)
->
option
<
T
>
{
T
result
;
if
(
istringstream
(
str
)
>>
result
)
return
result
;
return
{};
}
void
print_usage
(
actor_ptr
printer
)
{
send
(
printer
,
"Usage: group_chat --type=<server|client>
\n
--type, -t
\t\t
can be: server, s, client, c
\n
--name, -n
\t\t
username (only needed for client)
\n
--host, -h
\t\t
hostname (only needed for client)
\n
--port, -p
\t\t
port for server/client"
);
}
std
::
function
<
option
<
string
>
(
const
string
&
)
>
get_extractor
(
const
string
&
identifier
)
{
auto
tmp
=
[
&
](
const
string
&
kvp
)
->
option
<
string
>
{
auto
vec
=
split
(
kvp
,
'='
);
if
(
vec
.
size
()
==
2
)
{
if
(
vec
.
front
()
==
"--"
+
identifier
)
{
return
vec
.
back
();
}
}
return
{};
};
return
tmp
;
}
auto
main
(
int
argc
,
char
*
argv
[])
->
int
{
cout
.
unsetf
(
std
::
ios_base
::
unitbuf
);
auto
printer
=
spawn
<
print_actor
>
();
// enables this client to print user-defined types
// without changing this source code
exec_plugin
();
string
name
;
bool
args_valid
=
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
on_opt
(
'n'
,
"name"
)
>>
[
&
](
const
string
&
input
)
->
bool
{
if
(
!
name
.
empty
())
{
cout
<<
"name already set to "
<<
name
<<
endl
;
return
false
;
}
name
=
input
;
return
true
;
}
vector
<
string
>
group_ids
;
options_description
desc
;
bool
args_valid
=
argc
>
1
&&
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
on_opt
(
'n'
,
"name"
,
&
desc
,
"set name"
)
>>
rd_arg
(
name
),
on_opt
(
'g'
,
"group"
,
&
desc
,
"join group <arg>"
)
>>
add_arg
(
group_ids
),
on_vopt
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
);
if
(
!
args_valid
)
{
print_usage
(
printer
);
send
(
printer
,
atom
(
"quit"
));
await_all_others_done
();
shutdown
();
return
0
;
}
if
(
!
args_valid
)
print_desc_and_exit
(
&
desc
)();
auto
printer
=
spawn
<
print_actor
>
();
while
(
name
.
empty
())
{
send
(
printer
,
"
So
what is your name for chatting?"
);
send
(
printer
,
"
***
what is your name for chatting?"
);
if
(
!
getline
(
cin
,
name
))
return
1
;
}
send
(
printer
,
"
S
tarting client."
);
send
(
printer
,
"
*** s
tarting client."
);
auto
client_actor
=
spawn
<
client
>
(
name
,
printer
);
auto
get_command
=
[
&
]()
->
bool
{
string
input
;
bool
done
=
false
;
getline
(
cin
,
input
);
if
(
input
.
size
()
>
0
)
{
if
(
input
.
front
()
==
'/'
)
{
input
.
erase
(
input
.
begin
());
vector
<
string
>
values
=
split
(
input
,
' '
);
match
(
values
)
(
on
(
"send"
,
val
<
string
>
,
any_vals
)
>>
[
&
](
const
string
&
groupname
)
{
if
(
values
.
size
()
<
3
)
{
send
(
printer
,
"no message to send"
);
}
else
{
send
(
client_actor
,
atom
(
"send"
),
groupname
,
join
(
begin
(
values
)
+
2
,
end
(
values
),
' '
));
}
},
on
(
"join"
,
arg_match
)
>>
[
&
](
const
string
&
mod
,
const
string
&
id
)
{
group_ptr
g
;
try
{
g
=
group
::
get
(
mod
,
id
);
send
(
client_actor
,
atom
(
"join"
),
g
);
}
catch
(
exception
&
e
)
{
send
(
printer
,
string
(
"exception: "
)
+
e
.
what
());
}
},
on
(
"quit"
)
>>
[
&
]
{
done
=
true
;
},
others
()
>>
[
&
]
{
send
(
printer
,
"available commands:
\n
/connect HOST PORT
\n
/join GROUPNAME
\n
/join hamcast URI
\n
/send GROUPNAME MESSAGE
\n
/quit"
);
}
);
// evaluate group parameters
for
(
auto
&
gid
:
group_ids
)
{
auto
p
=
gid
.
find
(
':'
);
if
(
p
==
std
::
string
::
npos
)
{
cerr
<<
"*** error parsing argument "
<<
gid
<<
", expected format: <module_name>:<group_id>"
;
}
else
{
try
{
auto
g
=
group
::
get
(
gid
.
substr
(
0
,
p
),
gid
.
substr
(
p
+
1
));
send
(
client_actor
,
atom
(
"join"
),
g
);
}
else
{
send
(
client_actor
,
atom
(
"broadcast"
),
input
);
catch
(
exception
&
e
)
{
ostringstream
err
;
err
<<
"*** exception: group::get(
\"
"
<<
gid
.
substr
(
0
,
p
)
<<
"
\"
,
\"
"
<<
gid
.
substr
(
p
+
1
)
<<
"
\"
) failed, what = "
<<
e
.
what
()
<<
endl
;
send
(
printer
,
err
.
str
());
}
}
return
!
done
;
};
while
(
get_command
())
{
}
send
(
client_actor
,
atom
(
"quit"
));
}
istream_iterator
<
line
>
lines
(
cin
);
istream_iterator
<
line
>
eof
;
match_each
(
lines
,
eof
,
split_line
)
(
on
(
"/join"
,
arg_match
)
>>
[
&
](
const
string
&
mod
,
const
string
&
id
)
{
try
{
send
(
client_actor
,
atom
(
"join"
),
group
::
get
(
mod
,
id
));
}
catch
(
exception
&
e
)
{
send
(
printer
,
string
(
"*** exception: "
)
+
e
.
what
());
}
},
on
(
"/quit"
)
>>
[
&
]
{
close
(
0
);
// close STDIN
},
on
<
string
,
anything
>
().
when
(
_x1
.
starts_with
(
"/"
))
>>
[
&
]
{
send
(
printer
,
"*** available commands:
\n
"
"/join MODULE GROUP
\n
"
"/quit"
);
},
others
()
>>
[
&
]
{
if
(
s_last_line
.
size
()
>
0
)
{
string
msg
=
s_last_line
.
get_as
<
string
>
(
0
);
for
(
size_t
i
=
1
;
i
<
s_last_line
.
size
();
++
i
)
{
msg
+=
" "
;
msg
+=
s_last_line
.
get_as
<
string
>
(
i
);
}
send
(
client_actor
,
atom
(
"broadcast"
),
msg
);
}
}
);
send
(
client_actor
,
atom
(
"quit"
));
send
(
printer
,
atom
(
"quit"
));
await_all_others_done
();
shutdown
();
...
...
examples/group_server.cpp
View file @
6a058c4d
#include <string>
#include <dlfcn.h>
#include <sstream>
#include <iostream>
#include "cppa/opt.hpp"
#include "cppa/cppa.hpp"
#include "type_plugins.hpp"
using
namespace
std
;
using
namespace
cppa
;
auto
on_opt
(
char
short_opt
,
const
char
*
long_opt
)
->
decltype
(
on
(
""
,
val
<
string
>
)
||
on
(
function
<
option
<
string
>
(
const
string
&
)
>
()))
{
const
char
short_flag_arr
[]
=
{
'-'
,
short_opt
,
'\0'
};
const
char
*
lhs_str
=
short_flag_arr
;
string
prefix
=
"--"
;
prefix
+=
long_opt
;
prefix
+=
"="
;
function
<
option
<
string
>
(
const
string
&
)
>
kvp
=
[
prefix
](
const
string
&
input
)
->
option
<
string
>
{
if
(
input
.
compare
(
0
,
prefix
.
size
(),
prefix
)
==
0
// accept '-key=' as well
||
input
.
compare
(
1
,
prefix
.
size
(),
prefix
)
==
0
)
{
return
input
.
substr
(
prefix
.
size
());
}
return
{};
};
return
on
(
lhs_str
,
val
<
string
>
)
||
on
(
kvp
);
}
auto
on_void_opt
(
char
short_opt
,
const
char
*
long_opt
)
->
decltype
(
on
<
string
>
().
when
(
cppa
::
placeholders
::
_x1
.
in
(
vector
<
string
>
())))
{
const
char
short_flag_arr
[]
=
{
'-'
,
short_opt
,
'\0'
};
vector
<
string
>
opt_strs
=
{
short_flag_arr
};
opt_strs
.
push_back
(
string
(
"-"
)
+
long_opt
);
string
str
=
"-"
;
str
+=
opt_strs
.
back
();
opt_strs
.
push_back
(
std
::
move
(
str
));
return
on
<
string
>
().
when
(
cppa
::
placeholders
::
_x1
.
in
(
opt_strs
));
}
int
main
(
int
argc
,
char
**
argv
)
{
uint16_t
port
;
// enables this server to be used with user-defined types
// without changing this source code
exec_plugin
();
uint16_t
port
=
0
;
options_description
desc
;
bool
args_valid
=
argc
>
1
&&
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
on_opt
(
'p'
,
"port"
)
>>
[
&
](
const
string
&
arg
)
->
bool
{
if
(
!
(
istringstream
(
arg
)
>>
port
))
{
cout
<<
"
\"
"
<<
arg
<<
"
\"
is not a valid port"
<<
endl
;
return
false
;
}
return
true
;
}
on_opt
(
'p'
,
"port"
,
&
desc
,
"set port"
)
>>
rd_arg
(
port
),
on_vopt
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
);
if
(
port
<=
1024
)
{
cout
<<
"no port > 1024 given"
<<
endl
;
...
...
@@ -54,9 +30,8 @@ int main(int argc, char** argv) {
string
line
;
while
(
getline
(
cin
,
line
))
{
if
(
line
==
"quit"
)
return
0
;
else
{
cout
<<
"illegal command"
<<
endl
;
}
else
cout
<<
"illegal command"
<<
endl
;
}
shutdown
();
return
0
;
}
examples/type_plugins.hpp
0 → 100644
View file @
6a058c4d
#ifndef TYPE_PLUGINS_HPP
#define TYPE_PLUGINS_HPP
#include <dlfcn.h>
#include <iostream>
#include "cppa/cppa.hpp"
inline
void
exec_plugin
()
{
using
namespace
std
;
using
namespace
cppa
;
// user-defined types can be announced by a plugin
void
*
handle
=
dlopen
(
"plugin.dylib"
,
RTLD_NOW
);
// macos
if
(
!
handle
)
handle
=
dlopen
(
"plugin.so"
,
RTLD_NOW
);
// linux
if
(
handle
)
{
auto
before
=
uniform_type_info
::
instances
();
cout
<<
"found a plugin, call exec_plugin()"
<<
endl
;
auto
fun
=
(
void
(
*
)())
dlsym
(
handle
,
"exec_plugin"
);
if
(
fun
)
{
fun
();
cout
<<
"the plugin announced the following types:"
<<
endl
;
for
(
auto
inf
:
uniform_type_info
::
instances
())
{
if
(
count
(
begin
(
before
),
end
(
before
),
inf
)
==
0
)
{
cout
<<
inf
->
name
()
<<
endl
;
}
}
}
}
}
#endif // TYPE_PLUGINS_HPP
src/decorated_names_map.cpp
0 → 100644
View file @
6a058c4d
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include <limits>
#include "cppa/detail/demangle.hpp"
#include "cppa/detail/decorated_names_map.hpp"
using
namespace
std
;
namespace
{
using
namespace
cppa
;
using
namespace
cppa
::
detail
;
constexpr
const
char
*
mapped_int_names
[][
2
]
=
{
{
nullptr
,
nullptr
},
// sizeof 0-> invalid
{
"@i8"
,
"@u8"
},
// sizeof 1 -> signed / unsigned int8
{
"@i16"
,
"@u16"
},
// sizeof 2 -> signed / unsigned int16
{
nullptr
,
nullptr
},
// sizeof 3-> invalid
{
"@i32"
,
"@u32"
},
// sizeof 4 -> signed / unsigned int32
{
nullptr
,
nullptr
},
// sizeof 5-> invalid
{
nullptr
,
nullptr
},
// sizeof 6-> invalid
{
nullptr
,
nullptr
},
// sizeof 7-> invalid
{
"@i64"
,
"@u64"
}
// sizeof 8 -> signed / unsigned int64
};
template
<
typename
T
>
constexpr
size_t
sign_index
()
{
static_assert
(
numeric_limits
<
T
>::
is_integer
,
"T is not an integer"
);
return
numeric_limits
<
T
>::
is_signed
?
0
:
1
;
}
template
<
typename
T
>
inline
string
demangled
()
{
return
demangle
(
typeid
(
T
));
}
template
<
typename
T
>
constexpr
const
char
*
mapped_int_name
()
{
return
mapped_int_names
[
sizeof
(
T
)][
sign_index
<
T
>
()];
}
template
<
typename
T
>
struct
is_signed
:
integral_constant
<
bool
,
numeric_limits
<
T
>::
is_signed
>
{
};
}
// namespace <anonymous>
namespace
cppa
{
namespace
detail
{
decorated_names_map
::
decorated_names_map
()
{
map
<
string
,
string
>
tmp
=
{
// integer types
{
demangled
<
char
>
(),
mapped_int_name
<
char
>
()
},
{
demangled
<
signed
char
>
(),
mapped_int_name
<
signed
char
>
()
},
{
demangled
<
unsigned
char
>
(),
mapped_int_name
<
unsigned
char
>
()
},
{
demangled
<
short
>
(),
mapped_int_name
<
short
>
()
},
{
demangled
<
signed
short
>
(),
mapped_int_name
<
signed
short
>
()
},
{
demangled
<
unsigned
short
>
(),
mapped_int_name
<
unsigned
short
>
()
},
{
demangled
<
short
int
>
(),
mapped_int_name
<
short
int
>
()
},
{
demangled
<
signed
short
int
>
(),
mapped_int_name
<
signed
short
int
>
()
},
{
demangled
<
unsigned
short
int
>
(),
mapped_int_name
<
unsigned
short
int
>
()},
{
demangled
<
int
>
(),
mapped_int_name
<
int
>
()
},
{
demangled
<
signed
int
>
(),
mapped_int_name
<
signed
int
>
()
},
{
demangled
<
unsigned
int
>
(),
mapped_int_name
<
unsigned
int
>
()
},
{
demangled
<
long
int
>
(),
mapped_int_name
<
long
int
>
()
},
{
demangled
<
signed
long
int
>
(),
mapped_int_name
<
signed
long
int
>
()
},
{
demangled
<
unsigned
long
int
>
(),
mapped_int_name
<
unsigned
long
int
>
()
},
{
demangled
<
long
>
(),
mapped_int_name
<
long
>
()
},
{
demangled
<
signed
long
>
(),
mapped_int_name
<
signed
long
>
()
},
{
demangled
<
unsigned
long
>
(),
mapped_int_name
<
unsigned
long
>
()
},
{
demangled
<
long
long
>
(),
mapped_int_name
<
long
long
>
()
},
{
demangled
<
signed
long
long
>
(),
mapped_int_name
<
signed
long
long
>
()
},
{
demangled
<
unsigned
long
long
>
(),
mapped_int_name
<
unsigned
long
long
>
()},
{
demangled
<
char16_t
>
(),
mapped_int_name
<
char16_t
>
()
},
{
demangled
<
char32_t
>
(),
mapped_int_name
<
char32_t
>
()
},
{
"cppa::atom_value"
,
"@atom"
},
{
"cppa::any_tuple"
,
"@<>"
},
{
"cppa::detail::addressed_message"
,
"@msg"
},
{
"cppa::intrusive_ptr<cppa::actor>"
,
"@actor"
},
{
"cppa::intrusive_ptr<cppa::group>"
,
"@group"
},
{
"cppa::intrusive_ptr<cppa::channel>"
,
"@channel"
},
{
"cppa::intrusive_ptr<cppa::process_information>"
,
"@process_info"
},
{
"std::basic_string<@i8,std::char_traits<@i8>,std::allocator<@i8>>"
,
"@str"
},
{
"std::basic_string<@u16,std::char_traits<@u16>,std::allocator<@u16>>"
,
"@u16str"
},
{
"std::basic_string<@u32,std::char_traits<@u32>,std::allocator<@u32>>"
,
"@u32str"
},
{
"std::string"
,
"@str"
},
// GCC
{
"cppa::util::void_type"
,
"@0"
}
};
m_map
=
move
(
tmp
);
}
const
string
&
decorated_names_map
::
decorate
(
const
string
&
what
)
const
{
auto
i
=
m_map
.
find
(
what
);
return
(
i
!=
m_map
.
end
())
?
i
->
second
:
what
;
}
}
}
// namespace cppa::detail
src/group.cpp
View file @
6a058c4d
...
...
@@ -107,10 +107,10 @@ struct group_nameserver : event_based_actor {
}
};
void
publish_local_groups_at
(
std
::
uint16_t
port
)
{
void
publish_local_groups_at
(
std
::
uint16_t
port
,
const
char
*
addr
)
{
auto
gn
=
spawn_hidden
<
group_nameserver
>
();
try
{
publish
(
gn
,
port
);
publish
(
gn
,
port
,
addr
);
}
catch
(
std
::
exception
&
)
{
gn
->
enqueue
(
nullptr
,
make_any_tuple
(
atom
(
"SHUTDOWN"
)));
...
...
src/ipv4_acceptor.cpp
View file @
6a058c4d
...
...
@@ -42,6 +42,7 @@
#else
# include <netdb.h>
# include <unistd.h>
# include <arpa/inet.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
...
...
@@ -97,7 +98,8 @@ bool accept_impl(util::io_stream_ptr_pair& result, native_socket_type fd, bool n
ipv4_acceptor
::
ipv4_acceptor
(
native_socket_type
fd
,
bool
nonblocking
)
:
m_fd
(
fd
),
m_is_nonblocking
(
nonblocking
)
{
}
std
::
unique_ptr
<
util
::
acceptor
>
ipv4_acceptor
::
create
(
std
::
uint16_t
port
)
{
std
::
unique_ptr
<
util
::
acceptor
>
ipv4_acceptor
::
create
(
std
::
uint16_t
port
,
const
char
*
addr
)
{
native_socket_type
sockfd
;
sockfd
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
sockfd
==
invalid_socket
)
{
...
...
@@ -112,7 +114,13 @@ std::unique_ptr<util::acceptor> ipv4_acceptor::create(std::uint16_t port) {
struct
sockaddr_in
serv_addr
;
memset
((
char
*
)
&
serv_addr
,
0
,
sizeof
(
serv_addr
));
serv_addr
.
sin_family
=
AF_INET
;
serv_addr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
if
(
!
addr
)
{
serv_addr
.
sin_addr
.
s_addr
=
INADDR_ANY
;
}
else
if
(
inet_pton
(
AF_INET
,
addr
,
&
serv_addr
.
sin_addr
)
<=
0
)
{
throw
network_error
(
"invalid IPv4 address"
);
}
serv_addr
.
sin_port
=
htons
(
port
);
if
(
bind
(
sockfd
,
(
struct
sockaddr
*
)
&
serv_addr
,
sizeof
(
serv_addr
))
<
0
)
{
throw
bind_failure
(
errno
);
...
...
src/middleman.cpp
View file @
6a058c4d
...
...
@@ -58,6 +58,9 @@
using
namespace
std
;
//#define VERBOSE_MIDDLEMAN
#ifdef VERBOSE_MIDDLEMAN
#define DEBUG(arg) { \
ostringstream oss; \
oss << "[process id: " \
...
...
@@ -65,9 +68,9 @@ using namespace std;
<< "] " << arg << endl; \
cout << oss.str(); \
} (void) 0
#undef DEBUG
#else
#define DEBUG(unused) ((void) 0)
#endif
namespace
cppa
{
namespace
detail
{
...
...
@@ -235,13 +238,15 @@ class peer_connection : public network_channel {
bool
continue_reading
();
bool
continue_writing
()
{
DEBUG
(
"peer_connection::continue_writing"
);
DEBUG
(
"peer_connection::continue_writing, try to write "
<<
m_wr_buf
.
size
()
<<
" bytes"
);
if
(
has_unwritten_data
())
{
size_t
written
;
written
=
m_ostream
->
write_some
(
m_wr_buf
.
data
(),
m_wr_buf
.
size
());
if
(
written
!=
m_wr_buf
.
size
())
{
m_wr_buf
.
erase_leading
(
written
);
DEBUG
(
"only "
<<
written
<<
" bytes written"
);
}
else
{
m_wr_buf
.
reset
();
...
...
@@ -257,17 +262,20 @@ class peer_connection : public network_channel {
auto
before
=
m_wr_buf
.
size
();
m_wr_buf
.
write
(
sizeof
(
std
::
uint32_t
),
&
size
,
util
::
grow_if_needed
);
bs
<<
msg
;
size
=
m_wr_buf
.
size
(
)
-
sizeof
(
std
::
uint32_t
);
size
=
(
m_wr_buf
.
size
()
-
before
)
-
sizeof
(
std
::
uint32_t
);
// update size in buffer
memcpy
(
m_wr_buf
.
data
()
+
before
,
&
size
,
sizeof
(
std
::
uint32_t
));
if
(
!
has_unwritten_data
())
{
size_t
written
=
m_ostream
->
write_some
(
m_wr_buf
.
data
(),
m_wr_buf
.
size
());
if
(
written
!=
m_wr_buf
.
size
())
{
DEBUG
(
"tried to write "
<<
m_wr_buf
.
size
()
<<
" bytes, only "
<<
written
<<
" bytes written"
);
m_wr_buf
.
erase_leading
(
written
);
has_unwritten_data
(
true
);
}
else
{
DEBUG
(
written
<<
" bytes written"
);
m_wr_buf
.
reset
();
}
}
...
...
@@ -398,6 +406,16 @@ bool peer_connection::continue_reading() {
memcpy
(
node_id
.
data
(),
m_rd_buf
.
data
()
+
sizeof
(
uint32_t
),
process_information
::
node_id_size
);
m_peer
.
reset
(
new
process_information
(
process_id
,
node_id
));
if
(
*
(
parent
()
->
pself
())
==
*
m_peer
)
{
# ifdef VERBOSE_MIDDLEMAN
DEBUG
(
"incoming connection from self"
);
# elif defined(CPPA_DEBUG)
std
::
cerr
<<
"*** middleman warning: "
"incoming connection from self"
<<
std
::
endl
;
# endif
throw
std
::
ios_base
::
failure
(
"refused connection from self"
);
}
parent
()
->
add_peer
(
*
m_peer
,
this
);
// initialization done
m_rd_state
=
wait_for_msg_size
;
...
...
@@ -698,6 +716,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
maxfd
=
max
(
maxfd
,
fd
);
FD_SET
(
fd
,
&
rdset
);
}
// check consistency of m_peers_with_unwritten_data
if
(
!
m_peers_with_unwritten_data
.
empty
())
{
auto
i
=
m_peers_with_unwritten_data
.
begin
();
auto
e
=
m_peers_with_unwritten_data
.
end
();
while
(
i
!=
e
)
{
if
((
*
i
)
->
has_unwritten_data
()
==
false
)
{
i
=
m_peers_with_unwritten_data
.
erase
(
i
);
}
else
++
i
;
}
}
if
(
m_peers_with_unwritten_data
.
empty
())
{
if
(
wrset_ptr
)
wrset_ptr
=
nullptr
;
}
...
...
@@ -714,8 +743,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
auto
continue_reading
=
[
&
](
const
network_channel_ptr
&
ch
)
{
bool
erase_channel
=
false
;
try
{
erase_channel
=
!
ch
->
continue_reading
();
}
catch
(
ios_base
::
failure
&
e
)
{
DEBUG
(
demangle
(
typeid
(
e
))
<<
": "
<<
e
.
what
());
erase_channel
=
true
;
}
catch
(
runtime_error
&
e
)
{
// thrown whenever serialize/deserialize fails
cerr
<<
"*** runtime_error in middleman: "
<<
e
.
what
()
<<
endl
;
erase_channel
=
true
;
}
catch
(
exception
&
e
)
{
DEBUG
(
demangle
(
typeid
(
e
)
.
name
()
)
<<
": "
<<
e
.
what
());
DEBUG
(
demangle
(
typeid
(
e
))
<<
": "
<<
e
.
what
());
erase_channel
=
true
;
}
if
(
erase_channel
)
{
...
...
@@ -725,7 +763,9 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
};
auto
continue_writing
=
[
&
](
const
peer_connection_ptr
&
peer
)
{
bool
erase_channel
=
false
;
try
{
erase_channel
=
!
peer
->
continue_writing
();
}
try
{
erase_channel
=
!
peer
->
continue_writing
();
}
catch
(
exception
&
e
)
{
DEBUG
(
demangle
(
typeid
(
e
).
name
())
<<
": "
<<
e
.
what
());
erase_channel
=
true
;
...
...
src/self.cpp
View file @
6a058c4d
...
...
@@ -100,6 +100,14 @@ void tss_reset(local_actor* ptr, bool inc_ref_count = true) {
}
// namespace <anonymous>
bool
operator
==
(
const
actor_ptr
&
lhs
,
const
self_type
&
rhs
)
{
return
lhs
.
get
()
==
rhs
.
get
();
}
bool
operator
!=
(
const
self_type
&
lhs
,
const
actor_ptr
&
rhs
)
{
return
lhs
.
get
()
!=
rhs
.
get
();
}
void
self_type
::
cleanup_fun
(
cppa
::
local_actor
*
what
)
{
if
(
what
)
{
auto
ptr
=
dynamic_cast
<
thread_mapped_actor
*>
(
what
);
...
...
src/singleton_manager.cpp
View file @
6a058c4d
...
...
@@ -43,6 +43,7 @@
#include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/network_manager.hpp"
#include "cppa/detail/singleton_manager.hpp"
#include "cppa/detail/decorated_names_map.hpp"
#include "cppa/detail/thread_pool_scheduler.hpp"
#include "cppa/detail/uniform_type_info_map.hpp"
...
...
@@ -57,6 +58,7 @@ using namespace cppa::detail;
//volatile uniform_type_info_map* s_uniform_type_info_map = 0;
std
::
atomic
<
uniform_type_info_map
*>
s_uniform_type_info_map
;
std
::
atomic
<
decorated_names_map
*>
s_decorated_names_map
;
std
::
atomic
<
network_manager
*>
s_network_manager
;
std
::
atomic
<
actor_registry
*>
s_actor_registry
;
std
::
atomic
<
group_manager
*>
s_group_manager
;
...
...
@@ -121,6 +123,8 @@ void shutdown() {
s_empty_tuple
=
nullptr
;
delete
s_uniform_type_info_map
.
load
();
s_uniform_type_info_map
=
nullptr
;
delete
s_decorated_names_map
.
load
();
s_decorated_names_map
=
nullptr
;
}
}
// namespace cppa
...
...
@@ -143,6 +147,10 @@ scheduler* singleton_manager::get_scheduler() {
return
s_scheduler
.
load
();
}
decorated_names_map
*
singleton_manager
::
get_decorated_names_map
()
{
return
lazy_get
(
s_decorated_names_map
);
}
bool
singleton_manager
::
set_scheduler
(
scheduler
*
ptr
)
{
scheduler
*
expected
=
nullptr
;
if
(
s_scheduler
.
compare_exchange_weak
(
expected
,
ptr
))
{
...
...
src/string_serialization.cpp
View file @
6a058c4d
...
...
@@ -29,7 +29,9 @@
#include <stack>
#include <cctype>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include "cppa/atom.hpp"
...
...
@@ -41,26 +43,28 @@
#include "cppa/primitive_variant.hpp"
#include "cppa/uniform_type_info.hpp"
using
namespace
std
;
namespace
cppa
{
namespace
{
class
string_serializer
:
public
serializer
{
std
::
ostream
&
out
;
ostream
&
out
;
struct
pt_writer
{
std
::
ostream
&
out
;
ostream
&
out
;
pt_writer
(
std
::
ostream
&
mout
)
:
out
(
mout
)
{
}
pt_writer
(
ostream
&
mout
)
:
out
(
mout
)
{
}
template
<
typename
T
>
void
operator
()(
const
T
&
value
)
{
out
<<
value
;
}
void
operator
()(
const
st
d
::
st
ring
&
str
)
{
void
operator
()(
const
string
&
str
)
{
out
<<
"
\"
"
;
// << str << "\"";
for
(
char
c
:
str
)
{
if
(
c
==
'"'
)
out
<<
"
\\\"
"
;
...
...
@@ -69,15 +73,15 @@ class string_serializer : public serializer {
out
<<
'"'
;
}
void
operator
()(
const
std
::
u16string
&
)
{
}
void
operator
()(
const
u16string
&
)
{
}
void
operator
()(
const
std
::
u32string
&
)
{
}
void
operator
()(
const
u32string
&
)
{
}
};
bool
m_after_value
;
bool
m_obj_just_opened
;
st
d
::
stack
<
std
::
string
>
m_open_objects
;
st
ack
<
string
>
m_open_objects
;
inline
void
clear
()
{
if
(
m_after_value
)
{
...
...
@@ -92,11 +96,11 @@ class string_serializer : public serializer {
public:
string_serializer
(
std
::
ostream
&
mout
)
string_serializer
(
ostream
&
mout
)
:
out
(
mout
),
m_after_value
(
false
),
m_obj_just_opened
(
false
)
{
}
void
begin_object
(
const
st
d
::
st
ring
&
type_name
)
{
void
begin_object
(
const
string
&
type_name
)
{
clear
();
m_open_objects
.
push
(
type_name
);
out
<<
type_name
;
// << " ( ";
...
...
@@ -129,14 +133,14 @@ class string_serializer : public serializer {
void
write_value
(
const
primitive_variant
&
value
)
{
clear
();
if
(
m_open_objects
.
empty
())
{
throw
std
::
runtime_error
(
"write_value(): m_open_objects.empty()"
);
throw
runtime_error
(
"write_value(): m_open_objects.empty()"
);
}
if
(
m_open_objects
.
top
()
==
"@atom"
)
{
if
(
value
.
ptype
()
!=
pt_uint64
)
{
throw
std
::
runtime_error
(
"expected uint64 value after @atom"
);
throw
runtime_error
(
"expected uint64 value after @atom"
);
}
// write atoms as strings instead of integer values
auto
av
=
static_cast
<
atom_value
>
(
get
<
std
::
uint64_t
>
(
value
));
auto
av
=
static_cast
<
atom_value
>
(
get
<
uint64_t
>
(
value
));
(
pt_writer
(
out
))(
to_string
(
av
));
}
else
{
...
...
@@ -155,33 +159,41 @@ class string_serializer : public serializer {
out
<<
(
m_after_value
?
" }"
:
"}"
);
}
void
write_raw
(
size_t
,
const
void
*
)
{
throw
std
::
runtime_error
(
"string_serializer::write_raw: "
"not implemented yet"
);
void
write_raw
(
size_t
num_bytes
,
const
void
*
buf
)
{
clear
();
auto
first
=
reinterpret_cast
<
const
unsigned
char
*>
(
buf
);
auto
last
=
first
+
num_bytes
;
out
<<
hex
;
out
<<
setfill
(
'0'
);
for
(;
first
!=
last
;
++
first
)
{
out
<<
setw
(
2
)
<<
static_cast
<
size_t
>
(
*
first
);
}
out
<<
dec
;
m_after_value
=
true
;
}
};
class
string_deserializer
:
public
deserializer
{
st
d
::
st
ring
m_str
;
st
d
::
st
ring
::
iterator
m_pos
;
string
m_str
;
string
::
iterator
m_pos
;
//size_t m_obj_count;
st
d
::
st
ack
<
bool
>
m_obj_had_left_parenthesis
;
st
d
::
stack
<
std
::
string
>
m_open_objects
;
stack
<
bool
>
m_obj_had_left_parenthesis
;
st
ack
<
string
>
m_open_objects
;
void
skip_space_and_comma
()
{
while
(
*
m_pos
==
' '
||
*
m_pos
==
','
)
++
m_pos
;
}
void
throw_malformed
(
const
st
d
::
st
ring
&
error_msg
)
{
throw
std
::
logic_error
(
"malformed string: "
+
error_msg
);
void
throw_malformed
(
const
string
&
error_msg
)
{
throw
logic_error
(
"malformed string: "
+
error_msg
);
}
void
consume
(
char
c
)
{
skip_space_and_comma
();
if
(
*
m_pos
!=
c
)
{
st
d
::
st
ring
error
;
string
error
;
error
+=
"expected '"
;
error
+=
c
;
error
+=
"' found '"
;
...
...
@@ -205,8 +217,8 @@ class string_deserializer : public deserializer {
return
false
;
}
inline
st
d
::
st
ring
::
iterator
next_delimiter
()
{
return
std
::
find_if
(
m_pos
,
m_str
.
end
(),
[]
(
char
c
)
->
bool
{
inline
string
::
iterator
next_delimiter
()
{
return
find_if
(
m_pos
,
m_str
.
end
(),
[]
(
char
c
)
->
bool
{
switch
(
c
)
{
case
'('
:
case
')'
:
...
...
@@ -235,33 +247,33 @@ class string_deserializer : public deserializer {
public:
string_deserializer
(
const
st
d
::
st
ring
&
str
)
:
m_str
(
str
)
{
string_deserializer
(
const
string
&
str
)
:
m_str
(
str
)
{
m_pos
=
m_str
.
begin
();
}
string_deserializer
(
st
d
::
string
&&
str
)
:
m_str
(
std
::
move
(
str
))
{
string_deserializer
(
st
ring
&&
str
)
:
m_str
(
move
(
str
))
{
m_pos
=
m_str
.
begin
();
}
st
d
::
st
ring
seek_object
()
{
string
seek_object
()
{
skip_space_and_comma
();
auto
substr_end
=
next_delimiter
();
if
(
m_pos
==
substr_end
)
{
throw_malformed
(
"could not seek object type name"
);
}
st
d
::
st
ring
result
(
m_pos
,
substr_end
);
string
result
(
m_pos
,
substr_end
);
m_pos
=
substr_end
;
return
result
;
}
st
d
::
st
ring
peek_object
()
{
st
d
::
st
ring
result
=
seek_object
();
string
peek_object
()
{
string
result
=
seek_object
();
// restore position in stream
m_pos
-=
result
.
size
();
return
result
;
}
void
begin_object
(
const
st
d
::
st
ring
&
type_name
)
{
void
begin_object
(
const
string
&
type_name
)
{
m_open_objects
.
push
(
type_name
);
//++m_obj_count;
skip_space_and_comma
();
...
...
@@ -280,7 +292,7 @@ class string_deserializer : public deserializer {
m_obj_had_left_parenthesis
.
pop
();
}
if
(
m_open_objects
.
empty
())
{
throw
std
::
runtime_error
(
"no object to end"
);
throw
runtime_error
(
"no object to end"
);
}
m_open_objects
.
pop
();
if
(
m_open_objects
.
empty
())
{
...
...
@@ -294,7 +306,7 @@ class string_deserializer : public deserializer {
size_t
begin_sequence
()
{
integrity_check
();
consume
(
'{'
);
return
std
::
count
(
m_pos
,
std
::
find
(
m_pos
,
m_str
.
end
(),
'}'
),
','
)
+
1
;
return
count
(
m_pos
,
find
(
m_pos
,
m_str
.
end
(),
'}'
),
','
)
+
1
;
}
void
end_sequence
()
{
...
...
@@ -303,18 +315,18 @@ class string_deserializer : public deserializer {
}
struct
from_string
{
const
st
d
::
st
ring
&
str
;
from_string
(
const
st
d
::
st
ring
&
s
)
:
str
(
s
)
{
}
const
string
&
str
;
from_string
(
const
string
&
s
)
:
str
(
s
)
{
}
template
<
typename
T
>
void
operator
()(
T
&
what
)
{
std
::
istringstream
s
(
str
);
istringstream
s
(
str
);
s
>>
what
;
}
void
operator
()(
st
d
::
st
ring
&
what
)
{
void
operator
()(
string
&
what
)
{
what
=
str
;
}
void
operator
()(
std
::
u16string
&
)
{
}
void
operator
()(
std
::
u32string
&
)
{
}
void
operator
()(
u16string
&
)
{
}
void
operator
()(
u32string
&
)
{
}
};
primitive_variant
read_value
(
primitive_type
ptype
)
{
...
...
@@ -323,14 +335,14 @@ class string_deserializer : public deserializer {
if
(
ptype
!=
pt_uint64
)
{
throw_malformed
(
"expected read of pt_uint64 after @atom"
);
}
auto
str_val
=
get
<
st
d
::
st
ring
>
(
read_value
(
pt_u8string
));
auto
str_val
=
get
<
string
>
(
read_value
(
pt_u8string
));
if
(
str_val
.
size
()
>
10
)
{
throw_malformed
(
"atom string size > 10"
);
}
return
detail
::
atom_val
(
str_val
.
c_str
());
}
skip_space_and_comma
();
st
d
::
st
ring
::
iterator
substr_end
;
string
::
iterator
substr_end
;
auto
find_if_cond
=
[]
(
char
c
)
->
bool
{
switch
(
c
)
{
case
')'
:
...
...
@@ -352,28 +364,28 @@ class string_deserializer : public deserializer {
last_char
=
c
;
return
false
;
};
substr_end
=
std
::
find_if
(
m_pos
,
m_str
.
end
(),
find_if_str_cond
);
substr_end
=
find_if
(
m_pos
,
m_str
.
end
(),
find_if_str_cond
);
}
else
{
substr_end
=
std
::
find_if
(
m_pos
,
m_str
.
end
(),
find_if_cond
);
substr_end
=
find_if
(
m_pos
,
m_str
.
end
(),
find_if_cond
);
}
}
else
{
substr_end
=
std
::
find_if
(
m_pos
,
m_str
.
end
(),
find_if_cond
);
substr_end
=
find_if
(
m_pos
,
m_str
.
end
(),
find_if_cond
);
}
if
(
substr_end
==
m_str
.
end
())
{
throw
std
::
logic_error
(
"malformed string (unterminated value)"
);
throw
logic_error
(
"malformed string (unterminated value)"
);
}
st
d
::
st
ring
substr
(
m_pos
,
substr_end
);
string
substr
(
m_pos
,
substr_end
);
m_pos
+=
substr
.
size
();
if
(
ptype
==
pt_u8string
)
{
// skip trailing "
if
(
*
m_pos
!=
'"'
)
{
st
d
::
st
ring
error_msg
;
string
error_msg
;
error_msg
=
"malformed string, expected '
\"
' found '"
;
error_msg
+=
*
m_pos
;
error_msg
+=
"'"
;
throw
std
::
logic_error
(
error_msg
);
throw
logic_error
(
error_msg
);
}
++
m_pos
;
// replace '\"' by '"'
...
...
@@ -385,12 +397,12 @@ class string_deserializer : public deserializer {
last_char
=
c
;
return
false
;
};
st
d
::
st
ring
tmp
;
string
tmp
;
auto
sbegin
=
substr
.
begin
();
auto
send
=
substr
.
end
();
for
(
auto
i
=
std
::
find_if
(
sbegin
,
send
,
cond
);
for
(
auto
i
=
find_if
(
sbegin
,
send
,
cond
);
i
!=
send
;
i
=
std
::
find_if
(
i
,
send
,
cond
))
{
i
=
find_if
(
i
,
send
,
cond
))
{
--
i
;
tmp
.
append
(
sbegin
,
i
);
tmp
+=
'"'
;
...
...
@@ -401,7 +413,7 @@ class string_deserializer : public deserializer {
tmp
.
append
(
sbegin
,
send
);
}
if
(
!
tmp
.
empty
())
{
substr
=
std
::
move
(
tmp
);
substr
=
move
(
tmp
);
}
}
primitive_variant
result
(
ptype
);
...
...
@@ -416,35 +428,50 @@ class string_deserializer : public deserializer {
consume
(
'{'
);
const
primitive_type
*
end
=
begin
+
size
;
for
(
;
begin
!=
end
;
++
begin
)
{
*
storage
=
std
::
move
(
read_value
(
*
begin
));
*
storage
=
move
(
read_value
(
*
begin
));
++
storage
;
}
consume
(
'}'
);
}
void
read_raw
(
size_t
,
void
*
)
{
throw
std
::
runtime_error
(
"string_deserializer::read_raw: "
"not implemented yet"
);
void
read_raw
(
size_t
buf_size
,
void
*
vbuf
)
{
auto
buf
=
reinterpret_cast
<
unsigned
char
*>
(
vbuf
);
integrity_check
();
skip_space_and_comma
();
auto
next_nibble
=
[
&
]()
->
size_t
{
if
(
*
m_pos
==
'\0'
)
{
throw_malformed
(
"unexpected end-of-string"
);
}
char
c
=
*
m_pos
++
;
if
(
!
isxdigit
(
c
))
{
throw_malformed
(
"unexpected character, expected [0-9a-f]"
);
}
return
static_cast
<
size_t
>
(
isdigit
(
c
)
?
c
-
'0'
:
(
c
-
'a'
+
10
));
};
for
(
size_t
i
=
0
;
i
<
buf_size
;
++
i
)
{
auto
nibble
=
next_nibble
();
*
buf
++
=
static_cast
<
unsigned
char
>
((
nibble
<<
4
)
|
next_nibble
());
}
}
};
}
// namespace <anonymous>
object
from_string
(
const
st
d
::
st
ring
&
what
)
{
object
from_string
(
const
string
&
what
)
{
string_deserializer
strd
(
what
);
st
d
::
st
ring
uname
=
strd
.
peek_object
();
string
uname
=
strd
.
peek_object
();
auto
utype
=
uniform_type_info
::
from
(
uname
);
if
(
utype
==
nullptr
)
{
throw
std
::
logic_error
(
uname
+
" is not announced"
);
throw
logic_error
(
uname
+
" is not announced"
);
}
return
utype
->
deserialize
(
&
strd
);
}
namespace
detail
{
st
d
::
st
ring
to_string_impl
(
const
void
*
what
,
const
uniform_type_info
*
utype
)
{
std
::
ostringstream
osstr
;
string
to_string_impl
(
const
void
*
what
,
const
uniform_type_info
*
utype
)
{
ostringstream
osstr
;
string_serializer
strs
(
osstr
);
utype
->
serialize
(
what
,
&
strs
);
return
osstr
.
str
();
...
...
src/thread_mapped_actor.cpp
View file @
6a058c4d
...
...
@@ -43,7 +43,7 @@
namespace
cppa
{
thread_mapped_actor
::
thread_mapped_actor
()
:
m_initialized
(
fals
e
)
{
}
thread_mapped_actor
::
thread_mapped_actor
()
:
m_initialized
(
tru
e
)
{
}
thread_mapped_actor
::
thread_mapped_actor
(
std
::
function
<
void
()
>
fun
)
:
super
(
std
::
move
(
fun
)),
m_initialized
(
false
)
{
}
...
...
src/to_uniform_name.cpp
View file @
6a058c4d
...
...
@@ -48,6 +48,8 @@
#include "cppa/detail/demangle.hpp"
#include "cppa/detail/to_uniform_name.hpp"
#include "cppa/detail/addressed_message.hpp"
#include "cppa/detail/singleton_manager.hpp"
#include "cppa/detail/decorated_names_map.hpp"
namespace
{
...
...
@@ -55,171 +57,157 @@ using namespace std;
using
namespace
cppa
;
using
namespace
detail
;
constexpr
const
char
*
mapped_int_names
[][
2
]
=
{
{
nullptr
,
nullptr
},
// sizeof 0-> invalid
{
"@i8"
,
"@u8"
},
// sizeof 1 -> signed / unsigned int8
{
"@i16"
,
"@u16"
},
// sizeof 2 -> signed / unsigned int16
{
nullptr
,
nullptr
},
// sizeof 3-> invalid
{
"@i32"
,
"@u32"
},
// sizeof 4 -> signed / unsigned int32
{
nullptr
,
nullptr
},
// sizeof 5-> invalid
{
nullptr
,
nullptr
},
// sizeof 6-> invalid
{
nullptr
,
nullptr
},
// sizeof 7-> invalid
{
"@i64"
,
"@u64"
}
// sizeof 8 -> signed / unsigned int64
};
template
<
typename
T
>
constexpr
size_t
sign_index
()
{
static_assert
(
numeric_limits
<
T
>::
is_integer
,
"T is not an integer"
);
return
numeric_limits
<
T
>::
is_signed
?
0
:
1
;
}
template
<
typename
T
>
inline
string
demangled
()
{
return
demangle
(
typeid
(
T
));
}
class
parse_tree
{
template
<
typename
T
>
constexpr
const
char
*
mapped_int_name
()
{
return
mapped_int_names
[
sizeof
(
T
)][
sign_index
<
T
>
()];
}
public:
template
<
typename
Iterator
>
string
to_uniform_name_impl
(
Iterator
begin
,
Iterator
end
,
bool
first_run
=
false
)
{
// all integer type names as uniform representation
static
map
<
string
,
string
>
mapped_demangled_names
=
{
// integer types
{
demangled
<
char
>
(),
mapped_int_name
<
char
>
()
},
{
demangled
<
signed
char
>
(),
mapped_int_name
<
signed
char
>
()
},
{
demangled
<
unsigned
char
>
(),
mapped_int_name
<
unsigned
char
>
()
},
{
demangled
<
short
>
(),
mapped_int_name
<
short
>
()
},
{
demangled
<
signed
short
>
(),
mapped_int_name
<
signed
short
>
()
},
{
demangled
<
unsigned
short
>
(),
mapped_int_name
<
unsigned
short
>
()
},
{
demangled
<
short
int
>
(),
mapped_int_name
<
short
int
>
()
},
{
demangled
<
signed
short
int
>
(),
mapped_int_name
<
signed
short
int
>
()
},
{
demangled
<
unsigned
short
int
>
(),
mapped_int_name
<
unsigned
short
int
>
()},
{
demangled
<
int
>
(),
mapped_int_name
<
int
>
()
},
{
demangled
<
signed
int
>
(),
mapped_int_name
<
signed
int
>
()
},
{
demangled
<
unsigned
int
>
(),
mapped_int_name
<
unsigned
int
>
()
},
{
demangled
<
long
int
>
(),
mapped_int_name
<
long
int
>
()
},
{
demangled
<
signed
long
int
>
(),
mapped_int_name
<
signed
long
int
>
()
},
{
demangled
<
unsigned
long
int
>
(),
mapped_int_name
<
unsigned
long
int
>
()
},
{
demangled
<
long
>
(),
mapped_int_name
<
long
>
()
},
{
demangled
<
signed
long
>
(),
mapped_int_name
<
signed
long
>
()
},
{
demangled
<
unsigned
long
>
(),
mapped_int_name
<
unsigned
long
>
()
},
{
demangled
<
long
long
>
(),
mapped_int_name
<
long
long
>
()
},
{
demangled
<
signed
long
long
>
(),
mapped_int_name
<
signed
long
long
>
()
},
{
demangled
<
unsigned
long
long
>
(),
mapped_int_name
<
unsigned
long
long
>
()},
{
demangled
<
char16_t
>
(),
mapped_int_name
<
char16_t
>
()
},
{
demangled
<
char32_t
>
(),
mapped_int_name
<
char32_t
>
()
},
// string types
{
demangled
<
string
>
(),
"@str"
},
{
demangled
<
u16string
>
(),
"@u16str"
},
{
demangled
<
u32string
>
(),
"@u32str"
},
// cppa types
{
demangled
<
atom_value
>
(),
"@atom"
},
{
demangled
<
util
::
void_type
>
(),
"@0"
},
{
demangled
<
any_tuple
>
(),
"@<>"
},
{
demangled
<
actor_ptr
>
(),
"@actor"
},
{
demangled
<
group_ptr
>
(),
"@group"
},
{
demangled
<
channel_ptr
>
(),
"@channel"
},
{
demangled
<
addressed_message
>
(),
"@msg"
},
{
demangled
<
intrusive_ptr
<
process_information
>
>
(),
"@process_info"
}
};
// check if we could find the whole string in our lookup map
if
(
first_run
)
{
string
tmp
(
begin
,
end
);
auto
i
=
mapped_demangled_names
.
find
(
tmp
);
if
(
i
!=
mapped_demangled_names
.
end
())
{
return
i
->
second
;
string
compile
()
const
{
string
result
;
if
(
m_volatile
)
result
+=
"volatile "
;
if
(
m_const
)
result
+=
"const "
;
if
(
!
m_template
)
{
result
+=
dmm
->
decorate
(
m_name
);
}
else
{
string
full_name
=
m_name
;
full_name
+=
"<"
;
for
(
auto
&
tparam
:
m_template_parameters
)
{
// decorate each single template parameter
if
(
full_name
.
back
()
!=
'<'
)
full_name
+=
","
;
full_name
+=
tparam
.
compile
();
}
full_name
+=
">"
;
// decorate full name
result
+=
dmm
->
decorate
(
full_name
);
}
if
(
m_pointer
)
result
+=
"*"
;
if
(
m_lvalue_ref
)
result
+=
"&"
;
if
(
m_rvalue_ref
)
result
+=
"&&"
;
return
result
;
}
// does [begin, end) represents an empty string?
if
(
begin
==
end
)
return
""
;
// derived reverse_iterator type
typedef
reverse_iterator
<
Iterator
>
reverse_iterator
;
// a subsequence [begin', end') within [begin, end)
typedef
pair
<
Iterator
,
Iterator
>
subseq
;
vector
<
subseq
>
substrings
;
// explode string if we got a list of types
int
open_brackets
=
0
;
// counts "open" '<'
// denotes the begin of a possible subsequence
Iterator
anchor
=
begin
;
for
(
Iterator
i
=
begin
;
i
!=
end
;
/* i is incemented in the loop */
)
{
switch
(
*
i
)
{
template
<
typename
Iterator
>
static
vector
<
parse_tree
>
parse_tpl_args
(
Iterator
first
,
Iterator
last
);
case
'<'
:
++
open_brackets
;
++
i
;
break
;
case
'>'
:
if
(
--
open_brackets
<
0
)
{
throw
runtime_error
(
"malformed string"
);
}
++
i
;
break
;
case
','
:
if
(
open_brackets
==
0
)
{
substrings
.
push_back
(
make_pair
(
anchor
,
i
));
++
i
;
anchor
=
i
;
template
<
typename
Iterator
>
static
parse_tree
parse
(
Iterator
first
,
Iterator
last
)
{
typedef
reverse_iterator
<
Iterator
>
rev_iter
;
auto
sub_first
=
find
(
first
,
last
,
'<'
);
auto
sub_last
=
find
(
rev_iter
(
last
),
rev_iter
(
first
),
'>'
).
base
()
-
1
;
if
(
sub_last
<
sub_first
)
{
sub_first
=
sub_last
=
last
;
}
auto
islegal
=
[](
char
c
)
{
return
isalnum
(
c
)
||
c
==
':'
||
c
==
'_'
;
};
vector
<
string
>
tokens
;
tokens
.
push_back
(
""
);
for
(
auto
i
=
first
;
i
!=
last
;)
{
if
(
i
==
sub_first
)
{
tokens
.
push_back
(
""
);
i
=
sub_last
;
}
else
{
char
c
=
*
i
;
if
(
islegal
(
c
))
{
if
(
!
tokens
.
back
().
empty
()
&&
!
islegal
(
tokens
.
back
().
back
()))
{
tokens
.
push_back
(
""
);
}
tokens
.
back
()
+=
c
;
}
else
if
(
c
==
' '
)
{
tokens
.
push_back
(
""
);
}
else
if
(
c
==
'&'
)
{
if
(
tokens
.
back
().
empty
()
||
tokens
.
back
().
back
()
==
'&'
)
{
tokens
.
back
()
+=
c
;
}
else
{
tokens
.
push_back
(
"&"
);
}
}
else
if
(
c
==
'*'
)
{
tokens
.
push_back
(
"*"
);
}
++
i
;
}
break
;
default:
++
i
;
break
;
}
}
// call recursively for each list argument
if
(
!
substrings
.
empty
())
{
string
result
;
substrings
.
push_back
(
make_pair
(
anchor
,
end
));
for
(
const
subseq
&
sstr
:
substrings
)
{
if
(
!
result
.
empty
())
result
+=
","
;
result
+=
to_uniform_name_impl
(
sstr
.
first
,
sstr
.
second
);
parse_tree
result
;
if
(
sub_first
!=
sub_last
)
{
result
.
m_template
=
true
;
result
.
m_template_parameters
=
parse_tpl_args
(
sub_first
+
1
,
sub_last
);
}
for
(
auto
&
token
:
tokens
)
{
if
(
token
==
"const"
)
{
result
.
m_const
=
true
;
}
else
if
(
token
==
"volatile"
)
{
result
.
m_volatile
=
true
;
}
else
if
(
token
==
"&"
)
{
result
.
m_lvalue_ref
=
true
;
}
else
if
(
token
==
"&&"
)
{
result
.
m_rvalue_ref
=
true
;
}
else
if
(
token
==
"*"
)
{
result
.
m_pointer
=
true
;
}
else
if
(
token
==
"class"
||
token
==
"struct"
)
{
// ignored (created by visual c++ compilers)
}
else
if
(
!
token
.
empty
())
{
if
(
!
result
.
m_name
.
empty
())
result
.
m_name
+=
" "
;
result
.
m_name
+=
token
;
}
}
return
result
;
}
// we didn't got a list, compute unify name
else
{
// is [begin, end) a template?
Iterator
substr_begin
=
find
(
begin
,
end
,
'<'
);
if
(
substr_begin
==
end
)
{
// not a template, return mapping
string
arg
(
begin
,
end
);
auto
mapped
=
mapped_demangled_names
.
find
(
arg
);
return
(
mapped
==
mapped_demangled_names
.
end
())
?
arg
:
mapped
->
second
;
}
// skip leading '<'
++
substr_begin
;
// find trailing '>'
Iterator
substr_end
=
find
(
reverse_iterator
(
end
),
reverse_iterator
(
substr_begin
),
'>'
)
// get as an Iterator
.
base
();
// skip trailing '>'
--
substr_end
;
if
(
substr_end
==
substr_begin
)
{
throw
runtime_error
(
"substr_end == substr_begin"
);
private:
parse_tree
()
:
m_const
(
false
),
m_pointer
(
false
),
m_volatile
(
false
),
m_template
(
false
)
,
m_lvalue_ref
(
false
),
m_rvalue_ref
(
false
)
{
dmm
=
singleton_manager
::
get_decorated_names_map
();
}
bool
m_const
;
bool
m_pointer
;
bool
m_volatile
;
bool
m_template
;
bool
m_lvalue_ref
;
bool
m_rvalue_ref
;
const
decorated_names_map
*
dmm
;
string
m_name
;
vector
<
parse_tree
>
m_template_parameters
;
};
template
<
typename
Iterator
>
vector
<
parse_tree
>
parse_tree
::
parse_tpl_args
(
Iterator
first
,
Iterator
last
)
{
vector
<
parse_tree
>
result
;
long
open_brackets
=
0
;
auto
i0
=
first
;
for
(;
first
!=
last
;
++
first
)
{
switch
(
*
first
)
{
case
'<'
:
++
open_brackets
;
break
;
case
'>'
:
--
open_brackets
;
break
;
case
','
:
if
(
open_brackets
==
0
)
{
result
.
push_back
(
parse
(
i0
,
first
));
i0
=
first
+
1
;
}
break
;
default:
break
;
}
string
result
;
// template name (part before leading '<')
result
.
append
(
begin
,
substr_begin
);
// get mappings of all template parameter(s)
result
+=
to_uniform_name_impl
(
substr_begin
,
substr_end
);
result
.
append
(
substr_end
,
end
);
return
result
;
}
result
.
push_back
(
parse
(
i0
,
first
));
return
result
;
}
template
<
size_t
RawSize
>
...
...
@@ -232,11 +220,7 @@ void replace_all(string& str, const char (&before)[RawSize], const char* after)
}
}
const
char
s_rawstr
[]
=
"std::basic_string<@i8,std::char_traits<@i8>,std::allocator<@i8>>"
;
const
char
s_str
[]
=
"@str"
;
const
char
s_rawan
[]
=
"(anonymous namespace)"
;
const
char
s_rawan
[]
=
"anonymous namespace"
;
const
char
s_an
[]
=
"@_"
;
}
// namespace <anonymous>
...
...
@@ -244,8 +228,8 @@ const char s_an[] = "@_";
namespace
cppa
{
namespace
detail
{
std
::
string
to_uniform_name
(
const
std
::
string
&
dname
)
{
auto
r
=
to_uniform_name_impl
(
dname
.
begin
(),
dname
.
end
(),
true
);
replace_all
(
r
,
s_rawstr
,
s_str
);
auto
r
=
parse_tree
::
parse
(
begin
(
dname
),
end
(
dname
)).
compile
(
);
// replace compiler-dependent "anonmyous namespace" with "@_"
replace_all
(
r
,
s_rawan
,
s_an
);
return
r
;
}
...
...
src/unicast_network.cpp
View file @
6a058c4d
...
...
@@ -57,10 +57,6 @@
#include "cppa/detail/actor_proxy_cache.hpp"
#include "cppa/detail/singleton_manager.hpp"
using
std
::
cout
;
using
std
::
endl
;
namespace
cppa
{
void
publish
(
actor_ptr
whom
,
std
::
unique_ptr
<
util
::
acceptor
>
acceptor
)
{
...
...
@@ -82,6 +78,14 @@ actor_ptr remote_actor(util::io_stream_ptr_pair peer) {
peer
.
first
->
read
(
&
peer_pid
,
sizeof
(
std
::
uint32_t
));
peer
.
first
->
read
(
peer_node_id
.
data
(),
peer_node_id
.
size
());
process_information_ptr
pinfptr
(
new
process_information
(
peer_pid
,
peer_node_id
));
if
(
*
pinf
==
*
pinfptr
)
{
// dude, this is not a remote actor, it's a local actor!
# ifdef CPPA_DEBUG
std
::
cerr
<<
"*** warning: remote_actor() called to access a local actor
\n
"
<<
std
::
flush
;
# endif
return
detail
::
singleton_manager
::
get_actor_registry
()
->
get
(
remote_actor_id
);
}
//auto key = std::make_tuple(remote_actor_id, pinfptr->process_id(), pinfptr->node_id());
detail
::
middleman_add_peer
(
peer
,
pinfptr
);
return
detail
::
get_actor_proxy_cache
().
get_or_put
(
remote_actor_id
,
...
...
@@ -89,8 +93,8 @@ actor_ptr remote_actor(util::io_stream_ptr_pair peer) {
pinfptr
->
node_id
());
}
void
publish
(
actor_ptr
whom
,
std
::
uint16_t
port
)
{
if
(
whom
)
publish
(
whom
,
detail
::
ipv4_acceptor
::
create
(
port
));
void
publish
(
actor_ptr
whom
,
std
::
uint16_t
port
,
const
char
*
addr
)
{
if
(
whom
)
publish
(
whom
,
detail
::
ipv4_acceptor
::
create
(
port
,
addr
));
}
actor_ptr
remote_actor
(
const
char
*
host
,
std
::
uint16_t
port
)
{
...
...
src/uniform_type_info.cpp
View file @
6a058c4d
...
...
@@ -66,11 +66,13 @@ namespace cppa { namespace detail {
namespace
{
using
namespace
std
;
inline
uniform_type_info_map
&
uti_map
()
{
return
*
singleton_manager
::
get_uniform_type_info_map
();
}
inline
const
char
*
raw_name
(
const
std
::
type_info
&
tinfo
)
{
inline
const
char
*
raw_name
(
const
type_info
&
tinfo
)
{
#ifdef CPPA_WINDOWS
return
tinfo
.
raw_name
();
#else
...
...
@@ -78,25 +80,21 @@ inline const char* raw_name(const std::type_info& tinfo) {
#endif
}
template
<
typename
T
>
struct
is_signed
:
std
::
integral_constant
<
bool
,
std
::
numeric_limits
<
T
>::
is_signed
>
{
};
template
<
typename
T
>
inline
const
char
*
raw_name
()
{
return
raw_name
(
typeid
(
T
));
}
typedef
s
td
::
set
<
std
::
string
>
string_set
;
typedef
std
::
map
<
int
,
std
::
pair
<
string_set
,
string_set
>
>
int_name_mapping
;
typedef
s
et
<
string
>
string_set
;
typedef
map
<
int
,
pair
<
string_set
,
string_set
>
>
int_name_mapping
;
template
<
typename
Int
>
inline
void
push_impl
(
int_name_mapping
&
ints
,
std
::
true_type
)
{
inline
void
push_impl
(
int_name_mapping
&
ints
,
true_type
)
{
ints
[
sizeof
(
Int
)].
first
.
insert
(
raw_name
<
Int
>
());
// signed version
}
template
<
typename
Int
>
inline
void
push_impl
(
int_name_mapping
&
ints
,
std
::
false_type
)
{
inline
void
push_impl
(
int_name_mapping
&
ints
,
false_type
)
{
ints
[
sizeof
(
Int
)].
second
.
insert
(
raw_name
<
Int
>
());
// unsigned version
}
...
...
@@ -111,7 +109,7 @@ inline void push(int_name_mapping& ints) {
push
<
Int1
,
Ints
...
>
(
ints
);
}
const
std
::
string
s_nullptr_type_name
{
"@0"
}
;
const
char
s_nullptr_type_name
[]
=
"@0"
;
void
serialize_nullptr
(
serializer
*
sink
)
{
sink
->
begin_object
(
s_nullptr_type_name
);
...
...
@@ -131,7 +129,7 @@ class void_type_tinfo : public uniform_type_info {
void_type_tinfo
()
:
uniform_type_info
(
to_uniform_name
<
util
::
void_type
>
())
{}
bool
equals
(
const
std
::
type_info
&
tinfo
)
const
{
bool
equals
(
const
type_info
&
tinfo
)
const
{
return
typeid
(
util
::
void_type
)
==
tinfo
;
}
...
...
@@ -142,9 +140,9 @@ class void_type_tinfo : public uniform_type_info {
}
void
deserialize
(
void
*
,
deserializer
*
source
)
const
{
st
d
::
st
ring
cname
=
source
->
seek_object
();
string
cname
=
source
->
seek_object
();
if
(
cname
!=
name
())
{
throw
std
::
logic_error
(
"wrong type name found"
);
throw
logic_error
(
"wrong type name found"
);
}
deserialize_nullptr
(
source
);
}
...
...
@@ -176,7 +174,7 @@ class actor_ptr_tinfo : public util::abstract_uniform_type_info<actor_ptr> {
static
void
s_serialize
(
const
actor_ptr
&
ptr
,
serializer
*
sink
,
const
st
d
::
st
ring
&
name
)
{
const
string
&
name
)
{
if
(
ptr
==
nullptr
)
{
serialize_nullptr
(
sink
);
}
...
...
@@ -196,16 +194,14 @@ class actor_ptr_tinfo : public util::abstract_uniform_type_info<actor_ptr> {
static
void
s_deserialize
(
actor_ptr
&
ptrref
,
deserializer
*
source
,
const
st
d
::
st
ring
&
name
)
{
std
::
string
cname
=
source
->
seek_object
();
const
string
&
name
)
{
auto
cname
=
source
->
seek_object
();
if
(
cname
!=
name
)
{
if
(
cname
==
s_nullptr_type_name
)
{
deserialize_nullptr
(
source
);
ptrref
.
reset
();
}
else
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
else
assert_type_name
(
source
,
name
);
// throws
}
else
{
primitive_variant
ptup
[
3
];
...
...
@@ -213,28 +209,28 @@ class actor_ptr_tinfo : public util::abstract_uniform_type_info<actor_ptr> {
source
->
begin_object
(
cname
);
source
->
read_tuple
(
3
,
ptypes
,
ptup
);
source
->
end_object
();
const
st
d
::
string
&
nstr
=
get
<
std
::
string
>
(
ptup
[
2
]);
const
st
ring
&
nstr
=
get
<
string
>
(
ptup
[
2
]);
// local actor?
auto
pinf
=
process_information
::
get
();
if
(
pinf
->
process_id
()
==
get
<
std
::
uint32_t
>
(
ptup
[
1
])
if
(
pinf
->
process_id
()
==
get
<
uint32_t
>
(
ptup
[
1
])
&&
cppa
::
equal
(
nstr
,
pinf
->
node_id
()))
{
auto
id
=
get
<
std
::
uint32_t
>
(
ptup
[
0
]);
auto
id
=
get
<
uint32_t
>
(
ptup
[
0
]);
ptrref
=
singleton_manager
::
get_actor_registry
()
->
get
(
id
);
//ptrref = actor::by_id(get<
std::
uint32_t>(ptup[0]));
//ptrref = actor::by_id(get<uint32_t>(ptup[0]));
}
else
{
/*
actor_proxy_cache::key_tuple key;
std::get<0>(key) = get<std::
uint32_t>(ptup[0]);
std::get<1>(key) = get<std::
uint32_t>(ptup[1]);
node_id_from_string(nstr,
std::
get<2>(key));
get<0>(key) = get<
uint32_t>(ptup[0]);
get<1>(key) = get<
uint32_t>(ptup[1]);
node_id_from_string(nstr, get<2>(key));
ptrref = detail::get_actor_proxy_cache().get(key);
*/
process_information
::
node_id_type
nid
;
node_id_from_string
(
nstr
,
nid
);
auto
&
cache
=
detail
::
get_actor_proxy_cache
();
ptrref
=
cache
.
get_or_put
(
get
<
std
::
uint32_t
>
(
ptup
[
0
]),
get
<
std
::
uint32_t
>
(
ptup
[
1
]),
ptrref
=
cache
.
get_or_put
(
get
<
uint32_t
>
(
ptup
[
0
]),
get
<
uint32_t
>
(
ptup
[
1
]),
nid
);
}
}
...
...
@@ -258,7 +254,7 @@ class group_ptr_tinfo : public util::abstract_uniform_type_info<group_ptr> {
static
void
s_serialize
(
const
group_ptr
&
ptr
,
serializer
*
sink
,
const
st
d
::
st
ring
&
name
)
{
const
string
&
name
)
{
if
(
ptr
==
nullptr
)
{
serialize_nullptr
(
sink
);
}
...
...
@@ -272,21 +268,19 @@ class group_ptr_tinfo : public util::abstract_uniform_type_info<group_ptr> {
static
void
s_deserialize
(
group_ptr
&
ptrref
,
deserializer
*
source
,
const
st
d
::
st
ring
&
name
)
{
std
::
string
cname
=
source
->
seek_object
();
const
string
&
name
)
{
auto
cname
=
source
->
seek_object
();
if
(
cname
!=
name
)
{
if
(
cname
==
s_nullptr_type_name
)
{
deserialize_nullptr
(
source
);
ptrref
.
reset
();
}
else
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
else
assert_type_name
(
source
,
name
);
// throws
}
else
{
source
->
begin_object
(
name
);
auto
modname
=
source
->
read_value
(
pt_u8string
);
ptrref
=
group
::
get_module
(
get
<
st
d
::
st
ring
>
(
modname
))
ptrref
=
group
::
get_module
(
get
<
string
>
(
modname
))
->
deserialize
(
source
);
source
->
end_object
();
}
...
...
@@ -308,16 +302,16 @@ class group_ptr_tinfo : public util::abstract_uniform_type_info<group_ptr> {
class
channel_ptr_tinfo
:
public
util
::
abstract_uniform_type_info
<
channel_ptr
>
{
st
d
::
st
ring
group_ptr_name
;
st
d
::
st
ring
actor_ptr_name
;
string
group_ptr_name
;
string
actor_ptr_name
;
public:
static
void
s_serialize
(
const
channel_ptr
&
ptr
,
serializer
*
sink
,
const
st
d
::
st
ring
&
channel_type_name
,
const
st
d
::
st
ring
&
actor_ptr_type_name
,
const
st
d
::
st
ring
&
group_ptr_type_name
)
{
const
string
&
channel_type_name
,
const
string
&
actor_ptr_type_name
,
const
string
&
group_ptr_type_name
)
{
sink
->
begin_object
(
channel_type_name
);
if
(
ptr
==
nullptr
)
{
serialize_nullptr
(
sink
);
...
...
@@ -332,7 +326,7 @@ class channel_ptr_tinfo : public util::abstract_uniform_type_info<channel_ptr> {
group_ptr_tinfo
::
s_serialize
(
gptr
,
sink
,
group_ptr_type_name
);
}
else
{
throw
std
::
logic_error
(
"channel is neither "
throw
logic_error
(
"channel is neither "
"an actor nor a group"
);
}
}
...
...
@@ -341,15 +335,12 @@ class channel_ptr_tinfo : public util::abstract_uniform_type_info<channel_ptr> {
static
void
s_deserialize
(
channel_ptr
&
ptrref
,
deserializer
*
source
,
const
std
::
string
&
name
,
const
std
::
string
&
actor_ptr_type_name
,
const
std
::
string
&
group_ptr_type_name
)
{
std
::
string
cname
=
source
->
seek_object
();
if
(
cname
!=
name
)
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
source
->
begin_object
(
cname
);
std
::
string
subobj
=
source
->
peek_object
();
const
string
&
name
,
const
string
&
actor_ptr_type_name
,
const
string
&
group_ptr_type_name
)
{
assert_type_name
(
source
,
name
);
source
->
begin_object
(
name
);
string
subobj
=
source
->
peek_object
();
if
(
subobj
==
actor_ptr_type_name
)
{
actor_ptr
tmp
;
actor_ptr_tinfo
::
s_deserialize
(
tmp
,
source
,
actor_ptr_type_name
);
...
...
@@ -365,7 +356,7 @@ class channel_ptr_tinfo : public util::abstract_uniform_type_info<channel_ptr> {
ptrref
.
reset
();
}
else
{
throw
std
::
logic_error
(
"unexpected type name: "
+
subobj
);
throw
logic_error
(
"unexpected type name: "
+
subobj
);
}
source
->
end_object
();
}
...
...
@@ -401,7 +392,7 @@ class any_tuple_tinfo : public util::abstract_uniform_type_info<any_tuple> {
static
void
s_serialize
(
const
any_tuple
&
atup
,
serializer
*
sink
,
const
st
d
::
st
ring
&
name
)
{
const
string
&
name
)
{
sink
->
begin_object
(
name
);
sink
->
begin_sequence
(
atup
.
size
());
for
(
size_t
i
=
0
;
i
<
atup
.
size
();
++
i
)
{
...
...
@@ -413,11 +404,10 @@ class any_tuple_tinfo : public util::abstract_uniform_type_info<any_tuple> {
static
void
s_deserialize
(
any_tuple
&
atref
,
deserializer
*
source
,
const
std
::
string
&
name
)
{
const
string
&
name
)
{
uniform_type_info
::
assert_type_name
(
source
,
name
);
auto
result
=
new
detail
::
object_array
;
auto
str
=
source
->
seek_object
();
if
(
str
!=
name
)
throw
std
::
logic_error
(
"invalid type found: "
+
str
);
source
->
begin_object
(
str
);
source
->
begin_object
(
name
);
size_t
tuple_size
=
source
->
begin_sequence
();
for
(
size_t
i
=
0
;
i
<
tuple_size
;
++
i
)
{
auto
tname
=
source
->
peek_object
();
...
...
@@ -443,10 +433,10 @@ class any_tuple_tinfo : public util::abstract_uniform_type_info<any_tuple> {
class
addr_msg_tinfo
:
public
util
::
abstract_uniform_type_info
<
addressed_message
>
{
st
d
::
st
ring
any_tuple_name
;
st
d
::
st
ring
actor_ptr_name
;
st
d
::
st
ring
group_ptr_name
;
st
d
::
st
ring
channel_ptr_name
;
string
any_tuple_name
;
string
actor_ptr_name
;
string
group_ptr_name
;
string
channel_ptr_name
;
public:
...
...
@@ -466,9 +456,8 @@ class addr_msg_tinfo : public util::abstract_uniform_type_info<addressed_message
}
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
auto
tname
=
source
->
seek_object
();
if
(
tname
!=
name
())
throw
42
;
source
->
begin_object
(
tname
);
assert_type_name
(
source
);
source
->
begin_object
(
name
());
auto
&
msg
=
*
reinterpret_cast
<
addressed_message
*>
(
instance
);
actor_ptr_tinfo
::
s_deserialize
(
msg
.
sender
(),
source
,
actor_ptr_name
);
channel_ptr_tinfo
::
s_deserialize
(
msg
.
receiver
(),
...
...
@@ -512,15 +501,13 @@ class process_info_ptr_tinfo : public util::abstract_uniform_type_info<process_i
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
auto
&
ptrref
=
*
reinterpret_cast
<
ptr_type
*>
(
instance
);
std
::
string
cname
=
source
->
seek_object
();
auto
cname
=
source
->
seek_object
();
if
(
cname
!=
name
())
{
if
(
cname
==
s_nullptr_type_name
)
{
deserialize_nullptr
(
source
);
ptrref
.
reset
();
}
else
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
else
assert_type_name
(
source
);
// throws
}
else
{
primitive_variant
ptup
[
2
];
...
...
@@ -529,8 +516,8 @@ class process_info_ptr_tinfo : public util::abstract_uniform_type_info<process_i
source
->
read_tuple
(
2
,
ptypes
,
ptup
);
source
->
end_object
();
process_information
::
node_id_type
nid
;
node_id_from_string
(
get
<
st
d
::
st
ring
>
(
ptup
[
1
]),
nid
);
ptrref
.
reset
(
new
process_information
{
get
<
std
::
uint32_t
>
(
ptup
[
0
]),
nid
});
node_id_from_string
(
get
<
string
>
(
ptup
[
1
]),
nid
);
ptrref
.
reset
(
new
process_information
{
get
<
uint32_t
>
(
ptup
[
0
]),
nid
});
}
}
...
...
@@ -543,18 +530,17 @@ class atom_value_tinfo : public util::abstract_uniform_type_info<atom_value> {
virtual
void
serialize
(
const
void
*
instance
,
serializer
*
sink
)
const
{
auto
val
=
reinterpret_cast
<
const
atom_value
*>
(
instance
);
sink
->
begin_object
(
name
());
sink
->
write_value
(
static_cast
<
std
::
uint64_t
>
(
*
val
));
sink
->
write_value
(
static_cast
<
uint64_t
>
(
*
val
));
sink
->
end_object
();
}
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
assert_type_name
(
source
);
auto
val
=
reinterpret_cast
<
atom_value
*>
(
instance
);
auto
tname
=
source
->
seek_object
();
if
(
tname
!=
name
())
throw
42
;
source
->
begin_object
(
tname
);
source
->
begin_object
(
name
());
auto
ptval
=
source
->
read_value
(
pt_uint64
);
source
->
end_object
();
*
val
=
static_cast
<
atom_value
>
(
get
<
std
::
uint64_t
>
(
ptval
));
*
val
=
static_cast
<
atom_value
>
(
get
<
uint64_t
>
(
ptval
));
}
};
...
...
@@ -564,20 +550,19 @@ class duration_tinfo : public util::abstract_uniform_type_info<util::duration> {
virtual
void
serialize
(
const
void
*
instance
,
serializer
*
sink
)
const
{
auto
val
=
reinterpret_cast
<
const
util
::
duration
*>
(
instance
);
sink
->
begin_object
(
name
());
sink
->
write_value
(
static_cast
<
std
::
uint32_t
>
(
val
->
unit
));
sink
->
write_value
(
static_cast
<
uint32_t
>
(
val
->
unit
));
sink
->
write_value
(
val
->
count
);
sink
->
end_object
();
}
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
assert_type_name
(
source
);
source
->
begin_object
(
name
());
auto
val
=
reinterpret_cast
<
util
::
duration
*>
(
instance
);
auto
tname
=
source
->
seek_object
();
if
(
tname
!=
name
())
throw
42
;
source
->
begin_object
(
tname
);
auto
unit_val
=
source
->
read_value
(
pt_uint32
);
auto
count_val
=
source
->
read_value
(
pt_uint32
);
source
->
end_object
();
switch
(
get
<
std
::
uint32_t
>
(
unit_val
))
{
switch
(
get
<
uint32_t
>
(
unit_val
))
{
case
1
:
val
->
unit
=
util
::
time_unit
::
seconds
;
break
;
...
...
@@ -594,7 +579,7 @@ class duration_tinfo : public util::abstract_uniform_type_info<util::duration> {
val
->
unit
=
util
::
time_unit
::
none
;
break
;
}
val
->
count
=
get
<
std
::
uint32_t
>
(
count_val
);
val
->
count
=
get
<
uint32_t
>
(
count_val
);
}
};
...
...
@@ -604,14 +589,14 @@ class int_tinfo : public detail::default_uniform_type_info_impl<T> {
public:
bool
equals
(
const
std
::
type_info
&
tinfo
)
const
{
bool
equals
(
const
type_info
&
tinfo
)
const
{
// TODO: string comparsion sucks & is slow; find a nicer solution
auto
map_iter
=
uti_map
().
int_names
().
find
(
sizeof
(
T
));
const
string_set
&
st
=
is_signed
<
T
>::
value
?
map_iter
->
second
.
first
:
map_iter
->
second
.
second
;
auto
x
=
raw_name
(
tinfo
);
return
std
::
any_of
(
st
.
begin
(),
st
.
end
(),
[
&
x
](
const
st
d
::
st
ring
&
y
)
{
return
x
==
y
;
});
return
any_of
(
st
.
begin
(),
st
.
end
(),
[
&
x
](
const
string
&
y
)
{
return
x
==
y
;
});
}
};
...
...
@@ -623,14 +608,13 @@ class bool_tinfo : public util::abstract_uniform_type_info<bool> {
virtual
void
serialize
(
const
void
*
instance
,
serializer
*
sink
)
const
{
auto
val
=
*
reinterpret_cast
<
const
bool
*>
(
instance
);
sink
->
begin_object
(
name
());
sink
->
write_value
(
static_cast
<
std
::
uint8_t
>
(
val
?
1
:
0
));
sink
->
write_value
(
static_cast
<
uint8_t
>
(
val
?
1
:
0
));
sink
->
end_object
();
}
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
{
auto
tname
=
source
->
seek_object
();
if
(
tname
!=
name
())
throw
42
;
source
->
begin_object
(
tname
);
assert_type_name
(
source
);
source
->
begin_object
(
name
());
auto
ptval
=
source
->
read_value
(
pt_uint8
);
source
->
end_object
();
*
reinterpret_cast
<
bool
*>
(
instance
)
=
(
get
<
pt_uint8
>
(
ptval
)
!=
0
);
...
...
@@ -726,18 +710,12 @@ uniform_type_info_map::~uniform_type_info_map() {
const
uniform_type_info
*
uniform_type_info_map
::
by_raw_name
(
const
std
::
string
&
name
)
const
{
auto
i
=
m_by_rname
.
find
(
name
);
if
(
i
!=
m_by_rname
.
end
())
{
return
i
->
second
;
}
return
nullptr
;
return
(
i
!=
m_by_rname
.
end
())
?
i
->
second
:
nullptr
;
}
const
uniform_type_info
*
uniform_type_info_map
::
by_uniform_name
(
const
std
::
string
&
name
)
const
{
auto
i
=
m_by_uname
.
find
(
name
);
if
(
i
!=
m_by_uname
.
end
())
{
return
i
->
second
;
}
return
nullptr
;
return
(
i
!=
m_by_uname
.
end
())
?
i
->
second
:
nullptr
;
}
bool
uniform_type_info_map
::
insert
(
const
std
::
set
<
std
::
string
>&
raw_names
,
...
...
@@ -776,7 +754,23 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype) {
uniform_type_info
::
uniform_type_info
(
const
std
::
string
&
str
)
:
m_name
(
str
)
{
}
uniform_type_info
::~
uniform_type_info
()
{
uniform_type_info
::~
uniform_type_info
()
{
}
void
uniform_type_info
::
assert_type_name
(
deserializer
*
source
,
const
std
::
string
&
expected_name
)
{
auto
tname
=
source
->
seek_object
();
if
(
tname
!=
expected_name
)
{
std
::
string
error_msg
=
"wrong type name found; expected
\"
"
;
error_msg
+=
expected_name
;
error_msg
+=
"
\"
, found
\"
"
;
error_msg
+=
tname
;
error_msg
+=
"
\"
"
;
throw
std
::
logic_error
(
std
::
move
(
error_msg
));
}
}
void
uniform_type_info
::
assert_type_name
(
deserializer
*
source
)
const
{
assert_type_name
(
source
,
name
());
}
object
uniform_type_info
::
create
()
const
{
...
...
unit_testing/test__remote_actor.cpp
View file @
6a058c4d
...
...
@@ -236,7 +236,7 @@ int main(int argc, char** argv) {
bool
success
=
false
;
do
{
try
{
publish
(
self
,
port
);
publish
(
self
,
port
,
"127.0.0.1"
);
success
=
true
;
}
catch
(
bind_failure
&
)
{
...
...
unit_testing/test__serialization.cpp
View file @
6a058c4d
...
...
@@ -50,17 +50,14 @@
#include "cppa/detail/ptype_to_type.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp"
using
std
::
cout
;
using
std
::
cerr
;
using
std
::
endl
;
using
namespace
std
;
using
namespace
cppa
;
using
namespace
cppa
::
util
;
using
cppa
::
detail
::
type_to_ptype
;
using
cppa
::
detail
::
ptype_to_type
;
namespace
{
const
size_t
ui32size
=
sizeof
(
std
::
uint32_t
);
}
namespace
{
const
size_t
ui32size
=
sizeof
(
uint32_t
);
}
struct
struct_a
{
int
x
;
...
...
@@ -78,7 +75,7 @@ bool operator!=(const struct_a& lhs, const struct_a& rhs) {
struct
struct_b
{
struct_a
a
;
int
z
;
std
::
list
<
int
>
ints
;
list
<
int
>
ints
;
};
bool
operator
==
(
const
struct_b
&
lhs
,
const
struct_b
&
rhs
)
{
...
...
@@ -89,11 +86,11 @@ bool operator!=(const struct_b& lhs, const struct_b& rhs) {
return
!
(
lhs
==
rhs
);
}
typedef
std
::
map
<
std
::
string
,
std
::
u16string
>
strmap
;
typedef
map
<
string
,
u16string
>
strmap
;
struct
struct_c
{
strmap
strings
;
s
td
::
s
et
<
int
>
ints
;
set
<
int
>
ints
;
};
bool
operator
==
(
const
struct_c
&
lhs
,
const
struct_c
&
rhs
)
{
...
...
@@ -106,36 +103,97 @@ bool operator!=(const struct_c& lhs, const struct_c& rhs) {
static
const
char
*
msg1str
=
u8R"__(@<> ( { @i32 ( 42 ), @str ( "Hello \"World\"!" ) } ))__"
;
struct
raw_struct
{
string
str
;
};
bool
operator
==
(
const
raw_struct
&
lhs
,
const
raw_struct
&
rhs
)
{
return
lhs
.
str
==
rhs
.
str
;
}
bool
operator
!=
(
const
raw_struct
&
lhs
,
const
raw_struct
&
rhs
)
{
return
lhs
.
str
!=
rhs
.
str
;
}
struct
raw_struct_type_info
:
util
::
abstract_uniform_type_info
<
raw_struct
>
{
void
serialize
(
const
void
*
ptr
,
serializer
*
sink
)
const
{
auto
rs
=
reinterpret_cast
<
const
raw_struct
*>
(
ptr
);
sink
->
begin_object
(
name
());
sink
->
write_value
(
static_cast
<
uint32_t
>
(
rs
->
str
.
size
()));
sink
->
write_raw
(
rs
->
str
.
size
(),
rs
->
str
.
data
());
sink
->
end_object
();
}
void
deserialize
(
void
*
ptr
,
deserializer
*
source
)
const
{
assert_type_name
(
source
);
source
->
begin_object
(
name
());
auto
rs
=
reinterpret_cast
<
raw_struct
*>
(
ptr
);
rs
->
str
.
clear
();
auto
size
=
get
<
std
::
uint32_t
>
(
source
->
read_value
(
pt_uint32
));
rs
->
str
.
resize
(
size
);
source
->
read_raw
(
size
,
&
(
rs
->
str
[
0
]));
source
->
end_object
();
}
};
int
main
()
{
CPPA_TEST
(
test__serialization
);
announce
(
typeid
(
raw_struct
),
new
raw_struct_type_info
);
auto
oarr
=
new
detail
::
object_array
;
oarr
->
push_back
(
object
::
from
(
static_cast
<
std
::
uint32_t
>
(
42
)));
oarr
->
push_back
(
object
::
from
(
static_cast
<
uint32_t
>
(
42
)));
oarr
->
push_back
(
object
::
from
(
"foo"
));
any_tuple
atuple1
(
oarr
);
try
{
auto
opt
=
tuple_cast
<
std
::
uint32_t
,
std
::
string
>
(
atuple1
);
auto
opt
=
tuple_cast
<
uint32_t
,
string
>
(
atuple1
);
CPPA_CHECK
(
opt
.
valid
());
if
(
opt
)
{
auto
&
tup
=
*
opt
;
CPPA_CHECK_EQUAL
(
tup
.
size
(),
static_cast
<
size_t
>
(
2
));
CPPA_CHECK_EQUAL
(
get
<
0
>
(
tup
),
static_cast
<
std
::
uint32_t
>
(
42
));
CPPA_CHECK_EQUAL
(
get
<
0
>
(
tup
),
static_cast
<
uint32_t
>
(
42
));
CPPA_CHECK_EQUAL
(
get
<
1
>
(
tup
),
"foo"
);
}
}
catch
(
std
::
exception
&
e
)
{
catch
(
exception
&
e
)
{
CPPA_ERROR
(
"exception: "
<<
e
.
what
());
}
try
{
// test raw_type in both binary and string serialization
raw_struct
rs
;
rs
.
str
=
"Lorem ipsum dolor sit amet."
;
util
::
buffer
wr_buf
;
binary_serializer
bs
(
&
wr_buf
);
bs
<<
rs
;
binary_deserializer
bd
(
wr_buf
.
data
(),
wr_buf
.
size
());
raw_struct
rs2
;
uniform_typeid
<
raw_struct
>
()
->
deserialize
(
&
rs2
,
&
bd
);
CPPA_CHECK_EQUAL
(
rs
.
str
,
rs2
.
str
);
auto
rsstr
=
cppa
::
to_string
(
rs
);
rs2
.
str
=
"foobar"
;
cout
<<
"rs as string: "
<<
rsstr
<<
endl
;
rs2
=
from_string
<
raw_struct
>
(
rsstr
);
CPPA_CHECK_EQUAL
(
rs
.
str
,
rs2
.
str
);
}
catch
(
exception
&
e
)
{
CPPA_ERROR
(
"exception: "
<<
e
.
what
());
}
{
any_tuple
ttup
=
make_cow_tuple
(
1
,
2
,
actor_ptr
(
self
));
util
::
buffer
wr_buf
;
binary_serializer
bs
(
&
wr_buf
);
bs
<<
ttup
;
bs
<<
ttup
;
binary_deserializer
bd
(
wr_buf
.
data
(),
wr_buf
.
size
());
any_tuple
ttup2
;
any_tuple
ttup3
;
uniform_typeid
<
any_tuple
>
()
->
deserialize
(
&
ttup2
,
&
bd
);
CPPA_CHECK
(
ttup
==
ttup2
);
uniform_typeid
<
any_tuple
>
()
->
deserialize
(
&
ttup3
,
&
bd
);
CPPA_CHECK
(
ttup
==
ttup2
);
CPPA_CHECK
(
ttup
==
ttup3
);
CPPA_CHECK
(
ttup2
==
ttup3
);
}
{
// serialize b1 to buf
...
...
@@ -147,7 +205,7 @@ int main() {
any_tuple
atuple2
;
uniform_typeid
<
any_tuple
>
()
->
deserialize
(
&
atuple2
,
&
bd
);
try
{
auto
opt
=
tuple_cast
<
std
::
uint32_t
,
std
::
string
>
(
atuple2
);
auto
opt
=
tuple_cast
<
uint32_t
,
string
>
(
atuple2
);
CPPA_CHECK
(
opt
.
valid
());
if
(
opt
.
valid
())
{
auto
&
tup
=
*
opt
;
...
...
@@ -156,12 +214,12 @@ int main() {
CPPA_CHECK_EQUAL
(
get
<
1
>
(
tup
),
"foo"
);
}
}
catch
(
std
::
exception
&
e
)
{
catch
(
exception
&
e
)
{
CPPA_ERROR
(
"exception: "
<<
e
.
what
());
}
}
{
any_tuple
msg1
=
cppa
::
make_cow_tuple
(
42
,
st
d
::
st
ring
(
"Hello
\"
World
\"
!"
));
any_tuple
msg1
=
cppa
::
make_cow_tuple
(
42
,
string
(
"Hello
\"
World
\"
!"
));
auto
msg1_tostring
=
to_string
(
msg1
);
if
(
msg1str
!=
msg1_tostring
)
{
CPPA_ERROR
(
"msg1str != to_string(msg1)"
);
...
...
@@ -178,8 +236,8 @@ int main() {
if
(
typeid
(
any_tuple
)
==
*
(
obj1
.
type
())
&&
obj2
.
type
()
==
obj1
.
type
())
{
auto
&
content1
=
get
<
any_tuple
>
(
obj1
);
auto
&
content2
=
get
<
any_tuple
>
(
obj2
);
auto
opt1
=
tuple_cast
<
decltype
(
42
),
st
d
::
st
ring
>
(
content1
);
auto
opt2
=
tuple_cast
<
decltype
(
42
),
st
d
::
st
ring
>
(
content2
);
auto
opt1
=
tuple_cast
<
decltype
(
42
),
string
>
(
content1
);
auto
opt2
=
tuple_cast
<
decltype
(
42
),
string
>
(
content2
);
CPPA_CHECK
(
opt1
.
valid
()
&&
opt2
.
valid
());
if
(
opt1
.
valid
()
&&
opt2
.
valid
())
{
auto
&
tup1
=
*
opt1
;
...
...
@@ -198,18 +256,18 @@ int main() {
}
CPPA_CHECK
((
is_iterable
<
int
>::
value
)
==
false
);
// st
d::st
ring is primitive and thus not identified by is_iterable
CPPA_CHECK
((
is_iterable
<
st
d
::
st
ring
>::
value
)
==
false
);
CPPA_CHECK
((
is_iterable
<
std
::
list
<
int
>>::
value
)
==
true
);
CPPA_CHECK
((
is_iterable
<
std
::
map
<
int
,
int
>>::
value
)
==
true
);
// string is primitive and thus not identified by is_iterable
CPPA_CHECK
((
is_iterable
<
string
>::
value
)
==
false
);
CPPA_CHECK
((
is_iterable
<
list
<
int
>>::
value
)
==
true
);
CPPA_CHECK
((
is_iterable
<
map
<
int
,
int
>>::
value
)
==
true
);
{
// test meta_object implementation for primitive types
auto
meta_int
=
uniform_typeid
<
std
::
uint32_t
>
();
auto
meta_int
=
uniform_typeid
<
uint32_t
>
();
CPPA_CHECK
(
meta_int
!=
nullptr
);
if
(
meta_int
)
{
auto
o
=
meta_int
->
create
();
get_ref
<
std
::
uint32_t
>
(
o
)
=
42
;
auto
str
=
to_string
(
get
<
std
::
uint32_t
>
(
o
));
CPPA_CHECK_EQUAL
(
str
,
"@u32 ( 42 )"
);
get_ref
<
uint32_t
>
(
o
)
=
42
;
auto
str
=
cppa
::
to_string
(
get
<
uint32_t
>
(
o
));
CPPA_CHECK_EQUAL
(
"@u32 ( 42 )"
,
str
);
}
}
{
// test serializers / deserializers with struct_b
...
...
@@ -220,7 +278,7 @@ int main() {
&
struct_b
::
z
,
&
struct_b
::
ints
);
// testees
struct_b
b1
=
{
{
1
,
2
},
3
,
std
::
list
<
int
>
{
4
,
5
,
6
,
7
,
8
,
9
,
10
}
};
struct_b
b1
=
{
{
1
,
2
},
3
,
list
<
int
>
{
4
,
5
,
6
,
7
,
8
,
9
,
10
}
};
struct_b
b2
;
struct_b
b3
;
// expected result of to_string(&b1, meta_b)
...
...
@@ -253,7 +311,7 @@ int main() {
// get meta type of struct_c and "announce"
announce
<
struct_c
>
(
&
struct_c
::
strings
,
&
struct_c
::
ints
);
// testees
struct_c
c1
{
strmap
{{
"abc"
,
u"cba"
},
{
"x"
,
u"y"
}},
s
td
::
s
et
<
int
>
{
9
,
4
,
5
}};
struct_c
c1
{
strmap
{{
"abc"
,
u"cba"
},
{
"x"
,
u"y"
}},
set
<
int
>
{
9
,
4
,
5
}};
struct_c
c2
;
{
// serialize c1 to buf
util
::
buffer
wr_buf
;
...
...
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