Commit 6a058c4d authored by Dominik Charousset's avatar Dominik Charousset

Merge branch 'unstable' of github.com:Neverlord/libcppa into unstable

parents 8f79f160 9e7db021
...@@ -131,6 +131,7 @@ set(LIBCPPA_SRC ...@@ -131,6 +131,7 @@ set(LIBCPPA_SRC
src/uniform_type_info.cpp src/uniform_type_info.cpp
src/yield_interface.cpp src/yield_interface.cpp
src/context_switching_actor.cpp src/context_switching_actor.cpp
src/decorated_names_map.cpp
) )
set(boost_context third_party/boost_context) set(boost_context third_party/boost_context)
......
...@@ -272,3 +272,6 @@ examples/group_chat.cpp ...@@ -272,3 +272,6 @@ examples/group_chat.cpp
cppa/opt.hpp cppa/opt.hpp
src/opt.cpp src/opt.cpp
cppa/detail/opt_impls.hpp cppa/detail/opt_impls.hpp
examples/type_plugins.hpp
cppa/detail/decorated_names_map.hpp
src/decorated_names_map.cpp
...@@ -202,6 +202,11 @@ class actor : public channel { ...@@ -202,6 +202,11 @@ class actor : public channel {
*/ */
typedef intrusive_ptr<actor> actor_ptr; 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 * * inline and template member function implementations *
******************************************************************************/ ******************************************************************************/
......
...@@ -751,9 +751,11 @@ inline void await_all_others_done() { ...@@ -751,9 +751,11 @@ inline void await_all_others_done() {
* The connection is automatically closed if the lifetime of @p whom ends. * The connection is automatically closed if the lifetime of @p whom ends.
* @param whom Actor that should be published at @p port. * @param whom Actor that should be published at @p port.
* @param port Unused TCP 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 * @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. * @brief Publishes @p whom using @p acceptor to handle incoming connections.
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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
...@@ -319,10 +319,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T ...@@ -319,10 +319,7 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
} }
void deserialize(void* obj, deserializer* d) const { void deserialize(void* obj, deserializer* d) const {
std::string cname = d->seek_object(); this->assert_type_name(d);
if (cname != this->name()) {
throw std::logic_error("wrong type name found");
}
d->begin_object(this->name()); d->begin_object(this->name());
for (auto& m : m_members) { for (auto& m : m_members) {
m.deserialize(obj, d); m.deserialize(obj, d);
......
...@@ -42,7 +42,8 @@ class ipv4_acceptor : public util::acceptor { ...@@ -42,7 +42,8 @@ class ipv4_acceptor : public util::acceptor {
public: 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(); ~ipv4_acceptor();
......
...@@ -36,24 +36,24 @@ ...@@ -36,24 +36,24 @@
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/primitive_variant.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/util/abstract_uniform_type_info.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/type_to_ptype.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<typename T1, typename T2> template<typename T1, typename T2, bool PrimitiveTypes> // default: true
class pair_member : public util::abstract_uniform_type_info<std::pair<T1,T2>> { struct pair_member_impl {
static constexpr primitive_type ptype1 = type_to_ptype<T1>::ptype; static constexpr primitive_type ptype1 = type_to_ptype<T1>::ptype;
static constexpr primitive_type ptype2 = type_to_ptype<T2>::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; typedef std::pair<T1, T2> pair_type;
public:
void serialize(const void* obj, serializer* s) const { void serialize(const void* obj, serializer* s) const {
auto& p = *reinterpret_cast<const pair_type*>(obj); auto& p = *reinterpret_cast<const pair_type*>(obj);
primitive_variant values[2] = { p.first, p.second }; 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>> { ...@@ -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 } } // namespace cppa::detail
#endif // CPPA_PAIR_MEMBER_HPP #endif // CPPA_PAIR_MEMBER_HPP
...@@ -45,6 +45,7 @@ class group_manager; ...@@ -45,6 +45,7 @@ class group_manager;
class abstract_tuple; class abstract_tuple;
class actor_registry; class actor_registry;
class network_manager; class network_manager;
class decorated_names_map;
class uniform_type_info_map; class uniform_type_info_map;
class singleton_manager { class singleton_manager {
...@@ -70,6 +71,8 @@ class singleton_manager { ...@@ -70,6 +71,8 @@ class singleton_manager {
static empty_tuple* get_empty_tuple(); static empty_tuple* get_empty_tuple();
static decorated_names_map* get_decorated_names_map();
}; };
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -195,11 +195,12 @@ class group : public channel { ...@@ -195,11 +195,12 @@ class group : public channel {
typedef intrusive_ptr<group> group_ptr; 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 bind_failure
* @throws network_error * @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 } // namespace cppa
......
...@@ -234,8 +234,22 @@ class uniform_type_info { ...@@ -234,8 +234,22 @@ class uniform_type_info {
*/ */
virtual void deserialize(void* instance, deserializer* source) const = 0; 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: 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); uniform_type_info(const std::string& uniform_name);
/** /**
......
...@@ -100,18 +100,13 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> { ...@@ -100,18 +100,13 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> {
} }
void deserialize(void* ptr, deserializer* source) const { void deserialize(void* ptr, deserializer* source) const {
// seek_object() gets the uniform name of the next object in the // throws an exception if the next object in source is not a tree
// stream without modifying the deserializer assert_type_name(source);
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");
}
// ptr is guaranteed to be a pointer of type tree // ptr is guaranteed to be a pointer of type tree
auto tree_ptr = reinterpret_cast<tree*>(ptr); auto tree_ptr = reinterpret_cast<tree*>(ptr);
tree_ptr->root.children.clear(); tree_ptr->root.children.clear();
// workflow is analogous to serialize: begin_object() ... end_object() // workflow is analogous to serialize: begin_object() ... end_object()
source->begin_object(cname); source->begin_object(name());
// recursively deserialize nodes, beginning with root // recursively deserialize nodes, beginning with root
deserialize_node(tree_ptr->root, source); deserialize_node(tree_ptr->root, source);
source->end_object(); source->end_object();
......
This diff is collapsed.
#include <string> #include <string>
#include <dlfcn.h>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include "cppa/opt.hpp"
#include "cppa/cppa.hpp" #include "cppa/cppa.hpp"
#include "type_plugins.hpp"
using namespace std; using namespace std;
using namespace cppa; 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) { 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) ( bool args_valid = argc > 1 && match_stream<string>(argv + 1, argv + argc) (
on_opt('p', "port") >> [&](const string& arg) -> bool { on_opt('p', "port", &desc, "set port") >> rd_arg(port),
if (!(istringstream(arg) >> port)) { on_vopt('h', "help", &desc, "print help") >> print_desc_and_exit(&desc)
cout << "\"" << arg << "\" is not a valid port" << endl;
return false;
}
return true;
}
); );
if (port <= 1024) { if (port <= 1024) {
cout << "no port > 1024 given" << endl; cout << "no port > 1024 given" << endl;
...@@ -54,9 +30,8 @@ int main(int argc, char** argv) { ...@@ -54,9 +30,8 @@ int main(int argc, char** argv) {
string line; string line;
while (getline(cin, line)) { while (getline(cin, line)) {
if (line == "quit") return 0; if (line == "quit") return 0;
else { else cout << "illegal command" << endl;
cout << "illegal command" << endl;
}
} }
shutdown();
return 0; return 0;
} }
#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
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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
...@@ -107,10 +107,10 @@ struct group_nameserver : event_based_actor { ...@@ -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>(); auto gn = spawn_hidden<group_nameserver>();
try { try {
publish(gn, port); publish(gn, port, addr);
} }
catch (std::exception&) { catch (std::exception&) {
gn->enqueue(nullptr, make_any_tuple(atom("SHUTDOWN"))); gn->enqueue(nullptr, make_any_tuple(atom("SHUTDOWN")));
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#else #else
# include <netdb.h> # include <netdb.h>
# include <unistd.h> # include <unistd.h>
# include <arpa/inet.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/socket.h> # include <sys/socket.h>
# include <netinet/in.h> # include <netinet/in.h>
...@@ -97,7 +98,8 @@ bool accept_impl(util::io_stream_ptr_pair& result, native_socket_type fd, bool n ...@@ -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) ipv4_acceptor::ipv4_acceptor(native_socket_type fd, bool nonblocking)
: m_fd(fd), m_is_nonblocking(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; native_socket_type sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == invalid_socket) { if (sockfd == invalid_socket) {
...@@ -112,7 +114,13 @@ std::unique_ptr<util::acceptor> ipv4_acceptor::create(std::uint16_t port) { ...@@ -112,7 +114,13 @@ std::unique_ptr<util::acceptor> ipv4_acceptor::create(std::uint16_t port) {
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
memset((char*) &serv_addr, 0, sizeof(serv_addr)); memset((char*) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; 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); serv_addr.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { if (bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
throw bind_failure(errno); throw bind_failure(errno);
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
using namespace std; using namespace std;
//#define VERBOSE_MIDDLEMAN
#ifdef VERBOSE_MIDDLEMAN
#define DEBUG(arg) { \ #define DEBUG(arg) { \
ostringstream oss; \ ostringstream oss; \
oss << "[process id: " \ oss << "[process id: " \
...@@ -65,9 +68,9 @@ using namespace std; ...@@ -65,9 +68,9 @@ using namespace std;
<< "] " << arg << endl; \ << "] " << arg << endl; \
cout << oss.str(); \ cout << oss.str(); \
} (void) 0 } (void) 0
#else
#undef DEBUG
#define DEBUG(unused) ((void) 0) #define DEBUG(unused) ((void) 0)
#endif
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -235,13 +238,15 @@ class peer_connection : public network_channel { ...@@ -235,13 +238,15 @@ class peer_connection : public network_channel {
bool continue_reading(); bool continue_reading();
bool continue_writing() { 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()) { if (has_unwritten_data()) {
size_t written; size_t written;
written = m_ostream->write_some(m_wr_buf.data(), written = m_ostream->write_some(m_wr_buf.data(),
m_wr_buf.size()); m_wr_buf.size());
if (written != m_wr_buf.size()) { if (written != m_wr_buf.size()) {
m_wr_buf.erase_leading(written); m_wr_buf.erase_leading(written);
DEBUG("only " << written << " bytes written");
} }
else { else {
m_wr_buf.reset(); m_wr_buf.reset();
...@@ -257,17 +262,20 @@ class peer_connection : public network_channel { ...@@ -257,17 +262,20 @@ class peer_connection : public network_channel {
auto before = m_wr_buf.size(); auto before = m_wr_buf.size();
m_wr_buf.write(sizeof(std::uint32_t), &size, util::grow_if_needed); m_wr_buf.write(sizeof(std::uint32_t), &size, util::grow_if_needed);
bs << msg; 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 // update size in buffer
memcpy(m_wr_buf.data() + before, &size, sizeof(std::uint32_t)); memcpy(m_wr_buf.data() + before, &size, sizeof(std::uint32_t));
if (!has_unwritten_data()) { if (!has_unwritten_data()) {
size_t written = m_ostream->write_some(m_wr_buf.data(), size_t written = m_ostream->write_some(m_wr_buf.data(),
m_wr_buf.size()); m_wr_buf.size());
if (written != 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); m_wr_buf.erase_leading(written);
has_unwritten_data(true); has_unwritten_data(true);
} }
else { else {
DEBUG(written << " bytes written");
m_wr_buf.reset(); m_wr_buf.reset();
} }
} }
...@@ -398,6 +406,16 @@ bool peer_connection::continue_reading() { ...@@ -398,6 +406,16 @@ bool peer_connection::continue_reading() {
memcpy(node_id.data(), m_rd_buf.data() + sizeof(uint32_t), memcpy(node_id.data(), m_rd_buf.data() + sizeof(uint32_t),
process_information::node_id_size); process_information::node_id_size);
m_peer.reset(new process_information(process_id, node_id)); 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); parent()->add_peer(*m_peer, this);
// initialization done // initialization done
m_rd_state = wait_for_msg_size; m_rd_state = wait_for_msg_size;
...@@ -698,6 +716,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -698,6 +716,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
maxfd = max(maxfd, fd); maxfd = max(maxfd, fd);
FD_SET(fd, &rdset); 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 (m_peers_with_unwritten_data.empty()) {
if (wrset_ptr) wrset_ptr = nullptr; if (wrset_ptr) wrset_ptr = nullptr;
} }
...@@ -714,8 +743,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -714,8 +743,17 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
auto continue_reading = [&](const network_channel_ptr& ch) { auto continue_reading = [&](const network_channel_ptr& ch) {
bool erase_channel = false; bool erase_channel = false;
try { erase_channel = !ch->continue_reading(); } 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) { catch (exception& e) {
DEBUG(demangle(typeid(e).name()) << ": " << e.what()); DEBUG(demangle(typeid(e)) << ": " << e.what());
erase_channel = true; erase_channel = true;
} }
if (erase_channel) { if (erase_channel) {
...@@ -725,7 +763,9 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -725,7 +763,9 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
}; };
auto continue_writing = [&](const peer_connection_ptr& peer) { auto continue_writing = [&](const peer_connection_ptr& peer) {
bool erase_channel = false; bool erase_channel = false;
try { erase_channel = !peer->continue_writing(); } try {
erase_channel = !peer->continue_writing();
}
catch (exception& e) { catch (exception& e) {
DEBUG(demangle(typeid(e).name()) << ": " << e.what()); DEBUG(demangle(typeid(e).name()) << ": " << e.what());
erase_channel = true; erase_channel = true;
......
...@@ -100,6 +100,14 @@ void tss_reset(local_actor* ptr, bool inc_ref_count = true) { ...@@ -100,6 +100,14 @@ void tss_reset(local_actor* ptr, bool inc_ref_count = true) {
} // namespace <anonymous> } // 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) { void self_type::cleanup_fun(cppa::local_actor* what) {
if (what) { if (what) {
auto ptr = dynamic_cast<thread_mapped_actor*>(what); auto ptr = dynamic_cast<thread_mapped_actor*>(what);
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "cppa/detail/actor_registry.hpp" #include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/network_manager.hpp" #include "cppa/detail/network_manager.hpp"
#include "cppa/detail/singleton_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/thread_pool_scheduler.hpp"
#include "cppa/detail/uniform_type_info_map.hpp" #include "cppa/detail/uniform_type_info_map.hpp"
...@@ -57,6 +58,7 @@ using namespace cppa::detail; ...@@ -57,6 +58,7 @@ using namespace cppa::detail;
//volatile uniform_type_info_map* s_uniform_type_info_map = 0; //volatile uniform_type_info_map* s_uniform_type_info_map = 0;
std::atomic<uniform_type_info_map*> s_uniform_type_info_map; 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<network_manager*> s_network_manager;
std::atomic<actor_registry*> s_actor_registry; std::atomic<actor_registry*> s_actor_registry;
std::atomic<group_manager*> s_group_manager; std::atomic<group_manager*> s_group_manager;
...@@ -121,6 +123,8 @@ void shutdown() { ...@@ -121,6 +123,8 @@ void shutdown() {
s_empty_tuple = nullptr; s_empty_tuple = nullptr;
delete s_uniform_type_info_map.load(); delete s_uniform_type_info_map.load();
s_uniform_type_info_map = nullptr; s_uniform_type_info_map = nullptr;
delete s_decorated_names_map.load();
s_decorated_names_map = nullptr;
} }
} // namespace cppa } // namespace cppa
...@@ -143,6 +147,10 @@ scheduler* singleton_manager::get_scheduler() { ...@@ -143,6 +147,10 @@ scheduler* singleton_manager::get_scheduler() {
return s_scheduler.load(); 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) { bool singleton_manager::set_scheduler(scheduler* ptr) {
scheduler* expected = nullptr; scheduler* expected = nullptr;
if (s_scheduler.compare_exchange_weak(expected, ptr)) { if (s_scheduler.compare_exchange_weak(expected, ptr)) {
......
This diff is collapsed.
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
namespace cppa { namespace cppa {
thread_mapped_actor::thread_mapped_actor() : m_initialized(false) { } thread_mapped_actor::thread_mapped_actor() : m_initialized(true) { }
thread_mapped_actor::thread_mapped_actor(std::function<void()> fun) thread_mapped_actor::thread_mapped_actor(std::function<void()> fun)
: super(std::move(fun)), m_initialized(false) { } : super(std::move(fun)), m_initialized(false) { }
......
This diff is collapsed.
...@@ -57,10 +57,6 @@ ...@@ -57,10 +57,6 @@
#include "cppa/detail/actor_proxy_cache.hpp" #include "cppa/detail/actor_proxy_cache.hpp"
#include "cppa/detail/singleton_manager.hpp" #include "cppa/detail/singleton_manager.hpp"
using std::cout;
using std::endl;
namespace cppa { namespace cppa {
void publish(actor_ptr whom, std::unique_ptr<util::acceptor> acceptor) { 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) { ...@@ -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_pid, sizeof(std::uint32_t));
peer.first->read(peer_node_id.data(), peer_node_id.size()); peer.first->read(peer_node_id.data(), peer_node_id.size());
process_information_ptr pinfptr(new process_information(peer_pid, peer_node_id)); 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()); //auto key = std::make_tuple(remote_actor_id, pinfptr->process_id(), pinfptr->node_id());
detail::middleman_add_peer(peer, pinfptr); detail::middleman_add_peer(peer, pinfptr);
return detail::get_actor_proxy_cache().get_or_put(remote_actor_id, 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) { ...@@ -89,8 +93,8 @@ actor_ptr remote_actor(util::io_stream_ptr_pair peer) {
pinfptr->node_id()); pinfptr->node_id());
} }
void publish(actor_ptr whom, std::uint16_t port) { void publish(actor_ptr whom, std::uint16_t port, const char* addr) {
if (whom) publish(whom, detail::ipv4_acceptor::create(port)); if (whom) publish(whom, detail::ipv4_acceptor::create(port, addr));
} }
actor_ptr remote_actor(const char* host, std::uint16_t port) { actor_ptr remote_actor(const char* host, std::uint16_t port) {
......
This diff is collapsed.
...@@ -236,7 +236,7 @@ int main(int argc, char** argv) { ...@@ -236,7 +236,7 @@ int main(int argc, char** argv) {
bool success = false; bool success = false;
do { do {
try { try {
publish(self, port); publish(self, port, "127.0.0.1");
success = true; success = true;
} }
catch (bind_failure&) { catch (bind_failure&) {
......
...@@ -50,17 +50,14 @@ ...@@ -50,17 +50,14 @@
#include "cppa/detail/ptype_to_type.hpp" #include "cppa/detail/ptype_to_type.hpp"
#include "cppa/detail/default_uniform_type_info_impl.hpp" #include "cppa/detail/default_uniform_type_info_impl.hpp"
using std::cout; using namespace std;
using std::cerr;
using std::endl;
using namespace cppa; using namespace cppa;
using namespace cppa::util; using namespace cppa::util;
using cppa::detail::type_to_ptype; using cppa::detail::type_to_ptype;
using cppa::detail::ptype_to_type; 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 { struct struct_a {
int x; int x;
...@@ -78,7 +75,7 @@ bool operator!=(const struct_a& lhs, const struct_a& rhs) { ...@@ -78,7 +75,7 @@ bool operator!=(const struct_a& lhs, const struct_a& rhs) {
struct struct_b { struct struct_b {
struct_a a; struct_a a;
int z; int z;
std::list<int> ints; list<int> ints;
}; };
bool operator==(const struct_b& lhs, const struct_b& rhs) { bool operator==(const struct_b& lhs, const struct_b& rhs) {
...@@ -89,11 +86,11 @@ 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); return !(lhs == rhs);
} }
typedef std::map<std::string, std::u16string> strmap; typedef map<string, u16string> strmap;
struct struct_c { struct struct_c {
strmap strings; strmap strings;
std::set<int> ints; set<int> ints;
}; };
bool operator==(const struct_c& lhs, const struct_c& rhs) { bool operator==(const struct_c& lhs, const struct_c& rhs) {
...@@ -106,36 +103,97 @@ 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\"!" ) } ))__"; 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() { int main() {
CPPA_TEST(test__serialization); CPPA_TEST(test__serialization);
announce(typeid(raw_struct), new raw_struct_type_info);
auto oarr = new detail::object_array; 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" )); oarr->push_back(object::from("foo" ));
any_tuple atuple1(oarr); any_tuple atuple1(oarr);
try { try {
auto opt = tuple_cast<std::uint32_t, std::string>(atuple1); auto opt = tuple_cast<uint32_t, string>(atuple1);
CPPA_CHECK(opt.valid()); CPPA_CHECK(opt.valid());
if (opt) { if (opt) {
auto& tup = *opt; auto& tup = *opt;
CPPA_CHECK_EQUAL(tup.size(), static_cast<size_t>(2)); 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"); CPPA_CHECK_EQUAL(get<1>(tup), "foo");
} }
} }
catch (std::exception& e) { catch (exception& e) {
CPPA_ERROR("exception: " << e.what()); 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)); any_tuple ttup = make_cow_tuple(1, 2, actor_ptr(self));
util::buffer wr_buf; util::buffer wr_buf;
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << ttup; bs << ttup;
bs << ttup;
binary_deserializer bd(wr_buf.data(), wr_buf.size()); binary_deserializer bd(wr_buf.data(), wr_buf.size());
any_tuple ttup2; any_tuple ttup2;
any_tuple ttup3;
uniform_typeid<any_tuple>()->deserialize(&ttup2, &bd); 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 // serialize b1 to buf
...@@ -147,7 +205,7 @@ int main() { ...@@ -147,7 +205,7 @@ int main() {
any_tuple atuple2; any_tuple atuple2;
uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd); uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd);
try { try {
auto opt = tuple_cast<std::uint32_t, std::string>(atuple2); auto opt = tuple_cast<uint32_t, string>(atuple2);
CPPA_CHECK(opt.valid()); CPPA_CHECK(opt.valid());
if (opt.valid()) { if (opt.valid()) {
auto& tup = *opt; auto& tup = *opt;
...@@ -156,12 +214,12 @@ int main() { ...@@ -156,12 +214,12 @@ int main() {
CPPA_CHECK_EQUAL(get<1>(tup), "foo"); CPPA_CHECK_EQUAL(get<1>(tup), "foo");
} }
} }
catch (std::exception& e) { catch (exception& e) {
CPPA_ERROR("exception: " << e.what()); CPPA_ERROR("exception: " << e.what());
} }
} }
{ {
any_tuple msg1 = cppa::make_cow_tuple(42, std::string("Hello \"World\"!")); any_tuple msg1 = cppa::make_cow_tuple(42, string("Hello \"World\"!"));
auto msg1_tostring = to_string(msg1); auto msg1_tostring = to_string(msg1);
if (msg1str != msg1_tostring) { if (msg1str != msg1_tostring) {
CPPA_ERROR("msg1str != to_string(msg1)"); CPPA_ERROR("msg1str != to_string(msg1)");
...@@ -178,8 +236,8 @@ int main() { ...@@ -178,8 +236,8 @@ int main() {
if (typeid(any_tuple) == *(obj1.type()) && obj2.type() == obj1.type()) { if (typeid(any_tuple) == *(obj1.type()) && obj2.type() == obj1.type()) {
auto& content1 = get<any_tuple>(obj1); auto& content1 = get<any_tuple>(obj1);
auto& content2 = get<any_tuple>(obj2); auto& content2 = get<any_tuple>(obj2);
auto opt1 = tuple_cast<decltype(42), std::string>(content1); auto opt1 = tuple_cast<decltype(42), string>(content1);
auto opt2 = tuple_cast<decltype(42), std::string>(content2); auto opt2 = tuple_cast<decltype(42), string>(content2);
CPPA_CHECK(opt1.valid() && opt2.valid()); CPPA_CHECK(opt1.valid() && opt2.valid());
if (opt1.valid() && opt2.valid()) { if (opt1.valid() && opt2.valid()) {
auto& tup1 = *opt1; auto& tup1 = *opt1;
...@@ -198,18 +256,18 @@ int main() { ...@@ -198,18 +256,18 @@ int main() {
} }
CPPA_CHECK((is_iterable<int>::value) == false); CPPA_CHECK((is_iterable<int>::value) == false);
// std::string is primitive and thus not identified by is_iterable // string is primitive and thus not identified by is_iterable
CPPA_CHECK((is_iterable<std::string>::value) == false); CPPA_CHECK((is_iterable<string>::value) == false);
CPPA_CHECK((is_iterable<std::list<int>>::value) == true); CPPA_CHECK((is_iterable<list<int>>::value) == true);
CPPA_CHECK((is_iterable<std::map<int,int>>::value) == true); CPPA_CHECK((is_iterable<map<int,int>>::value) == true);
{ // test meta_object implementation for primitive types { // 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); CPPA_CHECK(meta_int != nullptr);
if (meta_int) { if (meta_int) {
auto o = meta_int->create(); auto o = meta_int->create();
get_ref<std::uint32_t>(o) = 42; get_ref<uint32_t>(o) = 42;
auto str = to_string(get<std::uint32_t>(o)); auto str = cppa::to_string(get<uint32_t>(o));
CPPA_CHECK_EQUAL(str, "@u32 ( 42 )"); CPPA_CHECK_EQUAL( "@u32 ( 42 )", str);
} }
} }
{ // test serializers / deserializers with struct_b { // test serializers / deserializers with struct_b
...@@ -220,7 +278,7 @@ int main() { ...@@ -220,7 +278,7 @@ int main() {
&struct_b::z, &struct_b::z,
&struct_b::ints); &struct_b::ints);
// testees // 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 b2;
struct_b b3; struct_b b3;
// expected result of to_string(&b1, meta_b) // expected result of to_string(&b1, meta_b)
...@@ -253,7 +311,7 @@ int main() { ...@@ -253,7 +311,7 @@ int main() {
// get meta type of struct_c and "announce" // get meta type of struct_c and "announce"
announce<struct_c>(&struct_c::strings, &struct_c::ints); announce<struct_c>(&struct_c::strings, &struct_c::ints);
// testees // testees
struct_c c1{strmap{{"abc", u"cba" }, { "x", u"y" }}, std::set<int>{9, 4, 5}}; struct_c c1{strmap{{"abc", u"cba" }, { "x", u"y" }}, set<int>{9, 4, 5}};
struct_c c2; { struct_c c2; {
// serialize c1 to buf // serialize c1 to buf
util::buffer wr_buf; util::buffer wr_buf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment