Commit 58d3373d authored by Dominik Charousset's avatar Dominik Charousset

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

parents 783b2413 960ee90e
...@@ -160,14 +160,19 @@ if (NOT DISABLE_CONTEXT_SWITCHING) ...@@ -160,14 +160,19 @@ if (NOT DISABLE_CONTEXT_SWITCHING)
) )
endif () endif ()
find_package(Boost COMPONENTS thread REQUIRED) if (BOOST_ROOT)
# Prevent falling back to system paths when using a custom Boost prefix.
set(Boost_NO_SYSTEM_PATHS true)
endif ()
find_package(Boost REQUIRED)
find_package(PTHREAD REQUIRED)
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
include_directories(. ${Boost_INCLUDE_DIRS} ${boost_context}/include) include_directories(. ${Boost_INCLUDE_DIRS} ${boost_context}/include ${PTHREAD_INCLUDE_DIR})
add_library(libcppa SHARED ${LIBCPPA_SRC}) add_library(libcppa SHARED ${LIBCPPA_SRC})
target_link_libraries(libcppa ${CMAKE_LD_LIBS} ${Boost_THREAD_LIBRARY}) target_link_libraries(libcppa ${CMAKE_LD_LIBS} ${Boost_THREAD_LIBRARY} ${PTHREAD_LIBRARIES})
set(LIBRARY_VERSION ${LIBCPPA_VERSION_MAJOR}.${LIBCPPA_VERSION_MINOR}.${LIBCPPA_VERSION_PATCH}) set(LIBRARY_VERSION ${LIBCPPA_VERSION_MAJOR}.${LIBCPPA_VERSION_MINOR}.${LIBCPPA_VERSION_PATCH})
set(LIBRARY_SOVERSION ${LIBCPPA_VERSION_MAJOR}) set(LIBRARY_SOVERSION ${LIBCPPA_VERSION_MAJOR})
......
Version 0.4.2
2012-XX-XX
- Bugfix: evaluate `errno` whenever select() fails and handle errors properly
Version 0.4.1 Version 0.4.1
2012-08-22 2012-08-22
......
# - Find pthread
# Find the native PTHREAD headers and libraries.
#
# PTHREAD_INCLUDE_DIR - where to find pthread.h, etc.
# PTHREAD_LIBRARIES - List of libraries when using pthread.
# PTHREAD_FOUND - True if pthread found.
GET_FILENAME_COMPONENT(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH )
# Look for the header file.
FIND_PATH(PTHREAD_INCLUDE_DIR NAMES pthread.h
PATHS $ENV{H3D_EXTERNAL_ROOT}/include
$ENV{H3D_EXTERNAL_ROOT}/include/pthread
$ENV{H3D_ROOT}/../External/include
$ENV{H3D_ROOT}/../External/include/pthread
../../External/include
../../External/include/pthread
${module_file_path}/../../../External/include
${module_file_path}/../../../External/include/pthread)
MARK_AS_ADVANCED(PTHREAD_INCLUDE_DIR)
# Look for the library.
IF(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthreadVC2
PATHS $ENV{H3D_EXTERNAL_ROOT}/lib
$ENV{H3D_ROOT}/../External/lib
../../External/lib
${module_file_path}/../../../External/lib)
ELSE(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread)
ENDIF(WIN32)
MARK_AS_ADVANCED(PTHREAD_LIBRARY)
# Copy the results to the output variables.
IF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 1)
SET(PTHREAD_LIBRARIES ${PTHREAD_LIBRARY})
SET(PTHREAD_INCLUDE_DIR ${PTHREAD_INCLUDE_DIR})
ELSE(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 0)
SET(PTHREAD_LIBRARIES)
SET(PTHREAD_INCLUDE_DIR)
ENDIF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
# Report the results.
IF(NOT PTHREAD_FOUND)
SET(PTHREAD_DIR_MESSAGE
"PTHREAD was not found. Make sure PTHREAD_LIBRARY and PTHREAD_INCLUDE_DIR are set. Pthread is required to compile.")
IF(PTHREAD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "${PTHREAD_DIR_MESSAGE}")
ELSEIF(NOT PTHREAD_FIND_QUIETLY)
MESSAGE(STATUS "${PTHREAD_DIR_MESSAGE}")
ENDIF(PTHREAD_FIND_REQUIRED)
ENDIF(NOT PTHREAD_FOUND)
...@@ -9,7 +9,7 @@ network transparent messaging, and more. ...@@ -9,7 +9,7 @@ network transparent messaging, and more.
On the Web On the Web
---------- ----------
* __Blog__: http://libcppa.blogspot.com * __Blog__: http://libcppa.org
* __Manual (PDF)__: http://neverlord.github.com/libcppa/manual/manual.pdf * __Manual (PDF)__: http://neverlord.github.com/libcppa/manual/manual.pdf
* __Manual (HTML)__: http://neverlord.github.com/libcppa/manual/index.html * __Manual (HTML)__: http://neverlord.github.com/libcppa/manual/index.html
* __Documentation__: http://neverlord.github.com/libcppa/ * __Documentation__: http://neverlord.github.com/libcppa/
......
...@@ -15,12 +15,13 @@ if(NOT cppa_LIBRARY) ...@@ -15,12 +15,13 @@ if(NOT cppa_LIBRARY)
find_package(Libcppa REQUIRED) find_package(Libcppa REQUIRED)
endif (NOT cppa_LIBRARY) endif (NOT cppa_LIBRARY)
find_package(Boost COMPONENTS thread REQUIRED) find_package(Boost REQUIRED)
find_package(PTHREAD REQUIRED)
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
include_directories(. ${cppa_INCLUDE} ${Boost_INCLUDE_DIRS}) include_directories(. ${cppa_INCLUDE} ${Boost_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIR})
set(benchmark_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${Boost_THREAD_LIBRARY}) set(benchmark_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${Boost_THREAD_LIBRARY} ${PTHREAD_LIBRARIES})
target_link_libraries(actor_creation ${benchmark_LIBS}) target_link_libraries(actor_creation ${benchmark_LIBS})
target_link_libraries(mailbox_performance ${benchmark_LIBS}) target_link_libraries(mailbox_performance ${benchmark_LIBS})
......
# - Find pthread
# Find the native PTHREAD headers and libraries.
#
# PTHREAD_INCLUDE_DIR - where to find pthread.h, etc.
# PTHREAD_LIBRARIES - List of libraries when using pthread.
# PTHREAD_FOUND - True if pthread found.
GET_FILENAME_COMPONENT(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH )
# Look for the header file.
FIND_PATH(PTHREAD_INCLUDE_DIR NAMES pthread.h
PATHS $ENV{H3D_EXTERNAL_ROOT}/include
$ENV{H3D_EXTERNAL_ROOT}/include/pthread
$ENV{H3D_ROOT}/../External/include
$ENV{H3D_ROOT}/../External/include/pthread
../../External/include
../../External/include/pthread
${module_file_path}/../../../External/include
${module_file_path}/../../../External/include/pthread)
MARK_AS_ADVANCED(PTHREAD_INCLUDE_DIR)
# Look for the library.
IF(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthreadVC2
PATHS $ENV{H3D_EXTERNAL_ROOT}/lib
$ENV{H3D_ROOT}/../External/lib
../../External/lib
${module_file_path}/../../../External/lib)
ELSE(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread)
ENDIF(WIN32)
MARK_AS_ADVANCED(PTHREAD_LIBRARY)
# Copy the results to the output variables.
IF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 1)
SET(PTHREAD_LIBRARIES ${PTHREAD_LIBRARY})
SET(PTHREAD_INCLUDE_DIR ${PTHREAD_INCLUDE_DIR})
ELSE(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 0)
SET(PTHREAD_LIBRARIES)
SET(PTHREAD_INCLUDE_DIR)
ENDIF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
# Report the results.
IF(NOT PTHREAD_FOUND)
SET(PTHREAD_DIR_MESSAGE
"PTHREAD was not found. Make sure PTHREAD_LIBRARY and PTHREAD_INCLUDE_DIR are set. Pthread is required to compile.")
IF(PTHREAD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "${PTHREAD_DIR_MESSAGE}")
ELSEIF(NOT PTHREAD_FIND_QUIETLY)
MESSAGE(STATUS "${PTHREAD_DIR_MESSAGE}")
ENDIF(PTHREAD_FIND_REQUIRED)
ENDIF(NOT PTHREAD_FOUND)
...@@ -58,6 +58,23 @@ struct projection_helper { ...@@ -58,6 +58,23 @@ struct projection_helper {
} }
}; };
template<class PartialFun>
struct result_fetching_projection_helper {
typedef typename PartialFun::result_type result_type;
const PartialFun& fun;
result_type& result;
result_fetching_projection_helper(const PartialFun& pfun, result_type& res)
: fun(pfun), result(res) { }
template<typename... Args>
bool operator()(Args&&... args) const {
if (fun.defined_at(std::forward<Args>(args)...)) {
result = fun(std::forward<Args>(args)...);
return true;
}
return false;
}
};
/** /**
* @brief Projection implemented by a set of functors. * @brief Projection implemented by a set of functors.
*/ */
...@@ -103,6 +120,31 @@ class projection { ...@@ -103,6 +120,31 @@ class projection {
return false; return false;
} }
template<class PartialFun>
bool invoke(PartialFun& fun, typename PartialFun::result_type& result, Args... args) const {
typedef typename PartialFun::result_type result_type;
typedef typename util::tl_zip<
typename util::tl_map<
ProjectionFuns,
util::get_result_type,
util::rm_option
>::type,
typename util::tl_map<
util::type_list<Args...>,
mutable_gref_wrapped
>::type,
util::left_or_right
>::type
collected_args;
typename tdata_from_type_list<collected_args>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...)) {
result_fetching_projection_helper<PartialFun> helper{fun, result};
return util::unchecked_apply_tuple<bool>(helper, pargs);
}
return false;
}
private: private:
template<typename Storage, typename T> template<typename Storage, typename T>
......
...@@ -31,11 +31,17 @@ ...@@ -31,11 +31,17 @@
#ifndef CPPA_MATCH_HPP #ifndef CPPA_MATCH_HPP
#define CPPA_MATCH_HPP #define CPPA_MATCH_HPP
#include <vector>
#include <istream>
#include <iterator>
#include <type_traits> #include <type_traits>
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct match_helper { struct match_helper {
...@@ -126,6 +132,165 @@ struct pmatch_each_helper { ...@@ -126,6 +132,165 @@ struct pmatch_each_helper {
} }
}; };
// Case is a projection_partial_function_pair
template<typename T, typename InputIterator, class Case>
size_t run_case(std::vector<T>& vec,
bool& match_returned_false,
InputIterator& pos,
const InputIterator& end,
Case& target);
template<size_t N, size_t Size>
struct unwind_and_call {
typedef unwind_and_call<N+1,Size> next;
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, vec, std::forward<Unwinded>(args)..., vec[N]);
}
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, sub_result, vec, std::forward<Unwinded>(args)..., vec[N]);
}
template<typename T, typename InputIterator, class MatchExpr>
static inline bool _(std::vector<T>& vec, InputIterator& pos, InputIterator end, MatchExpr& ex) {
bool match_returned_false = false;
if (run_case(vec, match_returned_false, pos, end, get<N>(ex.cases())) == 0) {
if (match_returned_false) {
return false;
}
return next::_(vec, pos, end, ex);
}
return true;
}
};
template<size_t Size>
struct unwind_and_call<Size, Size> {
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, std::vector<T>&, Unwinded&&... args) {
return target.first(target.second, std::forward<Unwinded>(args)...);
}
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>&, Unwinded&&... args) {
return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...);
}
template<typename T, typename... Args>
static inline bool _(std::vector<T>&, Args&&...) { return false; }
};
template<bool EvaluateSubResult> // default = false
struct run_case_impl {
template<class Case, typename T>
static inline bool _(Case& target, std::vector<T>& vec, bool&) {
return unwind_and_call<0, Case::pattern_type::size>::_(target, vec);
}
};
template<>
struct run_case_impl<true> {
template<class Case, typename T>
static inline bool _(Case& target, std::vector<T>& vec, bool& match_returned_false) {
bool sub_result;
if (unwind_and_call<0, Case::pattern_type::size>::_(target, sub_result, vec)) {
if (sub_result == false) {
match_returned_false = true;
}
return true;
}
return false;
}
};
// Case is a projection_partial_function_pair
template<typename T, typename InputIterator, class Case>
size_t run_case(std::vector<T>& vec,
bool& match_returned_false,
InputIterator& pos,
const InputIterator& end,
Case& target) {
static constexpr size_t num_args = Case::pattern_type::size;
typedef typename Case::second_type partial_fun_type;
typedef typename partial_fun_type::result_type result_type;
typedef typename partial_fun_type::arg_types arg_types;
typedef typename util::tl_map<arg_types, util::rm_ref>::type plain_args;
static_assert(num_args > 0,
"empty match expressions are not allowed in stream matching");
static_assert(util::tl_forall<plain_args, util::tbind<std::is_same, T>::template type>::value,
"match_stream<T>: at least one callback argument "
" is not of type T");
while (vec.size() < num_args) {
if (pos == end) {
return 0;
}
vec.emplace_back(*pos++);
}
if (run_case_impl<std::is_same<result_type, bool>::value>::_(target, vec, match_returned_false)) {
if (vec.size() == num_args) {
vec.clear();
}
else {
auto i = vec.begin();
vec.erase(i, i + num_args);
}
return match_returned_false ? 0 : num_args;
}
return 0;
}
template<typename T, typename InputIterator>
class stream_matcher {
public:
typedef InputIterator iter;
stream_matcher(iter first, iter last) : m_pos(first), m_end(last) { }
template<typename... Cases>
bool operator()(match_expr<Cases...>& expr) {
while (m_pos != m_end) {
if (!unwind_and_call<0, match_expr<Cases...>::cases_list::size>::_(m_cache, m_pos, m_end, expr)) {
return false;
}
}
return true;
}
template<typename... Cases>
bool operator()(match_expr<Cases...>&& expr) {
auto tmp = std::move(expr);
return (*this)(tmp);
}
template<typename... Cases>
bool operator()(const match_expr<Cases...>& expr) {
auto tmp = expr;
return (*this)(tmp);
}
template<typename Arg0, typename... Args>
bool operator()(Arg0&& arg0, Args&&... args) {
return (*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
}
private:
iter m_pos;
iter m_end;
std::vector<T> m_cache;
};
} } // namespace cppa::detail } } // namespace cppa::detail
namespace cppa { namespace cppa {
...@@ -199,6 +364,19 @@ auto match_each(InputIterator first, InputIterator last, Projection proj) ...@@ -199,6 +364,19 @@ auto match_each(InputIterator first, InputIterator last, Projection proj)
return {first, last, std::move(proj)}; return {first, last, std::move(proj)};
} }
template<typename T>
detail::stream_matcher<T, std::istream_iterator<T> > match_stream(std::istream& stream) {
std::istream_iterator<T> first(stream);
std::istream_iterator<T> last; // 'end of stream' iterator
return {first, last};
}
template<typename T, typename InputIterator>
detail::stream_matcher<T, InputIterator> match_stream(InputIterator first,
InputIterator last ) {
return {first, last};
}
} // namespace cppa } // namespace cppa
#endif // CPPA_MATCH_HPP #endif // CPPA_MATCH_HPP
...@@ -876,6 +876,35 @@ inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs, ...@@ -876,6 +876,35 @@ inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs,
return lhs.or_else(rhs); return lhs.or_else(rhs);
} }
template<typename Arg0, typename... Args>
typename match_expr_from_type_list<
typename util::tl_concat<
typename Arg0::cases_list,
typename Args::cases_list...
>::type
>::type
match_expr_collect(const Arg0& arg0, const Args&... args) {
typedef typename match_expr_from_type_list<
typename util::tl_concat<
typename Arg0::cases_list,
typename Args::cases_list...
>::type
>::type
combined_type;
typename detail::tdata_from_type_list<
typename util::tl_map<
typename util::tl_concat<
typename Arg0::cases_list,
typename Args::cases_list...
>::type,
gref_wrapped
>::type
>::type
all_cases;
detail::collect_tdata(all_cases, arg0.cases(), args.cases()...);
return {all_cases};
}
template<bool HasTimeout> template<bool HasTimeout>
struct match_expr_concat_impl { struct match_expr_concat_impl {
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
......
...@@ -62,6 +62,8 @@ class tpartial_function { ...@@ -62,6 +62,8 @@ class tpartial_function {
static constexpr bool manipulates_args = static constexpr bool manipulates_args =
util::tl_exists<arg_types, util::is_mutable_ref>::value; util::tl_exists<arg_types, util::is_mutable_ref>::value;
typedef Result result_type;
template<typename Fun, typename... G> template<typename Fun, typename... G>
tpartial_function(Fun&& fun, G&&... guard_args) tpartial_function(Fun&& fun, G&&... guard_args)
: m_guard(std::forward<G>(guard_args)...) : m_guard(std::forward<G>(guard_args)...)
...@@ -80,7 +82,7 @@ class tpartial_function { ...@@ -80,7 +82,7 @@ class tpartial_function {
return m_guard(args...); return m_guard(args...);
} }
Result operator()(Args... args) const { result_type operator()(Args... args) const {
return util::apply_args<Result, ctrait_args::size, sizeof...(Args)> return util::apply_args<Result, ctrait_args::size, sizeof...(Args)>
::_(m_expr, args...); ::_(m_expr, args...);
} }
......
...@@ -21,12 +21,13 @@ if(NOT cppa_LIBRARY) ...@@ -21,12 +21,13 @@ if(NOT cppa_LIBRARY)
find_package(Libcppa REQUIRED) find_package(Libcppa REQUIRED)
endif (NOT cppa_LIBRARY) endif (NOT cppa_LIBRARY)
find_package(Boost COMPONENTS thread REQUIRED) find_package(Boost REQUIRED)
find_package(PTHREAD REQUIRED)
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
include_directories(. ${CPPA_INCLUDE} ${Boost_INCLUDE_DIRS}) include_directories(. ${CPPA_INCLUDE} ${Boost_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIR})
set(EXAMPLE_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${Boost_THREAD_LIBRARY}) set(EXAMPLE_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${PTHREAD_LIBRARIES})
target_link_libraries(announce_example_1 ${EXAMPLE_LIBS}) target_link_libraries(announce_example_1 ${EXAMPLE_LIBS})
target_link_libraries(announce_example_2 ${EXAMPLE_LIBS}) target_link_libraries(announce_example_2 ${EXAMPLE_LIBS})
......
# - Find pthread
# Find the native PTHREAD headers and libraries.
#
# PTHREAD_INCLUDE_DIR - where to find pthread.h, etc.
# PTHREAD_LIBRARIES - List of libraries when using pthread.
# PTHREAD_FOUND - True if pthread found.
GET_FILENAME_COMPONENT(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH )
# Look for the header file.
FIND_PATH(PTHREAD_INCLUDE_DIR NAMES pthread.h
PATHS $ENV{H3D_EXTERNAL_ROOT}/include
$ENV{H3D_EXTERNAL_ROOT}/include/pthread
$ENV{H3D_ROOT}/../External/include
$ENV{H3D_ROOT}/../External/include/pthread
../../External/include
../../External/include/pthread
${module_file_path}/../../../External/include
${module_file_path}/../../../External/include/pthread)
MARK_AS_ADVANCED(PTHREAD_INCLUDE_DIR)
# Look for the library.
IF(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthreadVC2
PATHS $ENV{H3D_EXTERNAL_ROOT}/lib
$ENV{H3D_ROOT}/../External/lib
../../External/lib
${module_file_path}/../../../External/lib)
ELSE(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread)
ENDIF(WIN32)
MARK_AS_ADVANCED(PTHREAD_LIBRARY)
# Copy the results to the output variables.
IF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 1)
SET(PTHREAD_LIBRARIES ${PTHREAD_LIBRARY})
SET(PTHREAD_INCLUDE_DIR ${PTHREAD_INCLUDE_DIR})
ELSE(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 0)
SET(PTHREAD_LIBRARIES)
SET(PTHREAD_INCLUDE_DIR)
ENDIF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
# Report the results.
IF(NOT PTHREAD_FOUND)
SET(PTHREAD_DIR_MESSAGE
"PTHREAD was not found. Make sure PTHREAD_LIBRARY and PTHREAD_INCLUDE_DIR are set. Pthread is required to compile.")
IF(PTHREAD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "${PTHREAD_DIR_MESSAGE}")
ELSEIF(NOT PTHREAD_FIND_QUIETLY)
MESSAGE(STATUS "${PTHREAD_DIR_MESSAGE}")
ENDIF(PTHREAD_FIND_REQUIRED)
ENDIF(NOT PTHREAD_FOUND)
...@@ -109,6 +109,7 @@ binary_serializer::binary_serializer(util::buffer* buf) ...@@ -109,6 +109,7 @@ binary_serializer::binary_serializer(util::buffer* buf)
} }
void binary_serializer::begin_object(const std::string& tname) { void binary_serializer::begin_object(const std::string& tname) {
/*
if (++m_obj_count == 1) { if (++m_obj_count == 1) {
// store a dummy size in the buffer that is // store a dummy size in the buffer that is
// eventually updated on matching end_object() // eventually updated on matching end_object()
...@@ -116,10 +117,12 @@ void binary_serializer::begin_object(const std::string& tname) { ...@@ -116,10 +117,12 @@ void binary_serializer::begin_object(const std::string& tname) {
std::uint32_t dummy_size = 0; std::uint32_t dummy_size = 0;
m_sink->write(sizeof(std::uint32_t), &dummy_size, util::grow_if_needed); m_sink->write(sizeof(std::uint32_t), &dummy_size, util::grow_if_needed);
} }
*/
binary_writer::write_string(m_sink, tname); binary_writer::write_string(m_sink, tname);
} }
void binary_serializer::end_object() { void binary_serializer::end_object() {
/*
if (--m_obj_count == 0) { if (--m_obj_count == 0) {
// update the size in the buffer // update the size in the buffer
auto data = m_sink->data(); auto data = m_sink->data();
...@@ -128,6 +131,7 @@ void binary_serializer::end_object() { ...@@ -128,6 +131,7 @@ void binary_serializer::end_object() {
auto wr_pos = data + m_begin_pos; auto wr_pos = data + m_begin_pos;
memcpy(wr_pos, &s, sizeof(std::uint32_t)); memcpy(wr_pos, &s, sizeof(std::uint32_t));
} }
*/
} }
void binary_serializer::begin_sequence(size_t list_size) { void binary_serializer::begin_sequence(size_t list_size) {
......
...@@ -99,13 +99,17 @@ ipv4_acceptor::ipv4_acceptor(native_socket_type fd, bool nonblocking) ...@@ -99,13 +99,17 @@ ipv4_acceptor::ipv4_acceptor(native_socket_type fd, bool 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) {
native_socket_type sockfd; native_socket_type sockfd;
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0); sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == invalid_socket) { if (sockfd == invalid_socket) {
throw network_error("could not create server socket"); throw network_error("could not create server socket");
} }
// sguard closes the socket in case of exception // sguard closes the socket in case of exception
socket_guard sguard(sockfd); socket_guard sguard(sockfd);
int on = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
detail::throw_io_failure("unable to set SO_REUSEADDR");
}
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; serv_addr.sin_addr.s_addr = INADDR_ANY;
......
...@@ -253,7 +253,13 @@ class peer_connection : public network_channel { ...@@ -253,7 +253,13 @@ class peer_connection : public network_channel {
void write(const addressed_message& msg) { void write(const addressed_message& msg) {
binary_serializer bs(&m_wr_buf); binary_serializer bs(&m_wr_buf);
std::uint32_t size = 0;
auto before = m_wr_buf.size();
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);
// update size in buffer
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());
...@@ -683,7 +689,7 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -683,7 +689,7 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
fd_set wrset; fd_set wrset;
fd_set* wrset_ptr = nullptr; fd_set* wrset_ptr = nullptr;
m_channels.emplace_back(new middleman_overseer(this, pipe_fd, queue)); m_channels.emplace_back(new middleman_overseer(this, pipe_fd, queue));
do { auto update_fd_sets = [&] {
FD_ZERO(&rdset); FD_ZERO(&rdset);
maxfd = 0; maxfd = 0;
CPPA_REQUIRE(m_channels.size() > 0); CPPA_REQUIRE(m_channels.size() > 0);
...@@ -704,56 +710,40 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -704,56 +710,40 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
wrset_ptr = &wrset; wrset_ptr = &wrset;
} }
CPPA_REQUIRE(maxfd > 0); CPPA_REQUIRE(maxfd > 0);
//DEBUG("select()"); };
int sresult; auto continue_reading = [&](const network_channel_ptr& ch) {
do { bool erase_channel = false;
sresult = select(maxfd + 1, &rdset, wrset_ptr, nullptr, nullptr); try { erase_channel = !ch->continue_reading(); }
if (sresult < 0) { catch (exception& e) {
CPPA_CRITICAL("select() failed"); DEBUG(demangle(typeid(e).name()) << ": " << e.what());
} erase_channel = true;
} }
while (sresult == 0); if (erase_channel) {
//DEBUG("continue reading ..."); DEBUG("erase worker");
{ // iterate over all channels and remove channels as needed m_erased_channels.insert(ch);
for (auto& channel : m_channels) {
if (FD_ISSET(channel->read_handle(), &rdset)) {
bool erase_channel = false;
try { erase_channel = !channel->continue_reading(); }
catch (exception& e) {
DEBUG(demangle(typeid(e).name()) << ": " << e.what());
erase_channel = true;
}
if (erase_channel) {
DEBUG("erase worker");
m_erased_channels.insert(channel);
}
}
}
} }
if (wrset_ptr) { // iterate over peers with unwritten data };
DEBUG("continue writing ..."); auto continue_writing = [&](const peer_connection_ptr& peer) {
for (auto& peer : m_peers_with_unwritten_data) { bool erase_channel = false;
if (FD_ISSET(peer->write_handle(), &wrset)) { try { erase_channel = !peer->continue_writing(); }
bool erase_channel = false; catch (exception& e) {
try { erase_channel = !peer->continue_writing(); } DEBUG(demangle(typeid(e).name()) << ": " << e.what());
catch (exception& e) { erase_channel = true;
DEBUG(demangle(typeid(e).name()) << ": " << e.what());
erase_channel = true;
}
if (erase_channel) {
DEBUG("erase worker");
m_erased_channels.insert(peer);
}
}
}
} }
// insert new handlers if (erase_channel) {
DEBUG("erase worker");
m_erased_channels.insert(peer);
}
};
auto insert_new_handlers = [&] {
if (m_new_channels.empty() == false) { if (m_new_channels.empty() == false) {
DEBUG("insert new channel(s)"); DEBUG("insert new channel(s)");
move(m_new_channels.begin(), m_new_channels.end(), move(m_new_channels.begin(), m_new_channels.end(),
back_inserter(m_channels)); back_inserter(m_channels));
m_new_channels.clear(); m_new_channels.clear();
} }
};
auto erase_erroneous_channels = [&] {
if (!m_erased_channels.empty()) { if (!m_erased_channels.empty()) {
DEBUG("erase channel(s)"); DEBUG("erase channel(s)");
// erase all marked channels // erase all marked channels
...@@ -766,6 +756,76 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) { ...@@ -766,6 +756,76 @@ void middleman::operator()(int pipe_fd, middleman_queue& queue) {
} }
m_erased_channels.clear(); m_erased_channels.clear();
} }
};
do {
update_fd_sets();
//DEBUG("select()");
int sresult;
do {
sresult = select(maxfd + 1, &rdset, wrset_ptr, nullptr, nullptr);
if (sresult < 0) {
// try again or die hard
sresult = 0;
switch (errno) {
// a signal was caught
case EINTR: {
// just try again
break;
}
// nfds is negative or the value
// contained within timeout is invalid
case EINVAL: {
if ((maxfd + 1) < 0) {
CPPA_CRITICAL("overflow: maxfd + 1 > 0");
}
break;
}
case ENOMEM: {
// there's not much we can do other than try again
// sleep some time in hope someone releases memory
// while we are sleeping
//this_thread::yield();
break;
}
case EBADF: {
// this really shouldn't happen
// try IO on each single socket and rebuild rd_set
for (auto& ch: m_channels) {
continue_reading(ch);
}
for (auto& peer : m_peers_with_unwritten_data) {
continue_writing(peer);
}
insert_new_handlers();
erase_erroneous_channels();
update_fd_sets();
break;
}
default: {
CPPA_CRITICAL("select() failed for an unknown reason");
}
}
}
}
while (sresult == 0);
//DEBUG("continue reading ...");
{ // iterate over all channels and remove channels as needed
for (auto& ch : m_channels) {
if (FD_ISSET(ch->read_handle(), &rdset)) {
continue_reading(ch);
}
}
}
if (wrset_ptr) { // iterate over peers with unwritten data
DEBUG("continue writing ...");
for (auto& peer : m_peers_with_unwritten_data) {
if (FD_ISSET(peer->write_handle(), &wrset)) {
continue_writing(peer);
}
}
}
insert_new_handlers();
erase_erroneous_channels();
} }
while (m_done == false); while (m_done == false);
DEBUG("middleman done"); DEBUG("middleman done");
......
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
// for thread_specific_ptr // for thread_specific_ptr
// needed unless the new keyword "thread_local" works in GCC // needed unless the new keyword "thread_local" works in GCC
#include <boost/thread/tss.hpp> //#include <boost/thread/tss.hpp>
#include <pthread.h>
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
...@@ -42,7 +44,59 @@ namespace cppa { ...@@ -42,7 +44,59 @@ namespace cppa {
namespace { namespace {
boost::thread_specific_ptr<local_actor> t_this_actor(&self_type::cleanup_fun); pthread_key_t s_key;
pthread_once_t s_key_once = PTHREAD_ONCE_INIT;
local_actor* tss_constructor() {
local_actor* result = new thread_mapped_actor;
result->ref();
get_scheduler()->register_converted_context(result);
return result;
}
void tss_destructor(void* vptr) {
if (vptr) self_type::cleanup_fun(reinterpret_cast<local_actor*>(vptr));
}
void tss_make_key() {
pthread_key_create(&s_key, tss_destructor);
}
local_actor* tss_get() {
pthread_once(&s_key_once, tss_make_key);
return reinterpret_cast<local_actor*>(pthread_getspecific(s_key));
}
local_actor* tss_release() {
pthread_once(&s_key_once, tss_make_key);
auto result = reinterpret_cast<local_actor*>(pthread_getspecific(s_key));
if (result) {
pthread_setspecific(s_key, nullptr);
}
return result;
}
local_actor* tss_get_or_create() {
pthread_once(&s_key_once, tss_make_key);
auto result = reinterpret_cast<local_actor*>(pthread_getspecific(s_key));
if (!result) {
result = tss_constructor();
pthread_setspecific(s_key, reinterpret_cast<void*>(result));
}
return result;
}
void tss_reset(local_actor* ptr, bool inc_ref_count = true) {
pthread_once(&s_key_once, tss_make_key);
auto old_ptr = reinterpret_cast<local_actor*>(pthread_getspecific(s_key));
if (old_ptr) {
tss_destructor(old_ptr);
}
if (ptr != nullptr && inc_ref_count) {
ptr->ref();
}
pthread_setspecific(s_key, reinterpret_cast<void*>(ptr));
}
} // namespace <anonymous> } // namespace <anonymous>
...@@ -58,19 +112,11 @@ void self_type::cleanup_fun(cppa::local_actor* what) { ...@@ -58,19 +112,11 @@ void self_type::cleanup_fun(cppa::local_actor* what) {
} }
void self_type::set_impl(self_type::pointer ptr) { void self_type::set_impl(self_type::pointer ptr) {
if (ptr) ptr->ref(); tss_reset(ptr);
t_this_actor.reset(ptr);
} }
self_type::pointer self_type::get_impl() { self_type::pointer self_type::get_impl() {
auto result = t_this_actor.get(); return tss_get_or_create();
if (result == nullptr) {
result = new thread_mapped_actor;
result->ref();
get_scheduler()->register_converted_context(result);
t_this_actor.reset(result);
}
return result;
} }
actor* self_type::convert_impl() { actor* self_type::convert_impl() {
...@@ -78,15 +124,15 @@ actor* self_type::convert_impl() { ...@@ -78,15 +124,15 @@ actor* self_type::convert_impl() {
} }
self_type::pointer self_type::get_unchecked_impl() { self_type::pointer self_type::get_unchecked_impl() {
return t_this_actor.get(); return tss_get();
} }
void self_type::adopt_impl(self_type::pointer ptr) { void self_type::adopt_impl(self_type::pointer ptr) {
t_this_actor.reset(ptr); tss_reset(ptr, false);
} }
self_type::pointer self_type::release_impl() { self_type::pointer self_type::release_impl() {
return t_this_actor.release(); return tss_release();
} }
} // namespace cppa } // namespace cppa
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
project(cppa_unit_tests CXX) project(cppa_unit_tests CXX)
# set up environment paths to cmake modules and libcppa # set up environment paths to cmake modules and libcppa
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
...@@ -9,16 +10,19 @@ if(NOT cppa_LIBRARY) ...@@ -9,16 +10,19 @@ if(NOT cppa_LIBRARY)
find_package(Libcppa REQUIRED) find_package(Libcppa REQUIRED)
endif (NOT cppa_LIBRARY) endif (NOT cppa_LIBRARY)
find_package(Boost COMPONENTS thread REQUIRED) #find_package(Boost COMPONENTS thread REQUIRED)
find_package(Boost REQUIRED)
find_package(PTHREAD REQUIRED)
link_directories(${Boost_LIBRARY_DIRS}) link_directories(${Boost_LIBRARY_DIRS})
include_directories(. ${cppa_INCLUDE} ${Boost_INCLUDE_DIRS}) include_directories(. ${cppa_INCLUDE} ${Boost_INCLUDE_DIRS} ${PTHREAD_INCLUDE_DIR})
set(EXAMPLE_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${Boost_THREAD_LIBRARY}) set(EXAMPLE_LIBS ${CMAKE_DL_LIBS} ${CPPA_LIBRARY} ${PTHREAD_LIBRARIES})
macro(add_unit_test name) macro(add_unit_test name)
add_executable(test__${name} test__${name}.cpp ${ARGN}) add_executable(test__${name} test__${name}.cpp ${ARGN})
target_link_libraries(test__${name} ${EXAMPLE_LIBS}) target_link_libraries(test__${name} ${EXAMPLE_LIBS} ${CMAKE_THREAD_LIBS_INIT})
add_test(${name} ${EXECUTABLE_OUTPUT_PATH}/test__${name}) add_test(${name} ${EXECUTABLE_OUTPUT_PATH}/test__${name})
endmacro() endmacro()
......
# - Find pthread
# Find the native PTHREAD headers and libraries.
#
# PTHREAD_INCLUDE_DIR - where to find pthread.h, etc.
# PTHREAD_LIBRARIES - List of libraries when using pthread.
# PTHREAD_FOUND - True if pthread found.
GET_FILENAME_COMPONENT(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH )
# Look for the header file.
FIND_PATH(PTHREAD_INCLUDE_DIR NAMES pthread.h
PATHS $ENV{H3D_EXTERNAL_ROOT}/include
$ENV{H3D_EXTERNAL_ROOT}/include/pthread
$ENV{H3D_ROOT}/../External/include
$ENV{H3D_ROOT}/../External/include/pthread
../../External/include
../../External/include/pthread
${module_file_path}/../../../External/include
${module_file_path}/../../../External/include/pthread)
MARK_AS_ADVANCED(PTHREAD_INCLUDE_DIR)
# Look for the library.
IF(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthreadVC2
PATHS $ENV{H3D_EXTERNAL_ROOT}/lib
$ENV{H3D_ROOT}/../External/lib
../../External/lib
${module_file_path}/../../../External/lib)
ELSE(WIN32)
FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread)
ENDIF(WIN32)
MARK_AS_ADVANCED(PTHREAD_LIBRARY)
# Copy the results to the output variables.
IF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 1)
SET(PTHREAD_LIBRARIES ${PTHREAD_LIBRARY})
SET(PTHREAD_INCLUDE_DIR ${PTHREAD_INCLUDE_DIR})
ELSE(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
SET(PTHREAD_FOUND 0)
SET(PTHREAD_LIBRARIES)
SET(PTHREAD_INCLUDE_DIR)
ENDIF(PTHREAD_INCLUDE_DIR AND PTHREAD_LIBRARY)
# Report the results.
IF(NOT PTHREAD_FOUND)
SET(PTHREAD_DIR_MESSAGE
"PTHREAD was not found. Make sure PTHREAD_LIBRARY and PTHREAD_INCLUDE_DIR are set. Pthread is required to compile.")
IF(PTHREAD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "${PTHREAD_DIR_MESSAGE}")
ELSEIF(NOT PTHREAD_FIND_QUIETLY)
MESSAGE(STATUS "${PTHREAD_DIR_MESSAGE}")
ENDIF(PTHREAD_FIND_REQUIRED)
ENDIF(NOT PTHREAD_FOUND)
#include <iostream>
#include <functional> #include <functional>
#include "test.hpp" #include "test.hpp"
...@@ -8,11 +9,9 @@ ...@@ -8,11 +9,9 @@
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/guard_expr.hpp" #include "cppa/guard_expr.hpp"
using namespace std;
using namespace cppa; using namespace cppa;
using std::vector;
using std::string;
bool is_even(int i) { return i % 2 == 0; } bool is_even(int i) { return i % 2 == 0; }
/* /*
...@@ -23,93 +22,16 @@ bool is_even(int i) { return i % 2 == 0; } ...@@ -23,93 +22,16 @@ bool is_even(int i) { return i % 2 == 0; }
* *
*/ */
bool ascending(int a, int b, int c) {
return a < b && b < c;
}
vector<const uniform_type_info*>
to_vec(util::empty_type_list,
vector<const uniform_type_info*> vec=vector<const uniform_type_info*>{}){
return vec;
}
template<typename Head, typename... Tail>
vector<const uniform_type_info*>
to_vec(util::type_list<Head, Tail...>,
vector<const uniform_type_info*> vec=vector<const uniform_type_info*>{}){
vec.push_back(uniform_typeid<Head>());
return to_vec(util::type_list<Tail...>{}, std::move(vec));
}
template<typename Fun>
class __ {
typedef typename util::get_callable_trait<Fun>::type trait;
public:
__(Fun f, string annotation = "") : m_fun(f), m_annotation(annotation) { }
__ operator[](const string& str) const {
return {m_fun, str};
}
template<typename... Args>
void operator()(Args&&... args) const {
m_fun(std::forward<Args>(args)...);
}
void plot_signature() {
auto vec = to_vec(typename trait::arg_types{});
for (auto i : vec) {
cout << i->name() << " ";
}
cout << endl;
}
const string& annotation() const {
return m_annotation;
}
private:
Fun m_fun;
string m_annotation;
};
template<typename Fun>
__<Fun> get__(Fun f) {
return {f};
}
struct fobaz : sb_actor<fobaz> {
behavior init_state;
void vfun() {
cout << "fobaz::mfun" << endl;
}
void ifun(int i) {
cout << "fobaz::ifun(" << i << ")" << endl;
}
fobaz() {
init_state = (
on<int>() >> [=](int i) { ifun(i); },
others() >> std::function<void()>{std::bind(&fobaz::vfun, this)}
);
}
};
int main() { int main() {
CPPA_TEST(test__match); CPPA_TEST(test__match);
using namespace std::placeholders; using namespace std::placeholders;
using namespace cppa::placeholders; using namespace cppa::placeholders;
auto ascending = [](int a, int b, int c) -> bool {
return a < b && b < c;
};
auto expr0_a = gcall(ascending, _x1, _x2, _x3); auto expr0_a = gcall(ascending, _x1, _x2, _x3);
CPPA_CHECK(ge_invoke(expr0_a, 1, 2, 3)); CPPA_CHECK(ge_invoke(expr0_a, 1, 2, 3));
CPPA_CHECK(!ge_invoke(expr0_a, 3, 2, 1)); CPPA_CHECK(!ge_invoke(expr0_a, 3, 2, 1));
...@@ -418,5 +340,52 @@ int main() { ...@@ -418,5 +340,52 @@ int main() {
CPPA_CHECK_EQUAL(3, pmatches); CPPA_CHECK_EQUAL(3, pmatches);
*/ */
// let's get the awesomeness started
istringstream iss("hello world");
match_stream<string>(iss) (
on("hello", "world") >> [] {
cout << "yeeeeeehaaaaaaa!!!!!" << endl;
},
on_arg_match >> [](const string& s1, const string& s2, const std::string& s3) {
cout << "you said: " << s1 << " " << s2 << " " << s3 << endl;
cout << "mind sayin 'hello world'?" << endl;
}
);
auto extract_name = [](const string& kvp) -> option<string> {
auto vec = split(kvp, '=');
if (vec.size() == 2) {
if (vec.front() == "--name") {
return vec.back();
}
}
return {};
};
const char* svec[] = {"-n", "foo", "--name=bar", "-p", "2"};
bool success = match_stream<string>(begin(svec), end(svec)) (
(on("-n", arg_match) || on(extract_name)) >> [](const string& name) {
cout << "your name is " << name << endl;
},
on("-p", arg_match) >> [&](const string& port) -> bool {
auto i = toint(port);
if (i) {
cout << "port = " << *i << endl;
return true;
}
else {
cout << "'" << port << "' is not a valid port" << endl;
return false;
}
},
on_arg_match >> [](const string& arg) {
cout << "dunno whatya wanna say me: " << arg << endl;
}
);
cout << "success: " << success << endl;
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -132,10 +132,7 @@ int main() { ...@@ -132,10 +132,7 @@ int main() {
util::buffer wr_buf; util::buffer wr_buf;
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << ttup; bs << ttup;
std::uint32_t serialized_size; binary_deserializer bd(wr_buf.data(), wr_buf.size());
memcpy(&serialized_size, wr_buf.data(), ui32size);
CPPA_CHECK_EQUAL(serialized_size, wr_buf.size() - ui32size);
binary_deserializer bd(wr_buf.data() + ui32size, wr_buf.size());
any_tuple ttup2; any_tuple ttup2;
uniform_typeid<any_tuple>()->deserialize(&ttup2, &bd); uniform_typeid<any_tuple>()->deserialize(&ttup2, &bd);
CPPA_CHECK(ttup == ttup2); CPPA_CHECK(ttup == ttup2);
...@@ -146,7 +143,7 @@ int main() { ...@@ -146,7 +143,7 @@ int main() {
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << atuple1; bs << atuple1;
// deserialize b2 from buf // deserialize b2 from buf
binary_deserializer bd(wr_buf.data() + ui32size, wr_buf.size()); binary_deserializer bd(wr_buf.data(), wr_buf.size());
any_tuple atuple2; any_tuple atuple2;
uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd); uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd);
try { try {
...@@ -173,7 +170,7 @@ int main() { ...@@ -173,7 +170,7 @@ int main() {
util::buffer wr_buf; util::buffer wr_buf;
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << msg1; bs << msg1;
binary_deserializer bd(wr_buf.data() + ui32size, wr_buf.size()); binary_deserializer bd(wr_buf.data(), wr_buf.size());
object obj1; object obj1;
bd >> obj1; bd >> obj1;
object obj2 = from_string(to_string(msg1)); object obj2 = from_string(to_string(msg1));
...@@ -236,7 +233,7 @@ int main() { ...@@ -236,7 +233,7 @@ int main() {
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << b1; bs << b1;
// deserialize b2 from buf // deserialize b2 from buf
binary_deserializer bd(wr_buf.data() + ui32size, wr_buf.size()); binary_deserializer bd(wr_buf.data(), wr_buf.size());
object res; object res;
bd >> res; bd >> res;
CPPA_CHECK_EQUAL(res.type()->name(), "struct_b"); CPPA_CHECK_EQUAL(res.type()->name(), "struct_b");
...@@ -263,7 +260,7 @@ int main() { ...@@ -263,7 +260,7 @@ int main() {
binary_serializer bs(&wr_buf); binary_serializer bs(&wr_buf);
bs << c1; bs << c1;
// serialize c2 from buf // serialize c2 from buf
binary_deserializer bd(wr_buf.data() + ui32size, wr_buf.size()); binary_deserializer bd(wr_buf.data(), wr_buf.size());
object res; object res;
bd >> res; bd >> res;
CPPA_CHECK_EQUAL(res.type()->name(), "struct_c"); CPPA_CHECK_EQUAL(res.type()->name(), "struct_c");
......
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