Commit a96f232d authored by Dominik Charousset's avatar Dominik Charousset

New terminology, e.g., `any_tuple` => `message`

This patch renames several classes to give programmers without functional
background a better intuition about the purpose of a particular class. For
example, `partial_function` is not a concept familiar to all C++ developers and
has been renamed to `message_handler`. Although the former is a better and more
general name in theory, the latter is a better description for what the class
is actually used for in the library.
parent f83fdfb4
......@@ -119,16 +119,6 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif ("${CMAKE_BUILD_TYPE}" STREQUAL "")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LIBCPPA_PLATFORM_SRC src/middleman_event_handler_epoll.cpp)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBCPPA_PLATFORM_SRC src/middleman_event_handler_poll.cpp)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Window")
set(LIBCPPA_PLATFORM_SRC src/middleman_event_handler_poll.cpp src/execinfo_windows.cpp)
else ()
message(FATAL_ERROR "This platform is not supported by libcppa")
endif()
# get header files; only needed by CMake generators,
# e.g., for creating proper Xcode projects
file(GLOB LIBCPPA_HDRS "cppa/*.hpp"
......@@ -139,13 +129,23 @@ file(GLOB LIBCPPA_HDRS "cppa/*.hpp"
"cppa/qtsupport/*.hpp"
"cppa/util/*.hpp")
# list cpp files including platform-dependent files
set(LIBCPPA_SRC
${LIBCPPA_PLATFORM_SRC}
# platform-dependent files
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(LIBCPPA_PLATFORM_SRCS src/middleman_event_handler_epoll.cpp)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBCPPA_PLATFORM_SRCS src/middleman_event_handler_poll.cpp)
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Window")
set(LIBCPPA_PLATFORM_SRCS src/middleman_event_handler_poll.cpp src/execinfo_windows.cpp)
else ()
message(FATAL_ERROR "This platform is not supported by libcppa")
endif()
# list cpp files excluding platform-dependent files
set (LIBCPPA_SRCS
${LIBCPPA_PLATFORM_SRCS}
src/abstract_actor.cpp
src/abstract_channel.cpp
src/abstract_group.cpp
src/abstract_tuple.cpp
src/acceptor.cpp
src/actor.cpp
src/actor_addr.cpp
......@@ -153,10 +153,8 @@ set(LIBCPPA_SRC
src/actor_namespace.cpp
src/actor_ostream.cpp
src/actor_proxy.cpp
src/actor_proxy.cpp
src/actor_registry.cpp
src/algorithm.cpp
src/any_tuple.cpp
src/atom.cpp
src/attachable.cpp
src/behavior.cpp
......@@ -194,14 +192,18 @@ set(LIBCPPA_SRC
src/match.cpp
src/memory.cpp
src/memory_managed.cpp
src/message.cpp
src/message_builder.cpp
src/message_handler.cpp
src/message_header.cpp
src/middleman.cpp
src/middleman_event_handler.cpp
src/node_id.cpp
src/object_array.cpp
src/opencl/global.cpp
src/opencl/opencl_metainfo.cpp
src/opencl/program.cpp
src/opt.cpp
src/output_stream.cpp
src/partial_function.cpp
src/peer.cpp
src/peer_acceptor.cpp
src/primitive_variant.cpp
......@@ -279,7 +281,7 @@ endif (ENABLE_CONTEXT_SWITCHING)
# build shared library if not compiling static only
if (NOT "${CPPA_BUILD_STATIC_ONLY}" STREQUAL "yes")
add_library(libcppa SHARED ${LIBCPPA_SRC} ${LIBCPPA_HDRS})
add_library(libcppa SHARED ${LIBCPPA_SRCS} ${LIBCPPA_HDRS})
target_link_libraries(libcppa ${LD_FLAGS})
set(LIBRARY_VERSION ${LIBCPPA_VERSION_MAJOR}.${LIBCPPA_VERSION_MINOR}.${LIBCPPA_VERSION_PATCH})
set(LIBRARY_SOVERSION ${LIBCPPA_VERSION_MAJOR})
......@@ -295,7 +297,7 @@ endif ()
# build static library only if --build-static or --build-static-only was set
if ("${CPPA_BUILD_STATIC_ONLY}" STREQUAL "yes" OR "${CPPA_BUILD_STATIC}" STREQUAL "yes")
add_library(libcppaStatic STATIC ${LIBCPPA_HDRS} ${LIBCPPA_SRC})
add_library(libcppaStatic STATIC ${LIBCPPA_HDRS} ${LIBCPPA_SRCS})
set_target_properties(libcppaStatic PROPERTIES OUTPUT_NAME cppa_static)
install(TARGETS libcppaStatic ARCHIVE DESTINATION lib)
endif ()
......
......@@ -46,7 +46,7 @@ class abstract_channel : public ref_counted {
* is not a scheduled actor.
*/
virtual void enqueue(msg_hdr_cref header,
any_tuple content,
message content,
execution_unit* host) = 0;
protected:
......
......@@ -47,7 +47,7 @@ class broker;
} // namespace io
namespace opencl {
template <typename Signature>
template<typename Signature>
class actor_facade;
} // namespace opencl
......
......@@ -65,7 +65,7 @@ class actor_companion : public extend<local_actor, actor_companion>::
*/
void on_enqueue(enqueue_handler handler);
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit* eu) override;
void enqueue(msg_hdr_cref hdr, message msg, execution_unit* eu) override;
private:
......
......@@ -21,7 +21,7 @@
#define CPPA_ACTOR_OSTREAM_HPP
#include "cppa/actor.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/to_string.hpp"
namespace cppa {
......@@ -51,11 +51,11 @@ class actor_ostream {
return write(move(arg));
}
inline actor_ostream& operator<<(const any_tuple& arg) {
inline actor_ostream& operator<<(const message& arg) {
return write(cppa::to_string(arg));
}
// disambiguate between conversion to string and to any_tuple
// disambiguate between conversion to string and to message
inline actor_ostream& operator<<(const char* arg) {
return *this << std::string{arg};
}
......@@ -63,7 +63,7 @@ class actor_ostream {
template<typename T>
inline typename std::enable_if<
!std::is_convertible<T, std::string>::value
&& !std::is_convertible<T, any_tuple>::value,
&& !std::is_convertible<T, message>::value,
actor_ostream&
>::type
operator<<(T&& arg) {
......
......@@ -63,7 +63,7 @@ class actor_proxy : public extend<abstract_actor>::with<enable_weak_ptr> {
* middleman's thread.
* @note This function is guaranteed to be called non-concurrently.
*/
virtual void deliver(msg_hdr_cref hdr, any_tuple msg) = 0;
virtual void deliver(msg_hdr_cref hdr, message msg) = 0;
protected:
......
......@@ -241,8 +241,8 @@ class meta_cow_tuple : public uniform_type_info {
return create_impl<tuple_type>(other);
}
any_tuple as_any_tuple(void* instance) const override {
return (instance) ? any_tuple{*cast(instance)} : any_tuple{};
message as_message(void* instance) const override {
return (instance) ? make_message(*cast(instance)) : message{};
}
bool equal_to(const std::type_info& tinfo) const override {
......
......@@ -32,18 +32,18 @@
namespace cppa {
class partial_function;
class message_handler;
/**
* @brief Describes the behavior of an actor.
*/
class behavior {
friend class partial_function;
friend class message_handler;
public:
typedef std::function<optional<any_tuple> (any_tuple&)> continuation_fun;
typedef std::function<optional<message> (message&)> continuation_fun;
/** @cond PRIVATE */
......@@ -61,7 +61,7 @@ class behavior {
behavior& operator=(behavior&&) = default;
behavior& operator=(const behavior&) = default;
behavior(const partial_function& fun);
behavior(const message_handler& fun);
template<typename F>
behavior(const timeout_definition<F>& arg);
......@@ -91,7 +91,7 @@ class behavior {
* does not evaluate guards.
*/
template<typename T>
inline optional<any_tuple> operator()(T&& arg);
inline optional<message> operator()(T&& arg);
/**
* @brief Adds a continuation to this behavior that is executed
......@@ -151,7 +151,7 @@ inline const util::duration& behavior::timeout() const {
}
template<typename T>
inline optional<any_tuple> behavior::operator()(T&& arg) {
inline optional<message> behavior::operator()(T&& arg) {
return (m_impl) ? m_impl->invoke(std::forward<T>(arg)) : none;
}
......
......@@ -46,11 +46,11 @@ class behavior_stack_based_impl : public single_timeout<Base, Subtype> {
typedef behavior_stack_based_impl combined_type;
typedef response_handle<behavior_stack_based_impl,
any_tuple,
message,
nonblocking_response_handle_tag>
response_handle_type;
template <typename... Ts>
template<typename... Ts>
behavior_stack_based_impl(Ts&&... vs) : super(std::forward<Ts>(vs)...) { }
/**************************************************************************
......
......@@ -124,7 +124,7 @@ class blocking_actor
* @code
* int i = 0;
* receive_for(i, 10) (
* on(atom("get")) >> [&]() -> any_tuple { return {"result", i}; }
* on(atom("get")) >> [&]() -> message { return {"result", i}; }
* );
* @endcode
* @param begin First value in range.
......
......@@ -135,7 +135,7 @@ using ::backtrace_symbols_fd;
} \
abort()
# define CPPA_REQUIRE(stmt) \
if ((stmt) == false) { \
if (static_cast<bool>(stmt) == false) { \
CPPA_REQUIRE__(#stmt, __FILE__, __LINE__); \
}((void) 0)
#else
......
......@@ -25,7 +25,7 @@
#include "cppa/on.hpp"
#include "cppa/behavior.hpp"
#include "cppa/message_id.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
namespace cppa {
......@@ -50,7 +50,7 @@ class continue_helper {
*/
template<typename F>
continue_helper& continue_with(F fun) {
return continue_with(behavior::continuation_fun{partial_function{
return continue_with(behavior::continuation_fun{message_handler{
on(any_vals, arg_match) >> fun
}});
}
......
......@@ -26,7 +26,7 @@
#include <type_traits>
#include "cppa/get.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/message.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/util/type_traits.hpp"
......@@ -39,13 +39,6 @@
namespace cppa {
// forward declaration
class any_tuple;
class local_actor;
template<typename... ElementTypes>
class cow_tuple;
/**
* @ingroup CopyOnWrite
* @brief A fixed-length copy-on-write cow_tuple.
......@@ -58,22 +51,16 @@ class cow_tuple<Head, Tail...> {
"illegal types in cow_tuple definition: "
"pointers and references are prohibited");
friend class any_tuple;
typedef detail::tuple_vals<Head, Tail...> data_type;
cow_ptr<detail::abstract_tuple> m_vals;
struct priv_ctor { };
using data_type = detail::tuple_vals<
typename detail::strip_and_convert<Head>::type,
typename detail::strip_and_convert<Tail>::type...>;
cow_tuple(priv_ctor, cow_ptr<detail::abstract_tuple>&& ptr) : m_vals(std::move(ptr)) { }
using data_ptr = detail::message_data::ptr;
public:
typedef util::type_list<Head, Tail...> types;
typedef cow_ptr<detail::abstract_tuple> cow_ptr_type;
static constexpr size_t num_elements = sizeof...(Tail) + 1;
cow_tuple() : m_vals(new data_type) { }
......@@ -99,12 +86,6 @@ class cow_tuple<Head, Tail...> {
cow_tuple& operator=(cow_tuple&&) = default;
cow_tuple& operator=(const cow_tuple&) = default;
static cow_tuple offset_subtuple(cow_ptr_type ptr, size_t offset) {
CPPA_REQUIRE(offset > 0);
auto ti = detail::static_type_list<Head, Tail...>::by_offset(offset);
return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, offset)};
}
/**
* @brief Gets the size of this cow_tuple.
*/
......@@ -138,28 +119,21 @@ class cow_tuple<Head, Tail...> {
return cow_tuple<Tail...>::offset_subtuple(m_vals, 1);
}
/** @cond PRIVATE */
static cow_tuple from(cow_ptr_type ptr) {
return {priv_ctor{}, std::move(ptr)};
inline operator message() {
return message{m_vals};
}
static cow_tuple from(cow_ptr_type ptr, std::vector<size_t> mv) {
auto ti = detail::static_type_list<Head, Tail...>::list;
return {priv_ctor{}, detail::decorated_tuple::create(std::move(ptr), ti, std::move(mv))};
}
private:
static cow_tuple from(cow_ptr_type ptr, const util::limited_vector<size_t, num_elements>& mv) {
std::vector<size_t> v(mv.size());
std::copy(mv.begin(), mv.end(), v.begin());
return from(ptr, std::move(v));
data_type* ptr() {
return static_cast<data_type*>(m_vals.get());
}
inline const cow_ptr<detail::abstract_tuple>& vals() const {
return m_vals;
const data_type* ptr() const {
return static_cast<data_type*>(m_vals.get());
}
/** @endcond */
data_ptr m_vals;
};
......
......@@ -37,7 +37,7 @@
#include "cppa/sb_actor.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/singletons.hpp"
#include "cppa/typed_actor.hpp"
......@@ -322,7 +322,7 @@
* std::vector<int> vec {1, 2, 3, 4};
* auto i = vec.begin();
* receive_for(i, vec.end()) (
* on(atom("get")) >> [&]() -> any_tuple { return {atom("result"), *i}; }
* on(atom("get")) >> [&]() -> message { return {atom("result"), *i}; }
* );
* @endcode
*
......@@ -425,7 +425,7 @@ namespace cppa {
/**
* @brief Sends @p to a message under the identity of @p from.
*/
inline void send_tuple_as(const actor& from, const channel& to, any_tuple msg) {
inline void send_tuple_as(const actor& from, const channel& to, message msg) {
if (to) to->enqueue({from.address(), to}, std::move(msg), nullptr);
}
......@@ -434,13 +434,13 @@ inline void send_tuple_as(const actor& from, const channel& to, any_tuple msg) {
*/
template<typename... Ts>
void send_as(const actor& from, const channel& to, Ts&&... args) {
send_tuple_as(from, to, make_any_tuple(std::forward<Ts>(args)...));
send_tuple_as(from, to, make_message(std::forward<Ts>(args)...));
}
/**
* @brief Anonymously sends @p to a message.
*/
inline void anon_send_tuple(const channel& to, any_tuple msg) {
inline void anon_send_tuple(const channel& to, message msg) {
send_tuple_as(invalid_actor, to, std::move(msg));
}
......
......@@ -31,7 +31,7 @@ class channel;
class node_id;
class behavior;
class resumable;
class any_tuple;
class message;
class actor_addr;
class actor_proxy;
class scoped_actor;
......@@ -40,7 +40,7 @@ class abstract_actor;
class abstract_group;
class blocking_actor;
class message_header;
class partial_function;
class message_handler;
class uniform_type_info;
class event_based_actor;
class primitive_variant;
......
......@@ -16,45 +16,41 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CALL_HPP
#define CALL_HPP
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/util/int_list.hpp"
namespace cppa {
namespace detail {
abstract_tuple::abstract_tuple(bool is_dynamic) : m_is_dynamic(is_dynamic) { }
bool abstract_tuple::equals(const abstract_tuple &other) const {
return this == &other
|| ( size() == other.size()
&& std::equal(begin(), end(), other.begin(), detail::full_eq));
}
abstract_tuple::abstract_tuple(const abstract_tuple& other)
: m_is_dynamic(other.m_is_dynamic) { }
const std::type_info* abstract_tuple::type_token() const {
return &typeid(void);
template <typename F, long... Is, class Tuple>
inline auto apply_args(F& f, util::int_list<Is...>, Tuple&& tup)
-> decltype(f(get<Is>(tup)...)) {
return f(get<Is>(tup)...);
}
const void* abstract_tuple::native_data() const {
return nullptr;
template <typename F, class Tuple, typename... Ts>
inline auto apply_args_prefixed(F& f, util::int_list<>, Tuple&, Ts&&... args)
-> decltype(f(std::forward<Ts>(args)...)) {
return f(std::forward<Ts>(args)...);
}
void* abstract_tuple::mutable_native_data() {
return nullptr;
template <typename F, long... Is, class Tuple, typename... Ts>
inline auto apply_args_prefixed(F& f, util::int_list<Is...>, Tuple& tup,
Ts&&... args)
-> decltype(f(std::forward<Ts>(args)..., get<Is>(tup)...)) {
return f(std::forward<Ts>(args)..., get<Is>(tup)...);
}
std::string get_tuple_type_names(const detail::abstract_tuple& tup) {
std::string result = "@<>";
for (size_t i = 0; i < tup.size(); ++i) {
auto uti = tup.type_at(i);
result += "+";
result += uti->name();
}
return result;
template <typename F, long... Is, class Tuple, typename... Ts>
inline auto apply_args_suffxied(F& f, util::int_list<Is...>, Tuple& tup,
Ts&&... args)
-> decltype(f(get<Is>(tup)..., std::forward<Ts>(args)...)) {
return f(get<Is>(tup)..., std::forward<Ts>(args)...);
}
} // namespace detail
} // namespace cppa
#endif // CALL_HPP
......@@ -16,18 +16,15 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#include "cppa/logging.hpp"
#include "cppa/io/protocol.hpp"
#include "cppa/io/middleman.hpp"
#ifndef CPPA_ARG_MATCH_T_HPP
#define CPPA_ARG_MATCH_T_HPP
namespace cppa {
namespace io {
namespace detail {
protocol::protocol(middleman* parent) : m_parent(parent) {
CPPA_REQUIRE(parent != nullptr);
}
struct arg_match_t {};
} // namespace io
} // namespace detail
} // namespace cppa
#endif // CPPA_ARG_MATCH_T_HPP
......@@ -16,89 +16,115 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef BEHAVIOR_IMPL_HPP
#define BEHAVIOR_IMPL_HPP
#ifndef CPPA_DETAIL_BEHAVIOR_IMPL_HPP
#define CPPA_DETAIL_BEHAVIOR_IMPL_HPP
#include <tuple>
#include <type_traits>
#include "cppa/atom.hpp"
#include "cppa/none.hpp"
#include "cppa/variant.hpp"
#include "cppa/optional.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/atom.hpp"
#include "cppa/message.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/apply_args.hpp"
namespace cppa {
class partial_function;
typedef optional<any_tuple> bhvr_invoke_result;
class message_handler;
typedef optional<message> bhvr_invoke_result;
} // namespace cppa
namespace cppa {
namespace detail {
template<class T> struct is_message_id_wrapper {
template<class U> static char (&test(typename U::message_id_wrapper_tag))[1];
template<class U> static char (&test(...))[2];
template<class T>
struct is_message_id_wrapper {
template<class U>
static char (&test(typename U::message_id_wrapper_tag))[1];
template<class U>
static char (&test(...))[2];
static constexpr bool value = sizeof(test<T>(0)) == 1;
};
struct optional_any_tuple_visitor : static_visitor<bhvr_invoke_result> {
//inline bhvr_invoke_result operator()() const { return any_tuple{}; }
struct optional_message_visitor : static_visitor<bhvr_invoke_result> {
// inline bhvr_invoke_result operator()() const { return message{}; }
inline bhvr_invoke_result operator()(none_t&) const { return none; }
inline bhvr_invoke_result operator()(const none_t&) const { return none; }
inline bhvr_invoke_result operator()(skip_message_t&) const { return none; }
inline bhvr_invoke_result operator()(const skip_message_t&) const { return none; }
inline bhvr_invoke_result operator()(unit_t&) const { return any_tuple{}; }
inline bhvr_invoke_result operator()(const unit_t&) const { return any_tuple{}; }
template<typename T>
inline bhvr_invoke_result operator()(T& value, typename std::enable_if<not is_message_id_wrapper<T>::value>::type* = 0) const {
return make_any_tuple(std::move(value));
inline bhvr_invoke_result operator()(const skip_message_t&) const {
return none;
}
template<typename T>
inline bhvr_invoke_result operator()(T& value, typename std::enable_if<is_message_id_wrapper<T>::value>::type* = 0) const {
return make_any_tuple(atom("MESSAGE_ID"), value.get_message_id().integer_value());
inline bhvr_invoke_result operator()(unit_t&) const {
return message{};
}
template<typename... Ts>
inline bhvr_invoke_result operator()(cow_tuple<Ts...>& value) const {
return any_tuple{std::move(value)};
inline bhvr_invoke_result operator()(const unit_t&) const {
return message{};
}
inline bhvr_invoke_result operator()(optional<skip_message_t>& val) const {
if (val) return none;
return message{};
}
inline bhvr_invoke_result
operator()(const optional<skip_message_t>& val) const {
if (val) return none;
return message{};
}
template<typename T, typename... Ts>
inline typename std::enable_if<not is_message_id_wrapper<T>::value,
bhvr_invoke_result>::type
operator()(T& v, Ts&... vs) const {
return make_message(std::move(v), std::move(vs)...);
}
inline bhvr_invoke_result operator()(any_tuple& value) const {
template<typename T>
inline bhvr_invoke_result
operator()(T& value,
typename std::enable_if<is_message_id_wrapper<T>::value>::type* =
0) const {
return make_message(atom("MESSAGE_ID"),
value.get_message_id().integer_value());
}
inline bhvr_invoke_result operator()(message& value) const {
return std::move(value);
}
template<typename... Ts>
inline bhvr_invoke_result operator()(std::tuple<Ts...>& value) const {
return detail::apply_args(*this, util::get_indices(value), value);
}
};
template<typename... Ts>
struct has_skip_message {
static constexpr bool value = util::disjunction<
std::is_same<Ts, skip_message_t>::value...
>::value;
static constexpr bool value =
util::disjunction<std::is_same<Ts, skip_message_t>::value...>::value;
};
class behavior_impl : public ref_counted {
public:
behavior_impl() = default;
inline behavior_impl(util::duration tout) : m_timeout(tout) { }
inline behavior_impl(util::duration tout) : m_timeout(tout) {}
virtual bhvr_invoke_result invoke(any_tuple&) = 0;
virtual bhvr_invoke_result invoke(const any_tuple&) = 0;
inline bhvr_invoke_result invoke(any_tuple&& arg) {
any_tuple tmp(std::move(arg));
virtual bhvr_invoke_result invoke(message&) = 0;
virtual bhvr_invoke_result invoke(const message&) = 0;
inline bhvr_invoke_result invoke(message&& arg) {
message tmp(std::move(arg));
return invoke(tmp);
}
virtual bool defined_at(const any_tuple&) = 0;
virtual void handle_timeout();
inline const util::duration& timeout() const {
return m_timeout;
}
inline const util::duration& timeout() const { return m_timeout; }
typedef intrusive_ptr<behavior_impl> pointer;
......@@ -109,19 +135,16 @@ class behavior_impl : public ref_counted {
struct combinator : behavior_impl {
pointer first;
pointer second;
bhvr_invoke_result invoke(any_tuple& arg) {
bhvr_invoke_result invoke(message& arg) {
auto res = first->invoke(arg);
if (!res) return second->invoke(arg);
return res;
}
bhvr_invoke_result invoke(const any_tuple& arg) {
bhvr_invoke_result invoke(const message& arg) {
auto res = first->invoke(arg);
if (!res) return second->invoke(arg);
return res;
}
bool defined_at(const any_tuple& arg) {
return first->defined_at(arg) || second->defined_at(arg);
}
void handle_timeout() {
// the second behavior overrides the timeout handling of
// first behavior
......@@ -131,7 +154,7 @@ class behavior_impl : public ref_counted {
return new combinator(first, second->copy(tdef));
}
combinator(const pointer& p0, const pointer& p1)
: behavior_impl(p1->timeout()), first(p0), second(p1) { }
: behavior_impl(p1->timeout()), first(p0), second(p1) {}
};
return new combinator(this, other);
}
......@@ -143,9 +166,9 @@ class behavior_impl : public ref_counted {
};
struct dummy_match_expr {
inline variant<none_t> invoke(const any_tuple&) const { return none; }
inline bool can_invoke(const any_tuple&) const { return false; }
inline variant<none_t> operator()(const any_tuple&) const { return none; }
inline variant<none_t> invoke(const message&) const { return none; }
inline bool can_invoke(const message&) const { return false; }
inline variant<none_t> operator()(const message&) const { return none; }
};
template<class MatchExpr, typename F>
......@@ -154,60 +177,59 @@ class default_behavior_impl : public behavior_impl {
typedef behavior_impl super;
public:
template<typename Expr>
default_behavior_impl(Expr&& expr, const timeout_definition<F>& d)
: super(d.timeout), m_expr(std::forward<Expr>(expr)), m_fun(d.handler) { }
: super(d.timeout)
, m_expr(std::forward<Expr>(expr))
, m_fun(d.handler) {}
template<typename Expr>
default_behavior_impl(Expr&& expr, util::duration tout, F f)
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { }
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) {}
bhvr_invoke_result invoke(any_tuple& tup) {
bhvr_invoke_result invoke(message& tup) {
auto res = m_expr(tup);
return apply_visitor(optional_any_tuple_visitor{}, res);
return apply_visitor(optional_message_visitor{}, res);
}
bhvr_invoke_result invoke(const any_tuple& tup) {
bhvr_invoke_result invoke(const message& tup) {
auto res = m_expr(tup);
return apply_visitor(optional_any_tuple_visitor{}, res);
}
bool defined_at(const any_tuple& tup) {
return m_expr.can_invoke(tup);
return apply_visitor(optional_message_visitor{}, res);
}
typename behavior_impl::pointer copy(const generic_timeout_definition& tdef) const {
return new default_behavior_impl<MatchExpr, std::function<void()>>(m_expr, tdef);
typename behavior_impl::pointer
copy(const generic_timeout_definition& tdef) const {
return new default_behavior_impl<MatchExpr, std::function<void()>>(
m_expr, tdef);
}
void handle_timeout() { m_fun(); }
private:
MatchExpr m_expr;
F m_fun;
};
template<class MatchExpr, typename F>
default_behavior_impl<MatchExpr, F>* new_default_behavior(const MatchExpr& mexpr, util::duration d, F f) {
default_behavior_impl<MatchExpr, F>*
new_default_behavior(const MatchExpr& mexpr, util::duration d, F f) {
return new default_behavior_impl<MatchExpr, F>(mexpr, d, f);
}
template<typename F>
default_behavior_impl<dummy_match_expr, F>* new_default_behavior(util::duration d, F f) {
return new default_behavior_impl<dummy_match_expr, F>(dummy_match_expr{}, d, f);
default_behavior_impl<dummy_match_expr, F>* new_default_behavior(util::duration d,
F f) {
return new default_behavior_impl<dummy_match_expr, F>(dummy_match_expr{}, d,
f);
}
typedef intrusive_ptr<behavior_impl> behavior_impl_ptr;
// implemented in partial_function.cpp
behavior_impl_ptr combine(behavior_impl_ptr, const partial_function&);
behavior_impl_ptr combine(const partial_function&, behavior_impl_ptr);
behavior_impl_ptr extract(const partial_function&);
// implemented in message_handler.cpp
// message_handler combine(behavior_impl_ptr, behavior_impl_ptr);
// behavior_impl_ptr extract(const message_handler&);
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_BEHAVIOR_IMPL_HPP
#endif // BEHAVIOR_IMPL_HPP
......@@ -16,30 +16,28 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_DECORATED_TUPLE_HPP
#define CPPA_DETAIL_DECORATED_TUPLE_HPP
#ifndef CPPA_DECORATED_TUPLE_HPP
#define CPPA_DECORATED_TUPLE_HPP
#include <vector>
#include <algorithm>
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/message_data.hpp"
#include "cppa/detail/serialize_tuple.hpp"
namespace cppa {
namespace detail {
class decorated_tuple : public abstract_tuple {
class decorated_tuple : public message_data {
typedef abstract_tuple super;
typedef message_data super;
decorated_tuple& operator=(const decorated_tuple&) = delete;
......@@ -47,7 +45,7 @@ class decorated_tuple : public abstract_tuple {
typedef std::vector<size_t> vector_type;
typedef cow_ptr<abstract_tuple> pointer;
typedef message_data::ptr pointer;
typedef const std::type_info* rtti;
......@@ -110,4 +108,4 @@ class decorated_tuple : public abstract_tuple {
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_DECORATED_TUPLE_HPP
#endif // CPPA_DECORATED_TUPLE_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_LIFTED_FUN_HPP
#define CPPA_DETAIL_LIFTED_FUN_HPP
#include "cppa/none.hpp"
#include "cppa/optional.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/detail/tuple_zip.hpp"
#include "cppa/detail/apply_args.hpp"
namespace cppa {
namespace detail {
class lifted_fun_zipper {
public:
template <typename F, typename T>
auto operator()(const F& fun, T& arg) -> decltype(fun(arg)) const {
return fun(arg);
}
// forward everything as reference if no guard/transformation is set
template <typename T>
auto operator()(const unit_t&, T& arg) const -> decltype(std::ref(arg)) {
return std::ref(arg);
}
};
template <typename T>
T& unopt(T& v) {
return v;
}
template <typename T>
T& unopt(optional<T>& v) {
return *v;
}
inline bool has_none() { return false; }
template <typename T, typename... Ts>
inline bool has_none(const T&, const Ts&... vs) {
return has_none(vs...);
}
template <typename T, typename... Ts>
inline bool has_none(const optional<T>& v, const Ts&... vs) {
return !v || has_none(vs...);
}
// allows F to have fewer arguments than the lifted_fun calling it
template <typename R, typename F>
class lifted_fun_invoker {
typedef typename util::get_callable_trait<F>::arg_types arg_types;
static constexpr size_t args = util::tl_size<arg_types>::value;
public:
lifted_fun_invoker(F& fun) : f(fun) {}
template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == args, R>::type
operator()(Ts&... args) const {
if (has_none(args...)) return none;
return f(unopt(args)...);
}
template <typename T, typename... Ts>
typename std::enable_if<(sizeof...(Ts) + 1 > args), R>::type
operator()(T& arg, Ts&... args) const {
if (has_none(arg)) return none;
return (*this)(args...);
}
private:
F& f;
};
template <typename F>
class lifted_fun_invoker<bool, F> {
typedef typename util::get_callable_trait<F>::arg_types arg_types;
static constexpr size_t args = util::tl_size<arg_types>::value;
public:
lifted_fun_invoker(F& fun) : f(fun) {}
template <typename... Ts>
typename std::enable_if<sizeof...(Ts) == args, bool>::type
operator()(Ts&&... args) const {
if (has_none(args...)) return false;
f(unopt(args)...);
return true;
}
template <typename T, typename... Ts>
typename std::enable_if<(sizeof...(Ts) + 1 > args), bool>::type
operator()(T&& arg, Ts&&... args) const {
if (has_none(arg)) return false;
return (*this)(args...);
}
private:
F& f;
};
/**
* @brief A lifted functor consists of a set of projections, a plain-old
* functor and its signature. Note that the signature of the lifted
* functor might differ from the underlying functor, because
* of the projections.
*/
template <typename F, class ListOfProjections, typename... Args>
class lifted_fun {
public:
typedef typename util::get_callable_trait<F>::result_type result_type;
// Let F be "R (Ts...)" then lifted_fun<F...> returns optional<R>
// unless R is void in which case bool is returned
typedef typename std::conditional<std::is_same<result_type, void>::value,
bool, optional<result_type>>::type
optional_result_type;
typedef ListOfProjections projections_list;
typedef typename util::tl_apply<projections_list, std::tuple>::type projections;
typedef util::type_list<Args...> arg_types;
lifted_fun() = default;
lifted_fun(lifted_fun&&) = default;
lifted_fun(const lifted_fun&) = default;
lifted_fun& operator=(lifted_fun&&) = default;
lifted_fun& operator=(const lifted_fun&) = default;
lifted_fun(F f) : m_fun(std::move(f)) {}
lifted_fun(F f, projections ps)
: m_fun(std::move(f)), m_ps(std::move(ps)) {}
/**
* @brief Invokes @p fun with a lifted_fun of <tt>args...</tt>.
*/
optional_result_type operator()(Args... args) {
auto indices = util::get_indices(m_ps);
lifted_fun_zipper zip;
lifted_fun_invoker<optional_result_type, F> invoke{m_fun};
return apply_args(
invoke, indices,
tuple_zip(zip, indices, m_ps, std::forward_as_tuple(args...)));
}
private:
F m_fun;
projections m_ps;
};
template <typename F, class ListOfProjections, class List>
struct get_lifted_fun;
template <typename F, class ListOfProjections, typename... Ts>
struct get_lifted_fun<F, ListOfProjections, util::type_list<Ts...>> {
typedef lifted_fun<F, ListOfProjections, Ts...> type;
};
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_LIFTED_FUN_HPP
......@@ -22,10 +22,11 @@
#include <numeric>
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/wildcard_position.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/limited_vector.hpp"
namespace cppa {
namespace detail {
......@@ -294,9 +295,9 @@ struct match_impl_from_type_list<Tuple, util::type_list<Ts...> > {
* @brief Returns true if this tuple matches the pattern <tt>{Ts...}</tt>.
*/
template<typename... Ts>
bool matches(const any_tuple& tup) {
bool matches(const message& tup) {
typedef util::type_list<Ts...> tl;
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
return match_impl<get_wildcard_position<tl>(), message, Ts...>
::_(tup);
}
......@@ -304,25 +305,25 @@ bool matches(const any_tuple& tup) {
* @brief Returns true if this tuple matches the pattern <tt>{Ts...}</tt>.
*/
template<typename... Ts>
bool matches(const any_tuple& tup,
bool matches(const message& tup,
util::limited_vector<
size_t,
util::tl_count_not<
util::type_list<Ts...>,
is_anything>::value>& mv) {
typedef util::type_list<Ts...> tl;
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
return match_impl<get_wildcard_position<tl>(), message, Ts...>
::_(tup, mv);
}
// support for type_list based matching
template<typename... Ts>
inline bool matches(const any_tuple& tup, const util::type_list<Ts...>&) {
inline bool matches(const message& tup, const util::type_list<Ts...>&) {
return matches<Ts...>(tup);
}
template<typename... Ts>
inline bool matches(const any_tuple& tup, const util::type_list<Ts...>&,
inline bool matches(const message& tup, const util::type_list<Ts...>&,
util::limited_vector<
size_t,
util::tl_count_not<
......@@ -332,10 +333,21 @@ inline bool matches(const any_tuple& tup, const util::type_list<Ts...>&,
}
template<typename... Ts>
inline bool matches_types(const any_tuple& tup, const util::type_list<Ts...>&) {
inline bool matches_types(const message& tup, const util::type_list<Ts...>&) {
return matches<Ts...>(tup);
}
template<class Tuple, class List>
struct select_matcher;
template<class Tuple, typename... Ts>
struct select_matcher<Tuple, util::type_list<Ts...> > {
typedef matcher<get_wildcard_position<util::type_list<Ts...>>(),
Tuple,
Ts...>
type;
};
} // namespace detail
} // namespace cppa
......
......@@ -16,31 +16,32 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_ABSTRACT_TUPLE_HPP
#define CPPA_DETAIL_ABSTRACT_TUPLE_HPP
#ifndef CPPA_ABSTRACT_TUPLE_HPP
#define CPPA_ABSTRACT_TUPLE_HPP
#include <string>
#include <iterator>
#include <typeinfo>
#include "cppa/intrusive_ptr.hpp"
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tuple_iterator.hpp"
#include "cppa/detail/message_iterator.hpp"
namespace cppa {
namespace detail {
class abstract_tuple : public ref_counted {
class message_data : public ref_counted {
public:
abstract_tuple(bool dynamically_typed);
abstract_tuple(const abstract_tuple& other);
message_data(bool dynamically_typed);
message_data(const message_data& other);
// mutators
virtual void* mutable_at(size_t pos) = 0;
......@@ -48,7 +49,7 @@ class abstract_tuple : public ref_counted {
// accessors
virtual size_t size() const = 0;
virtual abstract_tuple* copy() const = 0;
virtual message_data* copy() const = 0;
virtual const void* at(size_t pos) const = 0;
virtual const uniform_type_info* type_at(size_t pos) const = 0;
virtual const std::string* tuple_type_names() const = 0;
......@@ -68,42 +69,84 @@ class abstract_tuple : public ref_counted {
// (default returns &typeid(void))
virtual const std::type_info* type_token() const;
bool equals(const abstract_tuple& other) const;
bool equals(const message_data& other) const;
typedef message_iterator<message_data> const_iterator;
inline const_iterator begin() const {
return {this};
}
inline const_iterator cbegin() const {
return {this};
}
typedef tuple_iterator<abstract_tuple> const_iterator;
inline const_iterator end() const {
return {this, size()};
}
inline const_iterator cend() const {
return {this, size()};
}
class ptr {
public:
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
ptr() = default;
ptr(ptr&&) = default;
ptr(const ptr&) = default;
ptr& operator=(ptr&&) = default;
ptr& operator=(const ptr&) = default;
inline const_iterator end() const { return {this, size()}; }
inline const_iterator cend() const { return {this, size()}; }
inline explicit ptr(message_data* p) : m_ptr(p) {}
inline void detach() { static_cast<void>(get_detached()); }
inline message_data* operator->() { return get_detached(); }
inline message_data& operator*() { return *get_detached(); }
inline const message_data* operator->() const { return m_ptr.get(); }
inline const message_data& operator*() const { return *m_ptr.get(); }
inline void swap(ptr& other) { m_ptr.swap(other.m_ptr); }
inline void reset(message_data* p = nullptr) { m_ptr.reset(p); }
inline const message_data* get() const { return m_ptr.get(); }
inline message_data* get() { return m_ptr.get(); }
inline explicit operator bool() const {
return static_cast<bool>(m_ptr);
}
private:
bool m_is_dynamic;
message_data* get_detached();
intrusive_ptr<message_data> m_ptr;
};
private:
bool m_is_dynamic;
};
struct full_eq_type {
constexpr full_eq_type() { }
constexpr full_eq_type() {}
template<class Tuple>
inline bool operator()(const tuple_iterator<Tuple>& lhs,
const tuple_iterator<Tuple>& rhs) const {
return lhs.type() == rhs.type()
&& lhs.type()->equals(lhs.value(), rhs.value());
inline bool operator()(const message_iterator<Tuple>& lhs,
const message_iterator<Tuple>& rhs) const {
return lhs.type() == rhs.type() &&
lhs.type()->equals(lhs.value(), rhs.value());
}
};
struct types_only_eq_type {
constexpr types_only_eq_type() { }
constexpr types_only_eq_type() {}
template<class Tuple>
inline bool operator()(const tuple_iterator<Tuple>& lhs,
const uniform_type_info* rhs ) const {
inline bool operator()(const message_iterator<Tuple>& lhs,
const uniform_type_info* rhs) const {
return lhs.type() == rhs;
}
template<class Tuple>
inline bool operator()(const uniform_type_info* lhs,
const tuple_iterator<Tuple>& rhs) const {
const message_iterator<Tuple>& rhs) const {
return lhs == rhs.type();
}
};
......@@ -113,9 +156,9 @@ constexpr full_eq_type full_eq;
constexpr types_only_eq_type types_only_eq;
} // namespace <anonymous>
std::string get_tuple_type_names(const detail::abstract_tuple&);
std::string get_tuple_type_names(const detail::message_data&);
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_ABSTRACT_TUPLE_HPP
#endif // CPPA_ABSTRACT_TUPLE_HPP
......@@ -16,9 +16,8 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_TUPLE_ITERATOR_HPP
#define CPPA_DETAIL_TUPLE_ITERATOR_HPP
#ifndef CPPA_TUPLE_ITERATOR_HPP
#define CPPA_TUPLE_ITERATOR_HPP
#include <cstddef>
......@@ -28,56 +27,55 @@ namespace cppa {
namespace detail {
template<class Tuple>
class tuple_iterator {
class message_iterator {
size_t m_pos;
const Tuple* m_tuple;
public:
inline tuple_iterator(const Tuple* tup, size_t pos = 0)
: m_pos(pos), m_tuple(tup) {
}
inline message_iterator(const Tuple* tup, size_t pos = 0)
: m_pos(pos), m_tuple(tup) {}
tuple_iterator(const tuple_iterator&) = default;
message_iterator(const message_iterator&) = default;
tuple_iterator& operator=(const tuple_iterator&) = default;
message_iterator& operator=(const message_iterator&) = default;
inline bool operator==(const tuple_iterator& other) const {
inline bool operator==(const message_iterator& other) const {
CPPA_REQUIRE(other.m_tuple == other.m_tuple);
return other.m_pos == m_pos;
}
inline bool operator!=(const tuple_iterator& other) const {
inline bool operator!=(const message_iterator& other) const {
return !(*this == other);
}
inline tuple_iterator& operator++() {
inline message_iterator& operator++() {
++m_pos;
return *this;
}
inline tuple_iterator& operator--() {
inline message_iterator& operator--() {
CPPA_REQUIRE(m_pos > 0);
--m_pos;
return *this;
}
inline tuple_iterator operator+(size_t offset) {
inline message_iterator operator+(size_t offset) {
return {m_tuple, m_pos + offset};
}
inline tuple_iterator& operator+=(size_t offset) {
inline message_iterator& operator+=(size_t offset) {
m_pos += offset;
return *this;
}
inline tuple_iterator operator-(size_t offset) {
inline message_iterator operator-(size_t offset) {
CPPA_REQUIRE(m_pos >= offset);
return {m_tuple, m_pos - offset};
}
inline tuple_iterator& operator-=(size_t offset) {
inline message_iterator& operator-=(size_t offset) {
CPPA_REQUIRE(m_pos >= offset);
m_pos -= offset;
return *this;
......@@ -85,19 +83,17 @@ class tuple_iterator {
inline size_t position() const { return m_pos; }
inline const void* value() const {
return m_tuple->at(m_pos);
}
inline const void* value() const { return m_tuple->at(m_pos); }
inline const uniform_type_info* type() const {
return m_tuple->type_at(m_pos);
}
inline tuple_iterator& operator*() { return *this; }
inline message_iterator& operator*() { return *this; }
};
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_TUPLE_ITERATOR_HPP
#endif // CPPA_TUPLE_ITERATOR_HPP
......@@ -143,17 +143,14 @@ struct is_rd_arg<rd_arg_functor<T> > : std::true_type { };
template<typename T>
struct is_rd_arg<add_arg_functor<T> > : std::true_type { };
typedef decltype(on<std::string>().when(cppa::placeholders::_x1.in(std::vector<std::string>())))
opt0_rvalue_builder;
typedef decltype(on<std::string>()) opt0_rvalue_builder;
template<bool HasShortOpt = true>
class opt1_rvalue_builder {
public:
typedef decltype(on<std::string, std::string>()
.when(cppa::placeholders::_x1.in(std::vector<std::string>())))
left_type;
typedef decltype(on<std::string, std::string>()) left_type;
typedef decltype(on(std::function<optional<std::string>(const std::string&)>()))
right_type;
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_PROJECTION_HPP
#define CPPA_DETAIL_PROJECTION_HPP
#include "cppa/optional.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/util/call.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa {
namespace detail {
template<typename Fun, typename Tuple, long... Is>
inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) {
return f.defined_at(get_cv_aware<Is>(tup)...);
}
template<typename ProjectionFuns, typename... Ts>
struct collected_args_tuple {
typedef typename tdata_from_type_list<
typename util::tl_zip<
typename util::tl_map<
ProjectionFuns,
util::map_to_result_type,
util::rm_optional
>::type,
typename util::tl_map<
util::type_list<Ts...>,
mutable_gref_wrapped
>::type,
util::left_or_right
>::type
>::type
type;
};
template<typename Fun>
struct is_void_fun {
static constexpr bool value = std::is_same<typename Fun::result_type, void>::value;
};
/**
* @brief Projection implemented by a set of functors.
*/
template<class ProjectionFuns, typename... Ts>
class projection {
public:
typedef typename tdata_from_type_list<ProjectionFuns>::type fun_container;
typedef util::type_list<typename util::rm_const_and_ref<Ts>::type...> arg_types;
projection() = default;
projection(fun_container&& args) : m_funs(std::move(args)) { }
projection(const fun_container& args) : m_funs(args) { }
projection(const projection&) = default;
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
template<class PartFun>
optional<typename PartFun::result_type> operator()(PartFun& fun, Ts... args) const {
typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
auto indices = util::get_indices(pargs);
if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
if (is_defined_at(fun, pargs, indices)) {
return util::apply_args(fun, pargs, indices);
}
}
return none;
}
private:
template<typename Storage, typename T>
static inline bool store(Storage& storage, T&& value) {
storage = std::forward<T>(value);
return true;
}
template<class Storage>
static inline bool store(Storage& storage, optional<Storage>&& value) {
if (value) {
storage = std::move(*value);
return true;
}
return false;
}
template<typename T>
static inline auto fetch(const unit_t&, T&& arg)
-> decltype(std::forward<T>(arg)) {
return std::forward<T>(arg);
}
template<typename Fun, typename T>
static inline auto fetch(const Fun& fun, T&& arg)
-> decltype(fun(std::forward<T>(arg))) {
return fun(std::forward<T>(arg));
}
static inline bool collect(tdata<>&, const tdata<>&) {
return true;
}
template<class TData, class Trans, typename U, typename... Us>
static inline bool collect(TData& td, const Trans& tr,
U&& arg, Us&&... args) {
return store(td.head, fetch(tr.head, std::forward<U>(arg)))
&& collect(td.tail(), tr.tail(), std::forward<Us>(args)...);
}
fun_container m_funs;
};
template<>
class projection<util::empty_type_list> {
public:
projection() = default;
projection(const tdata<>&) { }
projection(const projection&) = default;
template<class PartFun>
optional<typename PartFun::result_type> operator()(PartFun& fun) const {
if (fun.defined_at()) {
return fun();
}
return none;
}
};
template<class ProjectionFuns, class List>
struct projection_from_type_list;
template<class ProjectionFuns, typename... Ts>
struct projection_from_type_list<ProjectionFuns, util::type_list<Ts...> > {
typedef projection<ProjectionFuns, Ts...> type;
};
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_PROJECTION_HPP
......@@ -26,7 +26,7 @@ class proper_actor_base : public Policies::resume_policy::template mixin<Base, D
public:
template <typename... Ts>
template<typename... Ts>
proper_actor_base(Ts&&... args) : super(std::forward<Ts>(args)...) {
CPPA_REQUIRE(this->m_hidden == true);
}
......@@ -40,7 +40,7 @@ class proper_actor_base : public Policies::resume_policy::template mixin<Base, D
typedef typename Policies::scheduling_policy::timeout_type timeout_type;
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit* eu) override {
void enqueue(msg_hdr_cref hdr, message msg, execution_unit* eu) override {
CPPA_PUSH_AID(dptr()->id());
CPPA_LOG_DEBUG(CPPA_TARG(hdr, to_string)
<< ", " << CPPA_TARG(msg, to_string));
......@@ -189,7 +189,7 @@ class proper_actor : public proper_actor_base<Base,
// that Base is derived from local_actor and uses the
// behavior_stack_based mixin
template <typename... Ts>
template<typename... Ts>
proper_actor(Ts&&... args) : super(std::forward<Ts>(args)...) { }
// required by event_based_resume::mixin::resume
......@@ -223,7 +223,7 @@ class proper_actor : public proper_actor_base<Base,
};
// for blocking actors, there's one more member function to implement
template <class Base, class Policies>
template<class Base, class Policies>
class proper_actor<Base, Policies, true> : public proper_actor_base<Base,
proper_actor<Base,
Policies,
......@@ -234,7 +234,7 @@ class proper_actor<Base, Policies, true> : public proper_actor_base<Base,
public:
template <typename... Ts>
template<typename... Ts>
proper_actor(Ts&&... args)
: super(std::forward<Ts>(args)...), m_next_timeout_id(0) { }
......@@ -304,7 +304,7 @@ class proper_actor<Base, Policies, true> : public proper_actor_base<Base,
std::uint32_t request_timeout(const util::duration& d) {
CPPA_REQUIRE(d.valid());
auto tid = ++m_next_timeout_id;
auto msg = make_any_tuple(timeout_msg{tid});
auto msg = make_message(timeout_msg{tid});
if (d.is_zero()) {
// immediately enqueue timeout message if duration == 0s
this->enqueue({this->address(), this},
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_TDATA_HPP
#define CPPA_DETAIL_TDATA_HPP
#include <typeinfo>
#include <functional>
#include <type_traits>
#include "cppa/get.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp"
#include "cppa/util/wrapped.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/tuple_iterator.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
} // namespace cppa
namespace cppa {
namespace detail {
template<typename T>
inline void* ptr_to(T& what) { return &what; }
template<typename T>
inline const void* ptr_to(const T& what) { return &what; }
template<typename T>
inline void* ptr_to(T* what) { return what; }
template<typename T>
inline const void* ptr_to(const T* what) { return what; }
template<typename T>
inline void* ptr_to(const std::reference_wrapper<T>& what) {
return &(what.get());
}
template<typename T>
inline const void* ptr_to(const std::reference_wrapper<const T>& what) {
return &(what.get());
}
template<typename T>
inline const uniform_type_info* utype_of(const T&) {
return static_types_array<T>::arr[0];
}
template<typename T>
inline const uniform_type_info* utype_of(const std::reference_wrapper<T>&) {
return static_types_array<typename util::rm_const_and_ref<T>::type>::arr[0];
}
template<typename T>
inline const uniform_type_info* utype_of(const T* ptr) {
return utype_of(*ptr);
}
template<typename T>
struct boxed_or_void {
static constexpr bool value = is_boxed<T>::value;
};
template<>
struct boxed_or_void<unit_t> {
static constexpr bool value = true;
};
template<typename T>
struct unbox_ref {
typedef T type;
};
template<typename T>
struct unbox_ref<std::reference_wrapper<T> > {
typedef typename std::remove_const<T>::type type;
};
template<typename T>
struct unbox_ref<util::rebindable_reference<T> > {
typedef typename std::remove_const<T>::type type;
};
/*
* "enhanced" std::tuple
*/
template<typename...>
struct tdata;
template<>
struct tdata<> {
typedef tdata super;
unit_t head;
typedef unit_t head_type;
typedef tdata<> tail_type;
typedef unit_t back_type;
typedef util::empty_type_list types;
static constexpr size_t num_elements = 0;
constexpr tdata() { }
// swallow any number of additional boxed or unit_t arguments silently
template<typename... Ts>
tdata(Ts&&...) {
typedef util::type_list<typename util::rm_const_and_ref<Ts>::type...> incoming;
typedef typename util::tl_filter_not_type<incoming, tdata>::type iargs;
static_assert(util::tl_forall<iargs, boxed_or_void>::value,
"Additional unboxed arguments provided");
}
typedef tuple_iterator<tdata> const_iterator;
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
inline const_iterator end() const { return {this}; }
inline const_iterator cend() const { return {this}; }
inline size_t size() const { return num_elements; }
tdata<>& tail() { return *this; }
const tdata<>& tail() const { return *this; }
const tdata<>& ctail() const { return *this; }
inline const void* at(size_t) const {
throw std::out_of_range("tdata<>");
}
inline void* mutable_at(size_t) {
throw std::out_of_range("tdata<>");
}
inline const uniform_type_info* type_at(size_t) const {
throw std::out_of_range("tdata<>");
}
inline void set() { }
inline bool operator==(const tdata&) const { return true; }
inline bool dynamically_typed() const {
return false;
}
};
template<bool IsBoxed, bool IsFunction, typename Head, typename T>
struct td_filter_ {
static inline const T& _(const T& arg) { return arg; }
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
};
template<typename Head, typename T>
struct td_filter_<false, true, Head, T> {
static inline T* _(T* arg) { return arg; }
};
template<typename Head, typename T>
struct td_filter_<true, false, Head, T> {
static inline Head _(const T&) { return Head{}; }
};
template<typename Head, typename T>
struct td_filter_<true, true, Head, T> : td_filter_<true, false, Head, T> { };
template<typename Head, typename T>
auto td_filter(T&& arg)
-> decltype(
td_filter_<
is_boxed<typename util::rm_const_and_ref<T>::type>::value,
std::is_function<typename util::rm_const_and_ref<T>::type>::value,
Head,
typename util::rm_const_and_ref<T>::type
>::_(std::forward<T>(arg))) {
return td_filter_<
is_boxed<typename util::rm_const_and_ref<T>::type>::value,
std::is_function<typename util::rm_const_and_ref<T>::type>::value,
Head,
typename util::rm_const_and_ref<T>::type
>::_(std::forward<T>(arg));
}
template<typename... X, typename... Y>
void tdata_set(tdata<X...>& rhs, const tdata<Y...>& lhs);
template<typename Head, typename... Tail>
struct tdata<Head, Tail...> : tdata<Tail...> {
typedef tdata<Tail...> super;
typedef util::type_list<
typename unbox_ref<Head>::type,
typename unbox_ref<Tail>::type...>
types;
Head head;
static constexpr size_t num_elements = (sizeof...(Tail) + 1);
typedef Head head_type;
typedef tdata<Tail...> tail_type;
typedef typename std::conditional<
(sizeof...(Tail) > 0),
typename tdata<Tail...>::back_type,
Head
>::type
back_type;
inline tdata() : super(), head() { }
//tdata(Head arg) : super(), head(std::move(arg)) { }
tdata(const Head& arg) : super(), head(arg) { }
tdata(Head&& arg) : super(), head(std::move(arg)) { }
template<typename T0, typename T1, typename... Ts>
tdata(T0&& arg0, T1&& arg1, Ts&&... args)
: super(std::forward<T1>(arg1), std::forward<Ts>(args)...)
, head(td_filter<Head>(std::forward<T0>(arg0))) {
}
tdata(const tdata&) = default;
tdata(tdata&& other)
: super(std::move(other.tail())), head(std::move(other.head)) {
}
// allow (partial) initialization from a different tdata
template<typename... Y>
tdata(tdata<Y...>& other) : super(other.tail()), head(other.head) {
}
template<typename... Y>
tdata(const tdata<Y...>& other) : super(other.tail()), head(other.head) {
}
template<typename... Y>
tdata(tdata<Y...>&& other)
: super(std::move(other.tail())), head(std::move(other.head)) {
}
template<typename... Y>
tdata& operator=(const tdata<Y...>& other) {
tdata_set(*this, other);
return *this;
}
template<typename T, typename... Ts>
inline void set(T&& arg, Ts&&... args) {
head = std::forward<T>(arg);
super::set(std::forward<Ts>(args)...);
}
inline size_t size() const { return num_elements; }
typedef tuple_iterator<tdata> const_iterator;
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
inline const_iterator end() const { return {this, size()}; }
inline const_iterator cend() const { return {this, size()}; }
// upcast
inline tdata<Tail...>& tail() { return *this; }
inline const tdata<Tail...>& tail() const { return *this; }
inline const tdata<Tail...>& ctail() const { return *this; }
inline const void* at(size_t p) const {
CPPA_REQUIRE(p < num_elements);
switch (p) {
case 0: return ptr_to(head);
case 1: return ptr_to(super::head);
case 2: return ptr_to(super::super::head);
case 3: return ptr_to(super::super::super::head);
case 4: return ptr_to(super::super::super::super::head);
default: return super::super::super::super::super::at(p - 5);
}
}
inline void* mutable_at(size_t p) {
# ifdef CPPA_DETAIL_DEBUG_MODE
if (p == 0) {
if (std::is_same<decltype(ptr_to(head)), const void*>::value) {
throw std::logic_error{"mutable_at with const head"};
}
return const_cast<void*>(ptr_to(head));
}
return super::mutable_at(p - 1);
# else
return const_cast<void*>(at(p));
# endif
}
inline const uniform_type_info* type_at(size_t p) const {
CPPA_REQUIRE(p < num_elements);
switch (p) {
case 0: return utype_of(head);
case 1: return utype_of(super::head);
case 2: return utype_of(super::super::head);
case 3: return utype_of(super::super::super::head);
case 4: return utype_of(super::super::super::super::head);
default: return super::super::super::super::super::type_at(p - 5);
}
}
Head& _back(std::integral_constant<size_t, 0>) {
return head;
}
template<size_t Pos>
back_type& _back(std::integral_constant<size_t, Pos>) {
std::integral_constant<size_t, Pos-1> token;
return super::_back(token);
}
back_type& back() {
std::integral_constant<size_t, sizeof...(Tail)> token;
return _back(token);
}
const Head& _back(std::integral_constant<size_t, 0>) const {
return head;
}
template<size_t Pos>
const back_type& _back(std::integral_constant<size_t, Pos>) const {
std::integral_constant<size_t, Pos-1> token;
return super::_back(token);
}
const back_type& back() const {
std::integral_constant<size_t, sizeof...(Tail)> token;
return _back(token);
}
};
template<typename... X>
void tdata_set(tdata<X...>&, const tdata<>&) { }
template<typename Head, typename... X, typename... Y>
void tdata_set(tdata<Head, X...>& lhs, tdata<Head, const Y...>& rhs) {
lhs.head = rhs.head;
tdata_set(lhs.tail(), rhs.tail());
}
template<size_t N, typename... Tn>
struct tdata_upcast_helper;
template<size_t N, typename Head, typename... Tail>
struct tdata_upcast_helper<N, Head, Tail...> {
typedef typename tdata_upcast_helper<N-1, Tail...>::type type;
};
template<typename Head, typename... Tail>
struct tdata_upcast_helper<0, Head, Tail...> {
typedef tdata<Head, Tail...> type;
};
template<typename T>
struct tdata_from_type_list;
template<typename... Ts>
struct tdata_from_type_list<util::type_list<Ts...>> {
typedef tdata<Ts...> type;
};
template<typename T, typename U>
inline void rebind_value(T& lhs, U& rhs) {
lhs = rhs;
}
template<typename T, typename U>
inline void rebind_value(util::rebindable_reference<T>& lhs, U& rhs) {
lhs.rebind(rhs);
}
template<typename... Ts>
inline void rebind_tdata(tdata<Ts...>&) { }
template<typename... Ts, typename... Vs>
void rebind_tdata(tdata<Ts...>& td, const tdata<>&, const Vs&... args) {
rebind_tdata(td, args...);
}
template<typename... Ts, typename... Us, typename... Vs>
void rebind_tdata(tdata<Ts...>& td, const tdata<Us...>& arg, const Vs&... args) {
rebind_value(td.head, arg.head);
rebind_tdata(td.tail(), arg.tail(), args...);
}
} // namespace detail
} // namespace cppa
namespace cppa {
template<size_t N, typename... Ts>
const typename util::type_at<N, Ts...>::type& get(const detail::tdata<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()");
return static_cast<const typename detail::tdata_upcast_helper<N, Ts...>::type&>(tv).head;
}
template<size_t N, typename... Ts>
typename util::type_at<N, Ts...>::type& get_ref(detail::tdata<Ts...>& tv) {
static_assert(N < sizeof...(Ts), "N >= tv.size()");
return static_cast<typename detail::tdata_upcast_helper<N, Ts...>::type&>(tv).head;
}
} // namespace cppa
#endif // CPPA_DETAIL_TDATA_HPP
......@@ -20,12 +20,11 @@
#ifndef CPPA_DETAIL_TUPLE_CAST_IMPL_HPP
#define CPPA_DETAIL_TUPLE_CAST_IMPL_HPP
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa {
namespace detail {
......@@ -46,7 +45,7 @@ struct tuple_cast_impl {
static_cast<size_t>(
util::tl_find<util::type_list<T...>, anything>::value);
typedef util::limited_vector<size_t, size> mapping_vector;
static inline optional<Result> safe(any_tuple& tup) {
static inline optional<Result> safe(message& tup) {
mapping_vector mv;
if (matches<T...>(tup, mv)) return {Result::from(std::move(tup.vals()),
mv)};
......@@ -56,7 +55,7 @@ struct tuple_cast_impl {
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::nil, Result, T...> {
static inline optional<Result> safe(any_tuple& tup) {
static inline optional<Result> safe(message& tup) {
if (matches<T...>(tup)) return {Result::from(std::move(tup.vals()))};
return none;
}
......@@ -69,7 +68,7 @@ struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::leading, Result, T...> {
static inline optional<Result> safe(any_tuple& tup) {
static inline optional<Result> safe(message& tup) {
size_t o = tup.size() - (sizeof...(T) - 1);
if (matches<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)};
return none;
......
......@@ -23,14 +23,14 @@
#include <typeinfo>
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tuple_iterator.hpp"
#include "cppa/detail/message_iterator.hpp"
namespace cppa {
namespace detail {
struct tuple_dummy {
typedef util::empty_type_list types;
typedef detail::tuple_iterator<tuple_dummy> const_iterator;
typedef detail::message_iterator<tuple_dummy> const_iterator;
inline size_t size() const {
return 0;
}
......
......@@ -16,68 +16,77 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_TUPLE_VALS_HPP
#define CPPA_TUPLE_VALS_HPP
#ifndef CPPA_DETAIL_TUPLE_VALS_HPP
#define CPPA_DETAIL_TUPLE_VALS_HPP
#include <tuple>
#include <stdexcept>
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tdata.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/message_data.hpp"
#include "cppa/detail/serialize_tuple.hpp"
namespace cppa {
namespace detail {
template<size_t Pos, size_t Max, bool InRange = (Pos < Max)>
struct tup_ptr_access {
template<class T>
static inline typename std::conditional<std::is_const<T>::value,
const void*, void*>::type
get(size_t pos, T& tup) {
if (pos == Pos) return &std::get<Pos>(tup);
return tup_ptr_access<Pos + 1, Max>::get(pos, tup);
}
};
template<size_t Pos, size_t Max>
struct tup_ptr_access<Pos, Max, false> {
template<class T>
static inline typename std::conditional<std::is_const<T>::value,
const void*, void*>::type
get(size_t, T&) {
// end of recursion
return nullptr;
}
};
template<typename... Ts>
class tuple_vals : public abstract_tuple {
class tuple_vals : public message_data {
static_assert(sizeof...(Ts) > 0,
"tuple_vals is not allowed to be empty");
static_assert(sizeof...(Ts) > 0, "tuple_vals is not allowed to be empty");
typedef abstract_tuple super;
typedef message_data super;
public:
typedef tdata<Ts...> data_type;
typedef std::tuple<Ts...> data_type;
typedef types_array<Ts...> element_types;
tuple_vals(const tuple_vals&) = default;
template<typename... Us>
tuple_vals(Us&&... args) : super(false), m_data(std::forward<Us>(args)...) { }
tuple_vals(Us&&... args)
: super(false), m_data(std::forward<Us>(args)...) {}
const void* native_data() const {
return &m_data;
}
const void* native_data() const { return &m_data; }
void* mutable_native_data() {
return &m_data;
}
void* mutable_native_data() { return &m_data; }
inline data_type& data() {
return m_data;
}
inline data_type& data() { return m_data; }
inline const data_type& data() const {
return m_data;
}
inline const data_type& data() const { return m_data; }
size_t size() const {
return sizeof...(Ts);
}
size_t size() const { return sizeof...(Ts); }
tuple_vals* copy() const {
return new tuple_vals(*this);
}
tuple_vals* copy() const { return new tuple_vals(*this); }
const void* at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_data.at(pos);
return tup_ptr_access<0, sizeof...(Ts)>::get(pos, m_data);
}
void* mutable_at(size_t pos) {
......@@ -90,13 +99,13 @@ class tuple_vals : public abstract_tuple {
return m_types[pos];
}
bool equals(const abstract_tuple& other) const {
bool equals(const message_data& other) const {
if (size() != other.size()) return false;
const tuple_vals* o = dynamic_cast<const tuple_vals*>(&other);
if (o) {
return m_data == (o->m_data);
}
return abstract_tuple::equals(other);
return message_data::equals(other);
}
const std::type_info* type_token() const {
......@@ -120,15 +129,7 @@ class tuple_vals : public abstract_tuple {
template<typename... Ts>
types_array<Ts...> tuple_vals<Ts...>::m_types;
template<typename TypeList>
struct tuple_vals_from_type_list;
template<typename... Ts>
struct tuple_vals_from_type_list< util::type_list<Ts...> > {
typedef tuple_vals<Ts...> type;
};
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_TUPLE_VALS_HPP
#endif // CPPA_TUPLE_VALS_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_TUPLE_VIEW_HPP
#define CPPA_DETAIL_TUPLE_VIEW_HPP
#include "cppa/guard_expr.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa {
namespace detail {
struct tuple_view_copy_helper {
size_t pos;
abstract_tuple* target;
tuple_view_copy_helper(abstract_tuple* trgt) : pos(0), target(trgt) { }
template<typename T>
void operator()(const T* value) {
*(reinterpret_cast<T*>(target->mutable_at(pos++))) = *value;
}
};
template<typename... Ts>
class tuple_view : public abstract_tuple {
static_assert(sizeof...(Ts) > 0,
"tuple_vals is not allowed to be empty");
typedef abstract_tuple super;
public:
typedef tdata<util::rebindable_reference<Ts>...> data_type;
typedef types_array<Ts...> element_types;
tuple_view() = delete;
tuple_view(const tuple_view&) = delete;
/**
* @warning @p tuple_view does @b NOT takes ownership for given pointers
*/
tuple_view(Ts*... args) : super(false), m_data(args...) { }
inline data_type& data() {
return m_data;
}
inline const data_type& data() const {
return m_data;
}
size_t size() const {
return sizeof...(Ts);
}
abstract_tuple* copy() const {
return new tuple_vals<Ts...>{m_data};
}
const void* at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_data.at(pos).get_ptr();
}
void* mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size());
return m_data.mutable_at(pos).get_ptr();
}
const uniform_type_info* type_at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_types[pos];
}
const std::type_info* type_token() const {
return detail::static_type_list<Ts...>::list;
}
private:
data_type m_data;
static types_array<Ts...> m_types;
tuple_view(const data_type& data) : m_data(data) { }
};
template<typename... Ts>
types_array<Ts...> tuple_view<Ts...>::m_types;
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_TUPLE_VIEW_HPP
......@@ -16,53 +16,23 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_TUPLE_ZIP_HPP
#define CPPA_DETAIL_TUPLE_ZIP_HPP
#ifndef CPPA_DETAIL_OBJECT_ARRAY_HPP
#define CPPA_DETAIL_OBJECT_ARRAY_HPP
#include <tuple>
#include <vector>
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/util/int_list.hpp"
namespace cppa {
namespace detail {
class object_array : public abstract_tuple {
typedef abstract_tuple super;
public:
using abstract_tuple::const_iterator;
object_array();
object_array(object_array&&) = default;
object_array(const object_array&);
~object_array();
void push_back(uniform_value what);
void* mutable_at(size_t pos) override;
size_t size() const override;
object_array* copy() const override;
const void* at(size_t pos) const override;
const uniform_type_info* type_at(size_t pos) const override;
const std::string* tuple_type_names() const override;
private:
std::vector<uniform_value> m_elements;
};
template <typename F, long... Is, class Tup0, class Tup1>
auto tuple_zip(F& f, util::int_list<Is...>, Tup0&& tup0, Tup1&& tup1)
-> decltype(std::make_tuple(f(std::get<Is>(tup0), std::get<Is>(tup1))...)) {
return std::make_tuple(f(std::get<Is>(tup0), std::get<Is>(tup1))...);
}
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_OBJECT_ARRAY_HPP
#endif // CPPA_DETAIL_TUPLE_ZIP_HPP
......@@ -62,14 +62,6 @@ struct deduce_signature {
typedef typename deduce_signature_helper<result_type, arg_types>::type type;
};
template<typename T>
struct match_expr_has_no_guard {
static constexpr bool value = std::is_same<
typename T::second_type::guard_type,
detail::empty_value_guard
>::value;
};
template<typename Arguments>
struct input_is {
template<typename Signature>
......
......@@ -54,7 +54,6 @@ using mapped_type_list = util::type_list<
acceptor_closed_msg,
actor,
actor_addr,
any_tuple,
atom_value,
channel,
connection_closed_msg,
......@@ -65,6 +64,7 @@ using mapped_type_list = util::type_list<
node_id_ptr,
io::accept_handle,
io::connection_handle,
message,
message_header,
new_connection_msg,
new_data_msg,
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_DETAIL_VALUE_GUARD_HPP
#define CPPA_DETAIL_VALUE_GUARD_HPP
#include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/util/algorithm.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa {
namespace detail {
// 'absorbs' callables and instances of `anything`
template<typename T>
const T& vg_fwd(const T& arg, typename std::enable_if<not util::is_callable<T>::value>::type* = 0) {
return arg;
}
inline unit_t vg_fwd(const anything&) {
return unit;
}
template<typename T>
unit_t vg_fwd(const T&, typename std::enable_if<util::is_callable<T>::value>::type* = 0) {
return unit;
}
template<typename T>
struct vg_cmp {
template<typename U>
inline static bool _(const T& lhs, const U& rhs) {
return util::safe_equal(lhs, rhs);
}
};
template<>
struct vg_cmp<unit_t> {
template<typename T>
inline static bool _(const unit_t&, const T&) {
return true;
}
};
template<typename FilteredPattern>
class value_guard {
public:
value_guard() = default;
value_guard(const value_guard&) = default;
template<typename... Ts>
value_guard(const Ts&... args) : m_args(vg_fwd(args)...) { }
template<typename... Ts>
inline bool operator()(const Ts&... args) const {
return _eval(m_args.head, m_args.tail(), args...);
}
private:
typename tdata_from_type_list<FilteredPattern>::type m_args;
template<typename T, typename U>
static inline bool cmp(const T& lhs, const U& rhs) {
return vg_cmp<T>::_(lhs, rhs);
}
template<typename T, typename U>
static inline bool cmp(const T& lhs, const std::reference_wrapper<U>& rhs) {
return vg_cmp<T>::_(lhs, rhs.get());
}
static inline bool _eval(const unit_t&, const tdata<>&) {
return true;
}
template<typename T, typename U, typename... Us>
static inline bool _eval(const T& head, const tdata<>&,
const U& arg, const Us&...) {
return cmp(head, arg);
}
template<typename T0, typename T1, typename... Ts,
typename U, typename... Us>
static inline bool _eval(const T0& head, const tdata<T1, Ts...>& tail,
const U& arg, const Us&... args) {
return cmp(head, arg) && _eval(tail.head, tail.tail(), args...);
}
};
typedef value_guard<util::empty_type_list> empty_value_guard;
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_VALUE_GUARD_HPP
......@@ -29,7 +29,7 @@
namespace cppa {
class channel;
class any_tuple;
class message;
class message_header;
struct invalid_group_t { constexpr invalid_group_t() { } };
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_GUARD_EXPR_HPP
#define CPPA_GUARD_EXPR_HPP
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/config.hpp"
#include "cppa/optional.hpp"
#include "cppa/util/call.hpp"
#include "cppa/util/algorithm.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa {
enum operator_id {
// arithmetic operators
addition_op, subtraction_op, multiplication_op, division_op, modulo_op,
// comparison operators
less_op, less_eq_op, greater_op, greater_eq_op, equal_op, not_equal_op,
// logical operators
logical_and_op, logical_or_op,
// pseudo operators for function invocation
exec_fun1_op, exec_fun2_op, exec_fun3_op,
// operator to invoke a given functor with all arguments forwarded
exec_xfun_op,
// pseudo operator to store function parameters
dummy_op
};
// {operator, lhs, rhs} expression
template<operator_id OP, typename First, typename Second>
struct guard_expr {
typedef First first_type;
typedef Second second_type;
std::pair<First, Second> m_args;
//guard_expr() = default;
template<typename T0, typename T1>
guard_expr(T0&& a0, T1&& a1)
: m_args(std::forward<T0>(a0), std::forward<T1>(a1)) {
}
// {operator, {operator, a0, a1}, a2}
template<typename T0, typename T1, typename T2>
guard_expr(T0&& a0, T1&& a1, T2&& a2)
: m_args(First{std::forward<T0>(a0), std::forward<T1>(a1)},
std::forward<T2>(a2)) {
}
// {operator, {operator, a0, a1}, {operator, a2, a3}}
template<typename T0, typename T1, typename T2, typename T3>
guard_expr(T0&& a0, T1&& a1, T2&& a2, T3&& a3)
: m_args(First{std::forward<T0>(a0), std::forward<T1>(a1)},
Second{std::forward<T2>(a2), std::forward<T3>(a3)}) {
}
guard_expr(const guard_expr&) = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
template<typename... Ts>
bool operator()(const Ts&... args) const;
};
/*
* @brief Invokes SubMacro for "+", "-", "*", "/", "%", "<", "<=", ">" and ">=".
**/
#define CPPA_FORALL_DEFAULT_OPS(SubMacro) \
SubMacro (addition_op, +) SubMacro (subtraction_op, -) \
SubMacro (multiplication_op, *) SubMacro (division_op, /) \
SubMacro (modulo_op, %) SubMacro (less_op, <) \
SubMacro (less_eq_op, <=) SubMacro (greater_op, >) \
SubMacro (greater_eq_op, >=)
/**
* @brief Creates a reference wrapper similar to std::reference_wrapper<const T>
* that could be used in guard expressions or to enforce lazy evaluation.
*/
template<typename T>
util::rebindable_reference<const T> gref(const T& value) {
return {value};
}
//ge_reference_wrapper<T> gref(const T& value) { return {value}; }
// bind utility for placeholders
template<typename Fun, typename T1>
struct gcall1 {
typedef guard_expr<exec_fun1_op, Fun, T1> result;
};
template<typename Fun, typename T1, typename T2>
struct gcall2 {
typedef guard_expr<exec_fun2_op, guard_expr<dummy_op, Fun, T1>, T2> result;
};
template<typename Fun, typename T1, typename T2, typename T3>
struct gcall3 {
typedef guard_expr<exec_fun3_op, guard_expr<dummy_op, Fun, T1>,
guard_expr<dummy_op, T2, T3> >
result;
};
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template<typename Fun, typename T1>
typename gcall1<Fun, T1>::result gcall(Fun fun, T1 t1) {
return {fun, t1};
}
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template<typename Fun, typename T1, typename T2>
typename gcall2<Fun, T1, T2>::result gcall(Fun fun, T1 t1, T2 t2) {
return {fun, t1, t2};
}
/**
* @brief Call wrapper for guard placeholders and lazy evaluation.
*/
template<typename Fun, typename T1, typename T2, typename T3>
typename gcall3<Fun, T1, T2, T3>::result gcall(Fun fun, T1 t1, T2 t2, T3 t3) {
return {fun, t1, t2, t3};
}
/**
* @brief Calls @p fun with all arguments given to the guard expression.
* The functor @p fun must return a boolean.
*/
template<typename Fun>
guard_expr<exec_xfun_op, Fun, unit_t> ge_sub_function(Fun fun) {
return {fun, unit};
}
struct ge_search_container {
bool sc;
ge_search_container(bool should_contain) : sc(should_contain) { }
template<class C>
bool operator()(const C& haystack,
const typename C::value_type& needle) const {
typedef typename C::value_type vtype;
if (sc)
return std::any_of(haystack.begin(), haystack.end(),
[&](const vtype& val) { return needle == val; });
return std::none_of(haystack.begin(), haystack.end(),
[&](const vtype& val) { return needle == val; });
}
};
struct ge_get_size {
template<class C>
inline auto operator()(const C& what) const -> decltype(what.size()) {
return what.size();
}
};
struct ge_is_empty {
bool expected;
ge_is_empty(bool expected_value) : expected(expected_value) { }
template<class C>
inline bool operator()(const C& what) const {
return what.empty() == expected;
}
};
struct ge_get_front {
template<class C>
inline auto operator()(const C& what,
typename std::enable_if<
std::is_reference<
decltype(what.front())
>::value
>::type* = 0) const
-> optional<
std::reference_wrapper<
const typename util::rm_const_and_ref<decltype(what.front())>::type> > {
if (what.empty() == false) return {what.front()};
return none;
}
template<class C>
inline auto operator()(const C& what,
typename std::enable_if<
std::is_reference<
decltype(what.front())
>::value == false
>::type* = 0) const
-> optional<decltype(what.front())> {
if (what.empty() == false) return {what.front()};
return none;
}
};
/**
* @brief A placeholder for guard expression.
*/
template<int X>
struct guard_placeholder {
constexpr guard_placeholder() { }
/**
* @brief Convenient way to call <tt>gcall(fun, guard_placeholder)</tt>.
*/
template<typename Fun>
typename gcall1<Fun, guard_placeholder>::result operator()(Fun fun) const {
return gcall(fun, *this);
}
// utility function for starts_with()
static bool u8_starts_with(const std::string& lhs, const std::string& rhs) {
return std::equal(rhs.begin(), rhs.end(), lhs.begin());
}
/**
* @brief Evaluates to the size of a container.
*/
typename gcall1<ge_get_size, guard_placeholder>::result size() const {
return gcall(ge_get_size{}, *this);
}
typename gcall1<ge_is_empty, guard_placeholder>::result empty() const {
return gcall(ge_is_empty{true}, *this);
}
typename gcall1<ge_is_empty, guard_placeholder>::result not_empty() const {
return gcall(ge_is_empty{false}, *this);
}
/**
* @brief Evaluates to the first element of a container if it's not empty.
*/
typename gcall1<ge_get_front, guard_placeholder>::result front() const {
return gcall(ge_get_front{}, *this);
}
/**
* @brief Evaluates to true if unbound argument starts with @p str.
*/
typename gcall2<decltype(&guard_placeholder::u8_starts_with),
guard_placeholder,
std::string
>::result
starts_with(std::string str) const {
return gcall(&guard_placeholder::u8_starts_with, *this, std::move(str));
}
/**
* @brief Evaluates to true if unbound argument
* is contained in @p container.
*/
template<class C>
typename gcall2<ge_search_container, C, guard_placeholder>::result
in(C container) const {
return gcall(ge_search_container{true}, std::move(container), *this);
}
/**
* @brief Evaluates to true if unbound argument
* is contained in @p list.
*/
template<typename T>
typename gcall2<ge_search_container,
std::vector<typename detail::strip_and_convert<T>::type>,
guard_placeholder
>::result
in(std::initializer_list<T> list) const {
std::vector<typename detail::strip_and_convert<T>::type> vec;
for (auto& i : list) vec.emplace_back(i);
return in(std::move(vec));
}
/**
* @brief Evaluates to true if unbound argument
* is not contained in @p container.
*/
template<class C>
typename gcall2<ge_search_container, C, guard_placeholder>::result
not_in(C container) const {
return gcall(ge_search_container{false}, std::move(container), *this);
}
/**
* @brief Evaluates to true if unbound argument
* is not contained in @p list.
*/
template<typename T>
typename gcall2<ge_search_container,
std::vector<typename detail::strip_and_convert<T>::type>,
guard_placeholder
>::result
not_in(std::initializer_list<T> list) const {
std::vector<typename detail::strip_and_convert<T>::type> vec;
for (auto& i : list) vec.emplace_back(i);
return not_in(vec);
}
};
template<typename T>
struct ge_value {
T value;
};
template<typename T>
ge_value<T> gval(T val) { return {std::move(val)}; }
// result type computation
template<typename T, class Tuple>
struct ge_unbound { typedef T type; };
template<typename T, class Tuple>
struct ge_unbound<util::rebindable_reference<const T>, Tuple> { typedef T type; };
template<typename T, class Tuple>
struct ge_unbound<std::reference_wrapper<T>, Tuple> { typedef T type; };
template<typename T, class Tuple>
struct ge_unbound<std::reference_wrapper<const T>, Tuple> { typedef T type; };
template<typename T, class Tuple>
struct ge_unbound<ge_value<T>, Tuple> { typedef T type; };
// unbound type of placeholder
template<int X, typename... Ts>
struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> > {
static_assert(X < sizeof...(Ts),
"Cannot unbind placeholder (too few arguments)");
typedef typename ge_unbound<
typename util::type_at<X, Ts...>::type,
detail::tdata<std::reference_wrapper<Ts>...>
>::type
type;
};
// operators, operators, operators
template<typename T>
struct is_ge_type {
static constexpr bool value = false;
};
template<int X>
struct is_ge_type<guard_placeholder<X> > {
static constexpr bool value = true;
};
template<typename T>
struct is_ge_type<util::rebindable_reference<T> > {
static constexpr bool value = true;
};
template<operator_id OP, typename First, typename Second>
struct is_ge_type<guard_expr<OP, First, Second> > {
static constexpr bool value = true;
};
template<typename T>
struct is_ge_type<ge_value<T>> {
static constexpr bool value = true;
};
template<operator_id OP, typename T1, typename T2>
guard_expr<OP, typename detail::strip_and_convert<T1>::type,
typename detail::strip_and_convert<T2>::type>
ge_concatenate(T1 first, T2 second,
typename std::enable_if<
is_ge_type<T1>::value || is_ge_type<T2>::value
>::type* = 0) {
return {first, second};
}
#define CPPA_GE_OPERATOR(EnumValue, Operator) \
template<typename T1, typename T2> \
auto operator Operator (T1 v1, T2 v2) \
-> decltype(ge_concatenate< EnumValue >(v1, v2)) { \
return ge_concatenate< EnumValue >(v1, v2); \
}
CPPA_FORALL_DEFAULT_OPS(CPPA_GE_OPERATOR)
CPPA_GE_OPERATOR(equal_op, ==)
CPPA_GE_OPERATOR(not_equal_op, !=)
template<operator_id OP>
struct ge_eval_op;
#define CPPA_EVAL_OP_IMPL(EnumValue, Operator) \
template<> struct ge_eval_op< EnumValue > { \
template<typename T1, typename T2> \
static inline auto _(const T1& lhs, const T2& rhs) \
-> decltype(lhs Operator rhs) { return lhs Operator rhs; } \
};
CPPA_FORALL_DEFAULT_OPS(CPPA_EVAL_OP_IMPL)
CPPA_EVAL_OP_IMPL(logical_and_op, &&)
CPPA_EVAL_OP_IMPL(logical_or_op, ||)
template<> struct ge_eval_op<equal_op> {
template<typename T1, typename T2>
static inline bool _(const T1& lhs, const T2& rhs) {
return util::safe_equal(lhs, rhs);
}
};
template<> struct ge_eval_op<not_equal_op> {
template<typename T1, typename T2>
static inline bool _(const T1& lhs, const T2& rhs) {
return !util::safe_equal(lhs, rhs);
}
};
template<typename T, class Tuple>
struct ge_result_ {
typedef typename ge_unbound<T, Tuple>::type type;
};
template<operator_id OP, typename First, typename Second, class Tuple>
struct ge_result_<guard_expr<OP, First, Second>, Tuple> {
typedef typename ge_result_<First, Tuple>::type lhs_type;
typedef typename ge_result_<Second, Tuple>::type rhs_type;
typedef decltype(
ge_eval_op<OP>::_(*static_cast<const lhs_type*>(nullptr),
*static_cast<const rhs_type*>(nullptr))) type;
};
template<typename Fun, class Tuple>
struct ge_result_<guard_expr<exec_xfun_op, Fun, unit_t>, Tuple> {
typedef bool type;
};
template<typename First, typename Second, class Tuple>
struct ge_result_<guard_expr<exec_fun1_op, First, Second>, Tuple> {
typedef First type0;
typedef typename ge_unbound<Second, Tuple>::type type1;
typedef decltype( (*static_cast<const type0*>(nullptr))(
*static_cast<const type1*>(nullptr)
)) type;
};
template<typename First, typename Second, class Tuple>
struct ge_result_<guard_expr<exec_fun2_op, First, Second>, Tuple> {
typedef typename First::first_type type0;
typedef typename ge_unbound<typename First::second_type, Tuple>::type type1;
typedef typename ge_unbound<Second, Tuple>::type type2;
typedef decltype( (*static_cast<const type0*>(nullptr))(
*static_cast<const type1*>(nullptr),
*static_cast<const type2*>(nullptr)
)) type;
};
template<typename First, typename Second, class Tuple>
struct ge_result_<guard_expr<exec_fun3_op, First, Second>, Tuple> {
typedef typename First::first_type type0;
typedef typename ge_unbound<typename First::second_type, Tuple>::type type1;
typedef typename ge_unbound<typename Second::first_type, Tuple>::type type2;
typedef typename ge_unbound<typename Second::second_type, Tuple>::type type3;
typedef decltype( (*static_cast<const type0*>(nullptr))(
*static_cast<const type1*>(nullptr),
*static_cast<const type2*>(nullptr),
*static_cast<const type3*>(nullptr)
)) type;
};
template<operator_id OP, typename First, typename Second, class Tuple>
struct ge_result {
typedef typename ge_result_<guard_expr<OP, First, Second>, Tuple>::type
type;
};
template<operator_id OP1, typename F1, typename S1,
operator_id OP2, typename F2, typename S2>
guard_expr<logical_and_op, guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>>
operator&&(guard_expr<OP1, F1, S1> lhs,
guard_expr<OP2, F2, S2> rhs) {
return {lhs, rhs};
}
template<operator_id OP1, typename F1, typename S1,
operator_id OP2, typename F2, typename S2>
guard_expr<logical_or_op, guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>>
operator||(guard_expr<OP1, F1, S1> lhs,
guard_expr<OP2, F2, S2> rhs) {
return {lhs, rhs};
}
// evaluation of guard_expr
template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const T& value) {
return value;
}
template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<T>& value) {
return value.get();
}
template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<const T>& value) {
return value.get();
}
template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const util::rebindable_reference<const T>& value) {
return value.get();
}
template<class Tuple, typename T>
inline const T& ge_resolve(const Tuple&, const ge_value<T>& wrapped_value) {
return wrapped_value.value;
}
template<class Tuple, int X>
inline auto ge_resolve(const Tuple& tup, guard_placeholder<X>)
-> decltype(get<X>(tup).get()) {
return get<X>(tup).get();
}
template<class Tuple, operator_id OP, typename First, typename Second>
auto ge_resolve(const Tuple& tup,
const guard_expr<OP, First, Second>& ge)
-> typename ge_result<OP, First, Second, Tuple>::type;
template<operator_id OP, class Tuple, typename First, typename Second>
struct ge_eval_ {
static inline typename ge_result<OP, First, Second, Tuple>::type
_(const Tuple& tup, const First& lhs, const Second& rhs) {
return ge_eval_op<OP>::_(ge_resolve(tup, lhs), ge_resolve(tup, rhs));
}
};
template<class Tuple, typename First, typename Second>
struct ge_eval_<logical_and_op, Tuple, First, Second> {
static inline bool _(const Tuple& tup, const First& lhs, const Second& rhs) {
// emulate short-circuit evaluation
if (ge_resolve(tup, lhs)) return ge_resolve(tup, rhs);
return false;
}
};
template<class Tuple, typename First, typename Second>
struct ge_eval_<logical_or_op, Tuple, First, Second> {
static inline bool _(const Tuple& tup, const First& lhs, const Second& rhs) {
// emulate short-circuit evaluation
if (ge_resolve(tup, lhs)) return true;
return ge_resolve(tup, rhs);
}
};
template<class Tuple, typename Fun>
struct ge_eval_<exec_xfun_op, Tuple, Fun, unit_t> {
static inline bool _(const Tuple& tup, const Fun& fun, const unit_t&) {
return util::apply_args(fun, tup, util::get_indices(tup));
}
};
template<class Tuple, typename First, typename Second>
struct ge_eval_<exec_fun1_op, Tuple, First, Second> {
static inline auto _(const Tuple& tup, const First& fun, const Second& arg0)
-> decltype(fun(ge_resolve(tup, arg0))) {
return fun(ge_resolve(tup, arg0));
}
};
template<class Tuple, typename First, typename Second>
struct ge_eval_<exec_fun2_op, Tuple, First, Second> {
static inline auto _(const Tuple& tup, const First& lhs, const Second& rhs)
-> decltype(lhs.m_args.first(ge_resolve(tup, lhs.m_args.second),
ge_resolve(tup, rhs))) {
return lhs.m_args.first(ge_resolve(tup, lhs.m_args.second),
ge_resolve(tup, rhs));
}
};
template<class Tuple, typename First, typename Second>
struct ge_eval_<exec_fun3_op, Tuple, First, Second> {
static inline auto _(const Tuple& tup, const First& lhs, const Second& rhs)
-> decltype(lhs.m_args.first(ge_resolve(tup, lhs.m_args.second),
ge_resolve(tup, rhs.m_args.first),
ge_resolve(tup, rhs.m_args.second))) {
return lhs.m_args.first(ge_resolve(tup, lhs.m_args.second),
ge_resolve(tup, rhs.m_args.first),
ge_resolve(tup, rhs.m_args.second));
}
};
template<operator_id OP, class Tuple, typename First, typename Second>
inline typename ge_result<OP, First, Second, Tuple>::type
ge_eval(const Tuple& tup, const First& lhs, const Second& rhs) {
return ge_eval_<OP, Tuple, First, Second>::_(tup, lhs, rhs);
}
template<class Tuple, operator_id OP, typename First, typename Second>
auto ge_resolve(const Tuple& tup,
const guard_expr<OP, First, Second>& ge)
-> typename ge_result<OP, First, Second, Tuple>::type {
return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second);
}
template<operator_id OP, typename First, typename Second, typename... Ts>
auto ge_invoke_step2(const guard_expr<OP, First, Second>& ge,
const detail::tdata<Ts...>& tup)
-> typename ge_result<OP, First, Second, detail::tdata<Ts...>>::type {
return ge_eval<OP>(tup, ge.m_args.first, ge.m_args.second);
}
template<operator_id OP, typename First, typename Second, typename... Ts>
auto ge_invoke(const guard_expr<OP, First, Second>& ge,
const Ts&... args)
-> typename ge_result<OP, First, Second,
detail::tdata<std::reference_wrapper<const Ts>...>>::type {
detail::tdata<std::reference_wrapper<const Ts>...> tup{args...};
return ge_invoke_step2(ge, tup);
}
template<class GuardExpr>
struct ge_invoke_helper {
const GuardExpr& ge;
ge_invoke_helper(const GuardExpr& arg) : ge(arg) { }
template<typename... Ts>
bool operator()(Ts&&... args) const {
return ge_invoke(ge, std::forward<Ts>(args)...);
}
};
template<operator_id OP, typename First, typename Second>
template<typename... Ts>
bool guard_expr<OP, First, Second>::operator()(const Ts&... args) const {
static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value,
"guard expression does not return a boolean");
return ge_invoke(*this, args...);
}
// some utility functions
template<typename T>
struct gref_wrapped {
typedef util::rebindable_reference<const typename util::rm_const_and_ref<T>::type> type;
};
template<typename T>
struct mutable_gref_wrapped {
typedef util::rebindable_reference<T> type;
};
template<typename T>
struct mutable_gref_wrapped<T&> {
typedef util::rebindable_reference<T> type;
};
// finally ...
namespace placeholders {
constexpr guard_placeholder<0> _x1;
constexpr guard_placeholder<1> _x2;
constexpr guard_placeholder<2> _x3;
constexpr guard_placeholder<3> _x4;
constexpr guard_placeholder<4> _x5;
constexpr guard_placeholder<5> _x6;
constexpr guard_placeholder<6> _x7;
constexpr guard_placeholder<7> _x8;
constexpr guard_placeholder<8> _x9;
} // namespace placeholders
} // namespace cppa
#endif // CPPA_GUARD_EXPR_HPP
......@@ -146,7 +146,7 @@ class broker : public extend<local_actor>::
return add_acceptor(tcp_acceptor::from_sockfd(tcp_sockfd));
}
void enqueue(msg_hdr_cref, any_tuple, execution_unit*) override;
void enqueue(msg_hdr_cref, message, execution_unit*) override;
template<typename F>
static broker_ptr from(F fun) {
......@@ -192,7 +192,7 @@ class broker : public extend<local_actor>::
static broker_ptr from_impl(std::function<behavior (broker*)> fun);
void invoke_message(msg_hdr_cref hdr, any_tuple msg);
void invoke_message(msg_hdr_cref hdr, message msg);
bool invoke_message_from_cache();
......
......@@ -22,7 +22,7 @@
#include <vector>
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/message_header.hpp"
......@@ -33,7 +33,7 @@ class default_message_queue : public ref_counted {
public:
typedef std::pair<message_header, any_tuple> value_type;
typedef std::pair<message_header, message> value_type;
typedef value_type& reference;
......
......@@ -134,7 +134,7 @@ class middleman {
*/
virtual void deliver(const node_id& node,
msg_hdr_cref hdr,
any_tuple msg ) = 0;
message msg ) = 0;
/**
* @brief This callback is invoked by {@link peer} implementations
......
......@@ -26,7 +26,7 @@
#include "cppa/extend.hpp"
#include "cppa/node_id.hpp"
#include "cppa/actor_proxy.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/type_lookup_table.hpp"
#include "cppa/weak_intrusive_ptr.hpp"
......@@ -63,7 +63,7 @@ class peer : public extend<continuable>::with<buffered_writing> {
void io_failed(event_bitmask mask) override;
void enqueue(msg_hdr_cref hdr, const any_tuple& msg);
void enqueue(msg_hdr_cref hdr, const message& msg);
inline bool stop_on_last_proxy_exited() const {
return m_stop_on_last_proxy_exited;
......@@ -109,7 +109,7 @@ class peer : public extend<continuable>::with<buffered_writing> {
// point to the published actor of the remote node
bool m_stop_on_last_proxy_exited;
partial_function m_content_handler;
message_handler m_content_handler;
type_lookup_table m_incoming_types;
type_lookup_table m_outgoing_types;
......@@ -122,13 +122,13 @@ class peer : public extend<continuable>::with<buffered_writing> {
void unlink(const actor_addr& sender, const actor_addr& ptr);
void deliver(msg_hdr_cref hdr, any_tuple msg);
void deliver(msg_hdr_cref hdr, message msg);
inline void enqueue(const any_tuple& msg) {
inline void enqueue(const message& msg) {
enqueue({invalid_actor_addr, nullptr}, msg);
}
void enqueue_impl(msg_hdr_cref hdr, const any_tuple& msg);
void enqueue_impl(msg_hdr_cref hdr, const message& msg);
void add_type_if_needed(const std::string& tname);
......
......@@ -72,7 +72,7 @@ class remote_actor_proxy : public actor_proxy {
node_id_ptr pinfo,
middleman* parent);
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit*) override;
void enqueue(msg_hdr_cref hdr, message msg, execution_unit*) override;
void link_to(const actor_addr& other) override;
......@@ -86,7 +86,7 @@ class remote_actor_proxy : public actor_proxy {
void local_unlink_from(const actor_addr& other) override;
void deliver(msg_hdr_cref hdr, any_tuple msg) override;
void deliver(msg_hdr_cref hdr, message msg) override;
protected:
......@@ -94,7 +94,7 @@ class remote_actor_proxy : public actor_proxy {
private:
void forward_msg(msg_hdr_cref hdr, any_tuple msg);
void forward_msg(msg_hdr_cref hdr, message msg);
middleman* m_parent;
intrusive::single_reader_queue<sync_request_info, detail::disposer> m_pending_requests;
......
......@@ -28,7 +28,7 @@
#include "cppa/extend.hpp"
#include "cppa/channel.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/spawn_fwd.hpp"
#include "cppa/message_id.hpp"
......@@ -43,7 +43,7 @@
#include "cppa/mailbox_element.hpp"
#include "cppa/response_promise.hpp"
#include "cppa/message_priority.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/util/duration.hpp"
......@@ -147,12 +147,12 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
/**
* @brief Sends @p what to the receiver specified in @p dest.
*/
void send_tuple(message_priority prio, const channel& whom, any_tuple what);
void send_tuple(message_priority prio, const channel& whom, message what);
/**
* @brief Sends @p what to the receiver specified in @p dest.
*/
inline void send_tuple(const channel& whom, any_tuple what) {
inline void send_tuple(const channel& whom, message what) {
send_tuple(message_priority::normal, whom, std::move(what));
}
......@@ -166,7 +166,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
template<typename... Ts>
inline void send(message_priority prio, const channel& whom, Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
send_tuple(prio, whom, make_any_tuple(std::forward<Ts>(what)...));
send_tuple(prio, whom, make_message(std::forward<Ts>(what)...));
}
/**
......@@ -179,7 +179,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
inline void send(const channel& whom, Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "sizeof...(Ts) == 0");
send_tuple(message_priority::normal, whom,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
/**
......@@ -193,7 +193,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
const typed_actor<Rs...>& whom,
cow_tuple<Ts...> what) {
check_typed_input(whom, what);
send_tuple(prio, whom.m_ptr, any_tuple{std::move(what)});
send_tuple(prio, whom.m_ptr, message{std::move(what)});
}
/**
......@@ -265,7 +265,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
void delayed_send_tuple(message_priority prio,
const channel& whom,
const util::duration& rtime,
any_tuple data);
message data);
/**
* @brief Sends a message to @p whom that is delayed by @p rel_time.
......@@ -276,7 +276,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
*/
inline void delayed_send_tuple(const channel& whom,
const util::duration& rtime,
any_tuple data) {
message data) {
delayed_send_tuple(message_priority::normal, whom,
rtime, std::move(data));
}
......@@ -293,7 +293,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
void delayed_send(message_priority prio, const channel& whom,
const util::duration& rtime, Ts&&... args) {
delayed_send_tuple(prio, whom, rtime,
make_any_tuple(std::forward<Ts>(args)...));
make_message(std::forward<Ts>(args)...));
}
/**
......@@ -307,7 +307,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
void delayed_send(const channel& whom, const util::duration& rtime,
Ts&&... args) {
delayed_send_tuple(message_priority::normal, whom, rtime,
make_any_tuple(std::forward<Ts>(args)...));
make_message(std::forward<Ts>(args)...));
}
/**************************************************************************
......@@ -371,7 +371,7 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
* from the actor's mailbox.
* @warning Only set during callback invocation.
*/
inline any_tuple& last_dequeued();
inline message& last_dequeued();
/**
* @brief Returns the address of the last sender of the
......@@ -502,12 +502,12 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
message_id timed_sync_send_tuple_impl(message_priority mp,
const actor& whom,
const util::duration& rel_time,
any_tuple&& what);
message&& what);
// returns the response ID
message_id sync_send_tuple_impl(message_priority mp,
const actor& whom,
any_tuple&& what);
message&& what);
// returns the response ID
template<typename... Rs, typename... Ts>
......@@ -517,14 +517,14 @@ class local_actor : public extend<abstract_actor>::with<memory_cached> {
check_typed_input(whom, what);
return sync_send_tuple_impl(mp,
actor{whom.m_ptr.get()},
any_tuple{std::move(what)});
message{std::move(what)});
}
// returns 0 if last_dequeued() is an asynchronous or sync request message,
// a response id generated from the request id otherwise
inline message_id get_response_id();
void reply_message(any_tuple&& what);
void reply_message(message&& what);
void forward_message(const actor& new_receiver, message_priority prio);
......@@ -616,7 +616,7 @@ inline void local_actor::trap_exit(bool new_value) {
m_trap_exit = new_value;
}
inline any_tuple& local_actor::last_dequeued() {
inline message& local_actor::last_dequeued() {
return m_current_node->msg;
}
......
......@@ -23,7 +23,7 @@
#include <cstdint>
#include "cppa/extend.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/actor_addr.hpp"
#include "cppa/message_id.hpp"
#include "cppa/ref_counted.hpp"
......@@ -45,7 +45,7 @@ class mailbox_element : public extend<memory_managed>::with<memory_cached> {
mailbox_element* next; // intrusive next pointer
bool marked; // denotes if this node is currently processed
actor_addr sender;
any_tuple msg; // 'content field'
message msg; // 'content field'
message_id mid;
~mailbox_element();
......@@ -64,7 +64,7 @@ class mailbox_element : public extend<memory_managed>::with<memory_cached> {
mailbox_element() = default;
mailbox_element(msg_hdr_cref hdr, any_tuple data);
mailbox_element(msg_hdr_cref hdr, message data);
};
......
......@@ -25,10 +25,11 @@
#include <iterator>
#include <type_traits>
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/message_builder.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
......@@ -45,11 +46,11 @@ class match_helper {
match_helper(match_helper&&) = default;
inline match_helper(any_tuple t) : tup(std::move(t)) { }
inline match_helper(message t) : tup(std::move(t)) { }
template<typename... Ts>
auto operator()(Ts&&... args)
-> decltype(match_expr_collect(std::forward<Ts>(args)...)(any_tuple{})) {
-> decltype(match_expr_collect(std::forward<Ts>(args)...)(message{})) {
static_assert(sizeof...(Ts) > 0, "at least one argument required");
auto tmp = match_expr_collect(std::forward<Ts>(args)...);
return tmp(tup);
......@@ -57,7 +58,7 @@ class match_helper {
private:
any_tuple tup;
message tup;
};
......@@ -301,7 +302,7 @@ namespace cppa {
* @param what Tuple that should be matched against a pattern.
* @returns A helper object providing <tt>operator(...)</tt>.
*/
inline detail::match_helper match(any_tuple what) {
inline detail::match_helper match(message what) {
return what;
}
......@@ -312,7 +313,7 @@ inline detail::match_helper match(any_tuple what) {
*/
template<typename T>
detail::match_helper match(T&& what) {
return any_tuple::view(std::forward<T>(what));
return message_builder{std::forward<T>(what)}.to_message();
}
/**
......
......@@ -16,28 +16,25 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_MATCH_EXPR_HPP
#define CPPA_MATCH_EXPR_HPP
#include "cppa/unit.hpp"
#include <vector>
#include "cppa/none.hpp"
#include "cppa/variant.hpp"
#include "cppa/optional.hpp"
#include "cppa/lift_void.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/util/call.hpp"
#include "cppa/unit.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/purge_refs.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/projection.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/apply_args.hpp"
#include "cppa/detail/lifted_fun.hpp"
#include "cppa/detail/tuple_dummy.hpp"
#include "cppa/detail/pseudo_tuple.hpp"
#include "cppa/detail/behavior_impl.hpp"
......@@ -46,20 +43,25 @@ namespace cppa {
namespace detail {
template<long N>
struct long_constant { static constexpr long value = N; };
struct long_constant {
static constexpr long value = N;
};
typedef long_constant<-1l> minus1l;
template<typename T1, typename T2>
inline T2& deduce_const(T1&, T2& rhs) { return rhs; }
inline T2& deduce_const(T1&, T2& rhs) {
return rhs;
}
template<typename T1, typename T2>
inline const T2& deduce_const(const T1&, T2& rhs) { return rhs; }
inline const T2& deduce_const(const T1&, T2& rhs) {
return rhs;
}
template<class FilteredPattern>
struct invoke_util_base {
typedef FilteredPattern filtered_pattern;
typedef typename pseudo_tuple_from_type_list<filtered_pattern>::type
typedef typename util::tl_apply<FilteredPattern, pseudo_tuple>::type
tuple_type;
};
......@@ -70,54 +72,45 @@ struct invoke_util_impl : invoke_util_base<FilteredPattern> {
typedef invoke_util_base<FilteredPattern> super;
template<class Tuple>
static bool can_invoke(const std::type_info& type_token,
const Tuple& tup) {
typedef typename match_impl_from_type_list<Tuple, Pattern>::type mimpl;
return type_token == typeid(FilteredPattern) || mimpl::_(tup);
static bool can_invoke(const std::type_info& type_token, const Tuple& tup) {
typename select_matcher<Tuple, Pattern>::type mimpl;
return type_token == typeid(FilteredPattern) || mimpl(tup);
}
template<typename PtrType, class Tuple>
static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& type_token,
bool,
PtrType*,
const std::type_info& type_token, bool, PtrType*,
Tuple& tup) {
typedef typename match_impl_from_type_list<
typename std::remove_const<Tuple>::type,
Pattern
>::type
mimpl;
util::limited_vector<size_t, util::tl_size<FilteredPattern>::value> mv;
typename select_matcher<typename std::remove_const<Tuple>::type,
Pattern>::type mimpl;
std::vector<size_t> mv;
if (type_token == typeid(FilteredPattern)) {
for (size_t i = 0; i < util::tl_size<FilteredPattern>::value; ++i) {
for (size_t i = 0; i < util::tl_size<FilteredPattern>::value;
++i) {
result[i] = const_cast<void*>(tup.at(i));
}
return true;
}
else if (mimpl::_(tup, mv)) {
for (size_t i = 0; i < util::tl_size<FilteredPattern>::value; ++i) {
} else if (mimpl(tup, mv)) {
for (size_t i = 0; i < util::tl_size<FilteredPattern>::value;
++i) {
result[i] = const_cast<void*>(tup.at(mv[i]));
}
return true;
}
return false;
}
};
template<>
struct invoke_util_impl<wildcard_position::nil,
util::empty_type_list,
util::empty_type_list >
: invoke_util_base<util::empty_type_list> {
struct invoke_util_impl<
wildcard_position::nil, util::empty_type_list,
util::empty_type_list> : invoke_util_base<util::empty_type_list> {
typedef invoke_util_base<util::empty_type_list> super;
template<typename PtrType, class Tuple>
static bool prepare_invoke(typename super::tuple_type&,
const std::type_info& type_token,
bool,
PtrType*,
const std::type_info& type_token, bool, PtrType*,
Tuple& tup) {
return can_invoke(type_token, tup);
}
......@@ -126,20 +119,18 @@ struct invoke_util_impl<wildcard_position::nil,
static bool can_invoke(const std::type_info& arg_types, const Tuple&) {
return arg_types == typeid(util::empty_type_list);
}
};
template<class Pattern, typename... Ts>
struct invoke_util_impl<wildcard_position::nil,
Pattern,
util::type_list<Ts...>>
: invoke_util_base<util::type_list<Ts...>> {
struct invoke_util_impl<
wildcard_position::nil, Pattern,
util::type_list<Ts...>> : invoke_util_base<util::type_list<Ts...>> {
typedef invoke_util_base<util::type_list<Ts...>> super;
typedef typename super::tuple_type tuple_type;
typedef detail::tdata<Ts...> native_data_type;
typedef std::tuple<Ts...> native_data_type;
typedef typename detail::static_types_array<Ts...> arr_type;
......@@ -157,58 +148,40 @@ struct invoke_util_impl<wildcard_position::nil,
}
template<typename PtrType, class Tuple>
static bool prepare_invoke(tuple_type& result,
const std::type_info&,
bool,
PtrType*,
Tuple& tup,
static bool prepare_invoke(
tuple_type& result, const std::type_info&, bool, PtrType*, Tuple& tup,
typename std::enable_if<
std::is_same<
typename std::remove_const<Tuple>::type,
detail::abstract_tuple
>::value == false
>::type* = 0) {
std::integral_constant<bool,
util::tl_binary_forall<
typename util::tl_map<
typename Tuple::types,
util::purge_refs
>::type,
util::type_list<Ts...>,
std::is_same
>::value > token;
std::is_same<typename std::remove_const<Tuple>::type,
detail::message_data>::value == false>::type* = 0) {
std::integral_constant<
bool, util::tl_binary_forall<
typename util::tl_map<typename Tuple::types,
util::purge_refs>::type,
util::type_list<Ts...>, std::is_same>::value> token;
return prepare_invoke(token, result, tup);
}
template<typename PtrType, class Tuple>
static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& arg_types,
bool dynamically_typed,
PtrType* native_arg,
Tuple& tup,
static bool prepare_invoke(
typename super::tuple_type& result, const std::type_info& arg_types,
bool dynamically_typed, PtrType* native_arg, Tuple& tup,
typename std::enable_if<
std::is_same<
typename std::remove_const<Tuple>::type,
detail::abstract_tuple
>::value == true
>::type* = 0) {
std::is_same<typename std::remove_const<Tuple>::type,
detail::message_data>::value == true>::type* = 0) {
if (arg_types == typeid(util::type_list<Ts...>)) {
if (native_arg) {
typedef typename std::conditional<
std::is_const<PtrType>::value,
const native_data_type*,
native_data_type*
>::type
cast_type;
std::is_const<PtrType>::value, const native_data_type*,
native_data_type*>::type cast_type;
auto arg = reinterpret_cast<cast_type>(native_arg);
for (size_t i = 0; i < sizeof...(Ts); ++i) {
result[i] = const_cast<void*>(arg->at(i));
result[i] = const_cast<void*>(
tup_ptr_access<0, sizeof...(Ts)>::get(i, *arg));
}
return true;
}
// 'fall through'
}
else if (dynamically_typed) {
} else if (dynamically_typed) {
auto& arr = arr_type::arr;
if (tup.size() != sizeof...(Ts)) {
return false;
......@@ -219,8 +192,8 @@ struct invoke_util_impl<wildcard_position::nil,
}
}
// 'fall through'
}
else return false;
} else
return false;
for (size_t i = 0; i < sizeof...(Ts); ++i) {
result[i] = const_cast<void*>(tup.at(i));
}
......@@ -231,14 +204,12 @@ struct invoke_util_impl<wildcard_position::nil,
static bool can_invoke(const std::type_info& arg_types, const Tuple&) {
return arg_types == typeid(util::type_list<Ts...>);
}
};
template<>
struct invoke_util_impl<wildcard_position::leading,
util::type_list<anything>,
util::empty_type_list>
: invoke_util_base<util::empty_type_list> {
struct invoke_util_impl<
wildcard_position::leading, util::type_list<anything>,
util::empty_type_list> : invoke_util_base<util::empty_type_list> {
typedef invoke_util_base<util::empty_type_list> super;
......@@ -249,26 +220,21 @@ struct invoke_util_impl<wildcard_position::leading,
template<typename PtrType, typename Tuple>
static inline bool prepare_invoke(typename super::tuple_type&,
const std::type_info&,
bool,
PtrType*,
const std::type_info&, bool, PtrType*,
Tuple&) {
return true;
}
};
template<class Pattern, typename... Ts>
struct invoke_util_impl<wildcard_position::trailing,
Pattern,
util::type_list<Ts...>>
: invoke_util_base<util::type_list<Ts...>> {
struct invoke_util_impl<
wildcard_position::trailing, Pattern,
util::type_list<Ts...>> : invoke_util_base<util::type_list<Ts...>> {
typedef invoke_util_base<util::type_list<Ts...>> super;
template<class Tuple>
static bool can_invoke(const std::type_info& arg_types,
const Tuple& tup) {
static bool can_invoke(const std::type_info& arg_types, const Tuple& tup) {
if (arg_types == typeid(util::type_list<Ts...>)) {
return true;
}
......@@ -287,9 +253,7 @@ struct invoke_util_impl<wildcard_position::trailing,
template<typename PtrType, class Tuple>
static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& arg_types,
bool,
PtrType*,
const std::type_info& arg_types, bool, PtrType*,
Tuple& tup) {
if (!can_invoke(arg_types, tup)) return false;
for (size_t i = 0; i < sizeof...(Ts); ++i) {
......@@ -297,20 +261,17 @@ struct invoke_util_impl<wildcard_position::trailing,
}
return true;
}
};
template<class Pattern, typename... Ts>
struct invoke_util_impl<wildcard_position::leading,
Pattern,
util::type_list<Ts...>>
: invoke_util_base<util::type_list<Ts...>> {
struct invoke_util_impl<
wildcard_position::leading, Pattern,
util::type_list<Ts...>> : invoke_util_base<util::type_list<Ts...>> {
typedef invoke_util_base<util::type_list<Ts...>> super;
template<class Tuple>
static bool can_invoke(const std::type_info& arg_types,
const Tuple& tup) {
static bool can_invoke(const std::type_info& arg_types, const Tuple& tup) {
if (arg_types == typeid(util::type_list<Ts...>)) {
return true;
}
......@@ -329,9 +290,7 @@ struct invoke_util_impl<wildcard_position::leading,
template<typename PtrType, class Tuple>
static bool prepare_invoke(typename super::tuple_type& result,
const std::type_info& arg_types,
bool,
PtrType*,
const std::type_info& arg_types, bool, PtrType*,
Tuple& tup) {
if (!can_invoke(arg_types, tup)) return false;
size_t i = tup.size() - sizeof...(Ts);
......@@ -341,129 +300,85 @@ struct invoke_util_impl<wildcard_position::leading,
}
return true;
}
};
template<class Pattern>
struct invoke_util
: invoke_util_impl<
get_wildcard_position<Pattern>(),
Pattern,
typename util::tl_filter_not_type<Pattern, anything>::type> {
};
get_wildcard_position<Pattern>(), Pattern,
typename util::tl_filter_not_type<Pattern, anything>::type> {};
template<class Expr, class Projections, class Signature, class Pattern>
class match_expr_case
: public get_lifted_fun<Expr, Projections, Signature>::type {
template<class Pattern, class Projection, class PartialFun>
struct projection_partial_function_pair : std::pair<Projection, PartialFun> {
typedef typename get_lifted_fun<Expr, Projections, Signature>::type super;
public:
template<typename... Ts>
projection_partial_function_pair(Ts&&... args)
: std::pair<Projection, PartialFun>(std::forward<Ts>(args)...) { }
match_expr_case(Ts&&... args)
: super(std::forward<Ts>(args)...) {}
typedef Pattern pattern_type;
};
template<class Expr, class Guard, class Transformers, class Pattern>
template<class Expr, class Transformers, class Pattern>
struct get_case_ {
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename util::tl_filter_not_type<
Pattern,
anything
>::type
typedef typename util::tl_filter_not_type<Pattern, anything>::type
filtered_pattern;
typedef typename util::tl_pad_right<
Transformers,
util::tl_size<filtered_pattern>::value
>::type
Transformers, util::tl_size<filtered_pattern>::value>::type
padded_transformers;
typedef typename util::tl_map<
filtered_pattern,
std::add_const,
std::add_lvalue_reference
>::type
typedef typename util::tl_map<filtered_pattern, std::add_const,
std::add_lvalue_reference>::type
base_signature;
typedef typename util::tl_map_conditional<
typename util::tl_pad_left<
typename ctrait::arg_types,
util::tl_size<filtered_pattern>::value
>::type,
std::is_lvalue_reference,
false,
std::add_const,
std::add_lvalue_reference
>::type
padded_expr_args;
util::tl_size<filtered_pattern>::value>::type,
std::is_lvalue_reference, false, std::add_const,
std::add_lvalue_reference>::type padded_expr_args;
// override base signature with required argument types of Expr
// and result types of transformation
typedef typename util::tl_zip<
typename util::tl_map<
padded_transformers,
util::map_to_result_type,
typename util::tl_map<padded_transformers, util::map_to_result_type,
util::rm_optional,
std::add_lvalue_reference
>::type,
typename util::tl_zip<
padded_expr_args,
base_signature,
util::left_or_right
>::type,
util::left_or_right
>::type
partial_fun_signature;
std::add_lvalue_reference>::type,
typename util::tl_zip<padded_expr_args, base_signature,
util::left_or_right>::type,
util::left_or_right>::type partial_fun_signature;
// 'inherit' mutable references from partial_fun_signature
// for arguments without transformation
typedef typename util::tl_zip<
typename util::tl_zip<
padded_transformers,
partial_fun_signature,
util::if_not_left
>::type,
base_signature,
util::deduce_ref_type
>::type
projection_signature;
typedef typename projection_from_type_list<
padded_transformers,
projection_signature
>::type
type1;
typedef typename get_tpartial_function<
Expr,
Guard,
partial_fun_signature
>::type
type2;
typedef projection_partial_function_pair<Pattern, type1, type2> type;
typename util::tl_zip<padded_transformers, partial_fun_signature,
util::if_not_left>::type,
base_signature, util::deduce_ref_type>::type projection_signature;
typedef match_expr_case<Expr, padded_transformers, projection_signature,
Pattern> type;
};
template<bool Complete, class Expr, class Guard, class Trans, class Pattern>
template<bool Complete, class Expr, class Trans, class Pattern>
struct get_case {
typedef typename get_case_<Expr, Guard, Trans, Pattern>::type type;
typedef typename get_case_<Expr, Trans, Pattern>::type type;
};
template<class Expr, class Guard, class Trans, class Pattern>
struct get_case<false, Expr, Guard, Trans, Pattern> {
template<class Expr, class Trans, class Pattern>
struct get_case<false, Expr, Trans, Pattern> {
typedef typename util::tl_pop_back<Pattern>::type lhs_pattern;
typedef typename util::tl_map<
typename util::get_callable_trait<Expr>::arg_types,
util::rm_const_and_ref
>::type
rhs_pattern;
util::rm_const_and_ref>::type rhs_pattern;
typedef typename get_case_<
Expr,
Guard,
Trans,
typename util::tl_concat<lhs_pattern, rhs_pattern>::type
>::type
type;
Expr, Trans,
typename util::tl_concat<lhs_pattern, rhs_pattern>::type>::type type;
};
template<typename Fun>
......@@ -483,9 +398,9 @@ inline bool unroll_expr_result_valid(const optional<T>& opt) {
return static_cast<bool>(opt);
}
template<typename T>
inline T& unroll_expr_result_unbox(T& value) {
return value;
inline variant<none_t, unit_t> unroll_expr_result_unbox(bool& value) {
if (value) return unit;
return none;
}
template<typename T>
......@@ -494,21 +409,17 @@ inline T& unroll_expr_result_unbox(optional<T>& opt) {
}
template<typename Result, class PPFPs, typename PtrType, class Tuple>
Result unroll_expr(PPFPs&, std::uint64_t, minus1l, const std::type_info&,
bool, PtrType*, Tuple&) {
Result unroll_expr(PPFPs&, uint64_t, minus1l, const std::type_info&, bool,
PtrType*, Tuple&) {
return none;
}
template<typename Result, class PPFPs, long N, typename PtrType, class Tuple>
Result unroll_expr(PPFPs& fs,
std::uint64_t bitmask,
long_constant<N>,
const std::type_info& type_token,
bool is_dynamic,
PtrType* ptr,
Tuple& tup) {
Result unroll_expr(PPFPs& fs, uint64_t bitmask, long_constant<N>,
const std::type_info& type_token, bool is_dynamic,
PtrType* ptr, Tuple& tup) {
/* recursively evaluate sub expressions */ {
Result res = unroll_expr<Result>(fs, bitmask, long_constant<N-1>{},
Result res = unroll_expr<Result>(fs, bitmask, long_constant<N - 1>{},
type_token, is_dynamic, ptr, tup);
if (!get<none_t>(&res)) return res;
}
......@@ -520,10 +431,7 @@ Result unroll_expr(PPFPs& fs,
typename policy::tuple_type targs;
if (policy::prepare_invoke(targs, type_token, is_dynamic, ptr, tup)) {
auto is = util::get_indices(targs);
auto res = util::apply_args_prefixed(f.first,
deduce_const(tup, targs),
is,
f.second);
auto res = detail::apply_args(f, is, deduce_const(tup, targs));
if (unroll_expr_result_valid(res)) {
return std::move(unroll_expr_result_unbox(res));
}
......@@ -531,46 +439,21 @@ Result unroll_expr(PPFPs& fs,
return none;
}
// PPFP = projection_partial_function_pair
template<class PPFPs, class T>
inline bool can_unroll_expr(PPFPs&, minus1l, const std::type_info&, const T&) {
return false;
}
template<class PPFPs, long N, class Tuple>
inline bool can_unroll_expr(PPFPs& fs,
long_constant<N>,
const std::type_info& arg_types,
const Tuple& tup) {
if (can_unroll_expr(fs, long_constant<N-1l>(), arg_types, tup)) {
return true;
}
auto& f = get<N>(fs);
typedef typename util::rm_const_and_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_util<pattern_type> policy;
return policy::can_invoke(arg_types, tup);
}
template<class PPFPs, class Tuple>
inline std::uint64_t calc_bitmask(PPFPs&,
minus1l,
const std::type_info&,
inline uint64_t calc_bitmask(PPFPs&, minus1l, const std::type_info&,
const Tuple&) {
return 0x00;
}
template<class PPFPs, long N, class Tuple>
inline std::uint64_t calc_bitmask(PPFPs& fs,
long_constant<N>,
const std::type_info& tinf,
const Tuple& tup) {
template<class Case, long N, class Tuple>
inline uint64_t calc_bitmask(Case& fs, long_constant<N>,
const std::type_info& tinf, const Tuple& tup) {
auto& f = get<N>(fs);
typedef typename util::rm_const_and_ref<decltype(f)>::type Fun;
typedef typename Fun::pattern_type pattern_type;
typedef detail::invoke_util<pattern_type> policy;
std::uint64_t result = policy::can_invoke(tinf, tup) ? (0x01 << N) : 0x00;
return result | calc_bitmask(fs, long_constant<N-1l>(), tinf, tup);
uint64_t result = policy::can_invoke(tinf, tup) ? (0x01 << N) : 0x00;
return result | calc_bitmask(fs, long_constant<N - 1l>(), tinf, tup);
}
template<bool IsManipulator, typename T0, typename T1>
......@@ -591,28 +474,24 @@ struct mexpr_fwd_<true, T&, T> {
template<bool IsManipulator, typename T>
struct mexpr_fwd {
typedef typename mexpr_fwd_<
IsManipulator,
T,
IsManipulator, T,
typename detail::implicit_conversions<
typename util::rm_const_and_ref<T>::type
>::type
>::type
type;
typename util::rm_const_and_ref<T>::type>::type>::type type;
};
// detach_if_needed(any_tuple tup, bool do_detach)
inline any_tuple& detach_if_needed(any_tuple& tup, std::true_type) {
// detach_if_needed(message tup, bool do_detach)
inline message& detach_if_needed(message& tup, std::true_type) {
tup.force_detach();
return tup;
}
inline any_tuple detach_if_needed(const any_tuple& tup, std::true_type) {
any_tuple cpy{tup};
inline message detach_if_needed(const message& tup, std::true_type) {
message cpy{tup};
cpy.force_detach();
return cpy;
}
inline const any_tuple& detach_if_needed(const any_tuple& tup, std::false_type) {
inline const message& detach_if_needed(const message& tup, std::false_type) {
return tup;
}
......@@ -628,12 +507,16 @@ inline const void* fetch_native_data(const Ptr& ptr, std::false_type) {
template<typename T>
struct is_manipulator_case {
static constexpr bool value = T::second_type::manipulates_args;
// static constexpr bool value = T::second_type::manipulates_args;
typedef typename T::arg_types arg_types;
static constexpr bool value = util::tl_exists<arg_types,
util::is_mutable_ref>::value;
};
template<typename T>
struct get_case_result {
typedef typename T::second_type::result_type type;
// typedef typename T::second_type::result_type type;
typedef typename T::result_type type;
};
} // namespace detail
......@@ -651,7 +534,7 @@ struct match_result_from_type_list<util::type_list<Ts...>> {
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>, whereas
* each case is a @p detail::projection_partial_function_pair.
* each case is a @p util::match_expr_case<...>.
*/
template<class... Cs>
class match_expr {
......@@ -659,25 +542,17 @@ class match_expr {
static_assert(sizeof...(Cs) < 64, "too many functions");
public:
typedef util::type_list<Cs...> cases_list;
typedef typename match_result_from_type_list<
typename util::tl_distinct<
typename util::tl_map<
cases_list,
detail::get_case_result
>::type
>::type
>::type
typename util::tl_distinct<typename util::tl_map<
cases_list, detail::get_case_result>::type>::type>::type
result_type;
static constexpr bool has_manipulator = util::tl_exists<
cases_list,
detail::is_manipulator_case
>::value;
static constexpr bool has_manipulator =
util::tl_exists<cases_list, detail::is_manipulator_case>::value;
typedef detail::long_constant<sizeof...(Cs)-1l> idx_token_type;
typedef detail::long_constant<sizeof...(Cs) - 1l> idx_token_type;
static constexpr idx_token_type idx_token = idx_token_type{};
......@@ -691,101 +566,29 @@ class match_expr {
init();
}
match_expr(const match_expr& other) : m_cases(other.m_cases) {
init();
}
bool can_invoke(const any_tuple& tup) {
auto type_token = tup.type_token();
if (not tup.dynamically_typed()) {
auto bitmask = get_cache_entry(type_token, tup);
return bitmask != 0;
}
return can_unroll_expr(m_cases,
idx_token,
*type_token,
tup);
}
match_expr(const match_expr& other) : m_cases(other.m_cases) { init(); }
inline result_type operator()(const any_tuple& tup) {
return apply(tup);
}
inline result_type operator()(const message& tup) { return apply(tup); }
inline result_type operator()(any_tuple& tup) {
return apply(tup);
}
inline result_type operator()(message& tup) { return apply(tup); }
inline result_type operator()(any_tuple&& tup) {
any_tuple tmp{tup};
inline result_type operator()(message&& tup) {
message tmp{tup};
return apply(tmp);
}
template<typename T, typename... Ts>
typename std::enable_if<
not std::is_same<
typename util::rm_const_and_ref<T>::type,
any_tuple
>::value
&& not is_cow_tuple<T>::value,
result_type
>::type
operator()(T&& arg0, Ts&&... args) {
// wraps and applies implicit conversions to args
typedef detail::tdata<
typename detail::mexpr_fwd<
has_manipulator,
T
>::type,
typename detail::mexpr_fwd<
has_manipulator,
Ts
>::type...
>
tuple_type;
tuple_type tup{std::forward<T>(arg0), std::forward<Ts>(args)...};
auto& type_token = typeid(typename tuple_type::types);
auto bitmask = get_cache_entry(&type_token, tup);
// ref_type keeps track of whether this match_expr is a mutator
typedef typename std::conditional<
has_manipulator,
tuple_type&,
const tuple_type&
>::type
ref_type;
// same here
typedef typename std::conditional<
has_manipulator,
void*,
const void*
>::type
ptr_type;
// iterate over cases and return if any case was invoked
return detail::unroll_expr<result_type>(m_cases,
bitmask,
idx_token,
type_token,
false, // not dynamically_typed
static_cast<ptr_type>(nullptr),
static_cast<ref_type>(tup));
}
template<class... Ds>
match_expr<Cs..., Ds...> or_else(const match_expr<Ds...>& other) const {
detail::tdata<util::rebindable_reference<const Cs>...,
util::rebindable_reference<const Ds>... > all_cases;
rebind_tdata(all_cases, m_cases, other.cases());
return {all_cases};
return {tuple_cat(m_cases, other.cases())};
}
/** @cond PRIVATE */
inline const detail::tdata<Cs...>& cases() const {
return m_cases;
}
inline const std::tuple<Cs...>& cases() const { return m_cases; }
intrusive_ptr<detail::behavior_impl> as_behavior_impl() const {
//return new pfun_impl(*this);
auto lvoid = [] { };
// return new pfun_impl(*this);
auto lvoid = [] {};
using impl = detail::default_behavior_impl<match_expr, decltype(lvoid)>;
return new impl(*this, util::duration{}, lvoid);
}
......@@ -794,16 +597,16 @@ class match_expr {
private:
// structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>,
// structure: std::tuple< std::tuple<type_list<...>, ...>,
// std::tuple<type_list<...>, ...>,
// ...>
detail::tdata<Cs...> m_cases;
std::tuple<Cs...> m_cases;
static constexpr size_t cache_size = 10;
typedef std::pair<const std::type_info*, std::uint64_t> cache_element;
typedef std::pair<const std::type_info*, uint64_t> cache_element;
util::limited_vector<cache_element, cache_size> m_cache;
std::vector<cache_element> m_cache;
// ring buffer like access to m_cache
size_t m_cache_begin;
......@@ -811,19 +614,17 @@ class match_expr {
cache_element m_dummy;
static inline void advance_(size_t& i) {
i = (i + 1) % cache_size;
}
static inline void advance_(size_t& i) { i = (i + 1) % cache_size; }
inline size_t find_token_pos(const std::type_info* type_token) {
for (size_t i = m_cache_begin ; i != m_cache_end; advance_(i)) {
for (size_t i = m_cache_begin; i != m_cache_end; advance_(i)) {
if (m_cache[i].first == type_token) return i;
}
return m_cache_end;
}
template<class Tuple>
std::uint64_t get_cache_entry(const std::type_info* type_token,
uint64_t get_cache_entry(const std::type_info* type_token,
const Tuple& value) {
CPPA_REQUIRE(type_token != nullptr);
if (value.dynamically_typed()) {
......@@ -836,18 +637,18 @@ class match_expr {
advance_(m_cache_end);
if (m_cache_end == m_cache_begin) advance_(m_cache_begin);
m_cache[i].first = type_token;
m_cache[i].second = calc_bitmask(m_cases,
idx_token,
*type_token,
value);
m_cache[i].second =
calc_bitmask(m_cases, idx_token, *type_token, value);
}
return m_cache[i].second;
}
void init() {
m_dummy.second = std::numeric_limits<std::uint64_t>::max();
m_dummy.second = std::numeric_limits<uint64_t>::max();
m_cache.resize(cache_size);
for (auto& entry : m_cache) { entry.first = nullptr; }
for (auto& entry : m_cache) {
entry.first = nullptr;
}
m_cache_begin = m_cache_end = 0;
}
......@@ -857,13 +658,9 @@ class match_expr {
detail::tuple_dummy td;
auto td_token_ptr = td.type_token();
auto td_bitmask = get_cache_entry(td_token_ptr, td);
return detail::unroll_expr<result_type>(m_cases,
td_bitmask,
idx_token,
*td_token_ptr,
false,
static_cast<void*>(nullptr),
td);
return detail::unroll_expr<result_type>(
m_cases, td_bitmask, idx_token, *td_token_ptr, false,
static_cast<void*>(nullptr), td);
}
std::integral_constant<bool, has_manipulator> mutator_token;
// returns either a reference or a new object
......@@ -874,13 +671,9 @@ class match_expr {
auto token_ptr = vals->type_token();
auto bitmask = get_cache_entry(token_ptr, *vals);
auto dynamically_typed = vals->dynamically_typed();
return detail::unroll_expr<result_type>(m_cases,
bitmask,
idx_token,
*token_ptr,
dynamically_typed,
ndp,
*vals);
return detail::unroll_expr<result_type>(m_cases, bitmask, idx_token,
*token_ptr, dynamically_typed,
ndp, *vals);
}
};
......@@ -895,16 +688,8 @@ struct is_match_expr<match_expr<Cs...>> {
static constexpr bool value = true;
};
template<class List>
struct match_expr_from_type_list;
template<typename... Ts>
struct match_expr_from_type_list<util::type_list<Ts...> > {
typedef match_expr<Ts...> type;
};
template<typename... Lhs, typename... Rhs>
inline match_expr<Lhs..., Rhs...> operator,(const match_expr<Lhs...>& lhs,
inline match_expr<Lhs..., Rhs...> operator, (const match_expr<Lhs...>& lhs,
const match_expr<Rhs...>& rhs) {
return lhs.or_else(rhs);
}
......@@ -925,158 +710,88 @@ const match_expr<Cs...>& match_expr_collect(const match_expr<Cs...>& arg) {
}
template<typename T, typename... Ts>
typename match_expr_from_type_list<
typename util::tl_concat<
typename T::cases_list,
typename Ts::cases_list...
>::type
>::type
typename util::tl_apply<
typename util::tl_concat<typename T::cases_list,
typename Ts::cases_list...>::type,
match_expr>::type
match_expr_collect(const T& arg, const Ts&... args) {
typename detail::tdata_from_type_list<
typename util::tl_map<
typename util::tl_concat<
typename T::cases_list,
typename Ts::cases_list...
>::type,
gref_wrapped
>::type
>::type
all_cases;
detail::rebind_tdata(all_cases, arg.cases(), args.cases()...);
return {all_cases};
return {std::tuple_cat(arg.cases(), args.cases()...)};
}
namespace detail {
//typedef std::true_type with_timeout;
//typedef std::false_type without_timeout;
// implemented in message_handler.cpp
message_handler combine(behavior_impl_ptr, behavior_impl_ptr);
behavior_impl_ptr extract(const message_handler&);
// end of recursion
template<class Data, class Token>
behavior_impl_ptr concat_rec(const Data& data, Token) {
typedef typename match_expr_from_type_list<Token>::type combined_type;
auto lvoid = [] { };
typedef default_behavior_impl<combined_type, decltype(lvoid)> impl_type;
return new impl_type(data, util::duration{}, lvoid);
template<typename... Cs>
behavior_impl_ptr extract(const match_expr<Cs...>& arg) {
return arg.as_behavior_impl();
}
// end of recursion with nothing but a partial function
inline behavior_impl_ptr concat_rec(const tdata<>&,
util::empty_type_list,
const partial_function& pfun) {
return extract(pfun);
template<typename... As, typename... Bs>
match_expr<As..., Bs...> combine(const match_expr<As...>& lhs,
const match_expr<Bs...>& rhs) {
return lhs.or_else(rhs);
}
// end of recursion with timeout
template<class Data, class Token, typename F>
behavior_impl_ptr concat_rec(const Data& data,
Token,
const timeout_definition<F>& arg) {
typedef typename match_expr_from_type_list<Token>::type combined_type;
return new default_behavior_impl<combined_type, F>{data, arg};
// forwards match_expr as match_expr as long as combining two match_expr,
// otherwise turns everything into behavior_impl_ptr
template<typename... As, typename... Bs>
const match_expr<As...>& combine_fwd(const match_expr<As...>& lhs,
const match_expr<Bs...>&) {
return lhs;
}
// recursive concatenation function
template<class Data, class Token, typename T, typename... Ts>
behavior_impl_ptr concat_rec(const Data& data,
Token,
const T& arg,
const Ts&... args) {
typedef typename util::tl_concat<
Token,
typename T::cases_list
>::type
next_token_type;
typename tdata_from_type_list<
typename util::tl_map<
next_token_type,
gref_wrapped
>::type
>::type
next_data;
next_token_type next_token;
rebind_tdata(next_data, data, arg.cases());
return concat_rec(next_data, next_token, args...);
template<typename T, typename U>
behavior_impl_ptr combine_fwd(T& lhs, U&) {
return extract(lhs);
}
// handle partial functions at end of recursion
template<class Data, class Token>
behavior_impl_ptr concat_rec(const Data& data,
Token token,
const partial_function& pfun) {
return combine(concat_rec(data, token), pfun);
template<typename T>
behavior_impl_ptr match_expr_concat(const T& arg) {
return arg.as_behavior_impl();
}
// handle partial functions in between
template<class Data, class Token, typename T, typename... Ts>
behavior_impl_ptr concat_rec(const Data& data,
Token token,
const partial_function& pfun,
const T& arg,
const Ts&... args) {
auto lhs = concat_rec(data, token);
detail::tdata<> dummy;
auto rhs = concat_rec(dummy, util::empty_type_list{}, arg, args...);
return combine(lhs, pfun)->or_else(rhs);
template<typename F>
behavior_impl_ptr match_expr_concat(const message_handler& arg0,
const timeout_definition<F>& arg) {
return extract(arg0)->copy(arg);
}
// handle partial functions at recursion start
template<typename T, typename... Ts>
behavior_impl_ptr concat_rec(const tdata<>& data,
util::empty_type_list token,
const partial_function& pfun,
const T& arg,
const Ts&... args) {
return combine(pfun, concat_rec(data, token, arg, args...));
template<typename... Cs, typename F>
behavior_impl_ptr match_expr_concat(const match_expr<Cs...>& arg0,
const timeout_definition<F>& arg) {
return new default_behavior_impl<match_expr<Cs...>, F>{arg0, arg};
}
template<typename T0, typename T1, typename... Ts>
behavior_impl_ptr match_expr_concat(const T0& arg0,
const T1& arg1,
behavior_impl_ptr match_expr_concat(const T0& arg0, const T1& arg1,
const Ts&... args) {
detail::tdata<> dummy;
return concat_rec(dummy, util::empty_type_list{}, arg0, arg1, args...);
}
template<typename T>
behavior_impl_ptr match_expr_concat(const T& arg) {
return arg.as_behavior_impl();
return match_expr_concat(
combine(combine_fwd(arg0, arg1), combine_fwd(arg1, arg0)), args...);
}
// some more convenience functions
template<typename F,
class E = typename std::enable_if<util::is_callable<F>::value>::type>
match_expr<
typename get_case<
false,
F,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type>
template<typename F, class E = typename std::enable_if<
util::is_callable<F>::value>::type>
match_expr<typename get_case<false, F, util::empty_type_list,
util::empty_type_list>::type>
lift_to_match_expr(F fun) {
typedef typename get_case<
false,
F,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type
result_type;
return result_type{typename result_type::first_type{},
typename result_type::second_type{
std::move(fun),
empty_value_guard{}}};
typedef typename get_case<false, F, util::empty_type_list,
util::empty_type_list>::type result_type;
return result_type{std::move(fun)};
}
template<typename T,
class E = typename std::enable_if<!util::is_callable<T>::value>::type>
template<typename T, class E = typename std::enable_if<
!util::is_callable<T>::value>::type>
inline T lift_to_match_expr(T arg) {
return arg;
}
} // namespace detail
} // namespace cppa
#endif // CPPA_MATCH_EXPR_HPP
......@@ -16,92 +16,73 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_ANY_TUPLE_HPP
#define CPPA_ANY_TUPLE_HPP
#include <type_traits>
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/util/int_list.hpp"
#include "cppa/util/comparable.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/tuple_view.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/container_tuple_view.hpp"
#include "cppa/detail/apply_args.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/message_data.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
class message_handler;
/**
* @brief Describes a fixed-length copy-on-write tuple
* with elements of any type.
*/
class any_tuple {
class message {
public:
/**
* @brief A raw pointer to the data.
*/
typedef detail::abstract_tuple* raw_ptr;
using raw_ptr = detail::message_data*;
/**
* @brief A smart pointer to the data.
* @brief A (COW) smart pointer to the data.
*/
typedef cow_ptr<detail::abstract_tuple> data_ptr;
using data_ptr = detail::message_data::ptr;
/**
* @brief An iterator to access each element as <tt>const void*</tt>.
*/
typedef detail::abstract_tuple::const_iterator const_iterator;
using const_iterator = detail::message_data::const_iterator;
/**
* @brief Creates an empty tuple.
*/
any_tuple() = default;
/**
* @brief Creates a tuple from @p t.
*/
template<typename... Ts>
any_tuple(const cow_tuple<Ts...>& arg) : m_vals(arg.vals()) { }
/**
* @brief Creates a tuple and moves the content from @p t.
*/
template<typename... Ts>
any_tuple(cow_tuple<Ts...>&& arg) : m_vals(std::move(arg.m_vals)) { }
/**
* @brief Creates a tuple from a set of values.
*/
template<typename T, typename... Ts>
explicit any_tuple(T v0, Ts&&... vs)
: m_vals(make_cow_tuple(std::move(v0), std::forward<Ts>(vs)...).vals()) { }
message() = default;
/**
* @brief Move constructor.
*/
any_tuple(any_tuple&&);
message(message&&);
/**
* @brief Copy constructor.
*/
any_tuple(const any_tuple&) = default;
message(const message&) = default;
/**
* @brief Move assignment.
*/
any_tuple& operator=(any_tuple&&);
message& operator=(message&&);
/**
* @brief Copy assignment.
*/
any_tuple& operator=(const any_tuple&) = default;
message& operator=(const message&) = default;
/**
* @brief Gets the size of this tuple.
......@@ -111,22 +92,22 @@ class any_tuple {
/**
* @brief Creates a new tuple with all but the first n values.
*/
any_tuple drop(size_t n) const;
message drop(size_t n) const;
/**
* @brief Creates a new tuple with all but the last n values.
*/
any_tuple drop_right(size_t n) const;
message drop_right(size_t n) const;
/**
* @brief Creates a new tuple from the first n values.
*/
inline any_tuple take(size_t n) const;
inline message take(size_t n) const;
/**
* @brief Creates a new tuple from the last n values.
*/
inline any_tuple take_right(size_t n) const;
inline message take_right(size_t n) const;
/**
* @brief Gets a mutable pointer to the element at position @p p.
......@@ -144,10 +125,16 @@ class any_tuple {
*/
const uniform_type_info* type_at(size_t p) const;
/**
* @brief Returns true if this message has the types @p Ts.
*/
template<typename... Ts>
bool has_types() const;
/**
* @brief Returns @c true if <tt>*this == other</tt>, otherwise false.
*/
bool equals(const any_tuple& other) const;
bool equals(const message& other) const;
/**
* @brief Returns true if <tt>size() == 0</tt>, otherwise false.
......@@ -192,7 +179,7 @@ class any_tuple {
inline const data_ptr& cvals() const;
/**
* @brief Returns either <tt>&typeid(util::type_list<Ts...>)</tt>, where
* @brief Returns either <tt>&typeid(detail::type_list<Ts...>)</tt>, where
* <tt>Ts...</tt> are the element types, or <tt>&typeid(void)</tt>.
*
* The type token @p &typeid(void) indicates that this tuple is dynamically
......@@ -208,221 +195,143 @@ class any_tuple {
/** @cond PRIVATE */
template<typename T>
static inline any_tuple view(T&& value);
inline void force_detach();
void reset();
explicit any_tuple(raw_ptr);
explicit message(raw_ptr);
inline const std::string* tuple_type_names() const;
/** @endcond */
private:
data_ptr m_vals;
explicit message(const data_ptr& vals);
explicit any_tuple(const data_ptr& vals);
template<typename T, typename CanOptimize>
static any_tuple view(T&& value, std::true_type, CanOptimize token);
template<typename T, typename CanOptimize>
static any_tuple view(T&& value, std::false_type, CanOptimize token);
template<typename T, typename U>
static any_tuple view(std::pair<T, U> p, std::false_type);
template<typename... Ts>
static inline message move_from_tuple(std::tuple<Ts...>&&);
template<typename T>
static auto simple_view(T& value, std::true_type) -> raw_ptr;
/**
* @brief Applies @p handler to this message and returns the result
* of <tt>handler(*this)</tt>.
*/
optional<message> apply(message_handler handler);
template<typename T, typename U>
static auto simple_view(std::pair<T, U>& p, std::true_type) -> raw_ptr;
bool apply_iterative(message_handler handler);
template<typename T>
static auto simple_view(T&& value, std::false_type) -> raw_ptr;
/** @endcond */
template<typename T>
static auto container_view(T& value, std::true_type) -> raw_ptr;
private:
template<typename T>
static auto container_view(T&& value, std::false_type) -> raw_ptr;
data_ptr m_vals;
};
/**
* @relates any_tuple
* @relates message
*/
inline bool operator==(const any_tuple& lhs, const any_tuple& rhs) {
inline bool operator==(const message& lhs, const message& rhs) {
return lhs.equals(rhs);
}
/**
* @relates any_tuple
* @relates message
*/
inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) {
inline bool operator!=(const message& lhs, const message& rhs) {
return !(lhs == rhs);
}
/**
* @brief Creates an {@link any_tuple} containing the elements @p args.
* @brief Creates an {@link message} containing the elements @p args.
* @param args Values to initialize the tuple elements.
*/
template<typename... Ts>
inline any_tuple make_any_tuple(Ts&&... args) {
return make_cow_tuple(std::forward<Ts>(args)...);
template<typename T, typename... Ts>
typename std::enable_if<
!std::is_same<message, typename util::rm_const_and_ref<T>::type>::value ||
(sizeof...(Ts) > 0),
message>::type
make_message(T&& arg, Ts&&... args) {
using namespace detail;
typedef tuple_vals<typename strip_and_convert<T>::type,
typename strip_and_convert<Ts>::type...> data;
auto ptr = new data(std::forward<T>(arg), std::forward<Ts>(args)...);
return message{detail::message_data::ptr{ptr}};
}
inline message make_message(message other) { return std::move(other); }
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
inline bool any_tuple::empty() const {
return size() == 0;
}
inline bool message::empty() const { return size() == 0; }
template<typename T>
inline const T& any_tuple::get_as(size_t p) const {
inline const T& message::get_as(size_t p) const {
CPPA_REQUIRE(*(type_at(p)) == typeid(T));
return *reinterpret_cast<const T*>(at(p));
}
template<typename T>
inline T& any_tuple::get_as_mutable(size_t p) {
inline T& message::get_as_mutable(size_t p) {
CPPA_REQUIRE(*(type_at(p)) == typeid(T));
return *reinterpret_cast<T*>(mutable_at(p));
}
inline any_tuple::const_iterator any_tuple::begin() const {
inline message::const_iterator message::begin() const {
return m_vals->begin();
}
inline any_tuple::const_iterator any_tuple::end() const {
return m_vals->end();
}
inline message::const_iterator message::end() const { return m_vals->end(); }
inline any_tuple::data_ptr& any_tuple::vals() {
return m_vals;
}
inline message::data_ptr& message::vals() { return m_vals; }
inline const any_tuple::data_ptr& any_tuple::vals() const {
return m_vals;
}
inline const message::data_ptr& message::vals() const { return m_vals; }
inline const any_tuple::data_ptr& any_tuple::cvals() const {
return m_vals;
}
inline const message::data_ptr& message::cvals() const { return m_vals; }
inline const std::type_info* any_tuple::type_token() const {
inline const std::type_info* message::type_token() const {
return m_vals->type_token();
}
inline bool any_tuple::dynamically_typed() const {
inline bool message::dynamically_typed() const {
return m_vals->dynamically_typed();
}
inline void any_tuple::force_detach() {
m_vals.detach();
}
inline void message::force_detach() { m_vals.detach(); }
inline const std::string* any_tuple::tuple_type_names() const {
inline const std::string* message::tuple_type_names() const {
return m_vals->tuple_type_names();
}
inline size_t message::size() const { return m_vals ? m_vals->size() : 0; }
inline size_t any_tuple::size() const {
return m_vals ? m_vals->size() : 0;
}
inline any_tuple any_tuple::take(size_t n) const {
inline message message::take(size_t n) const {
return n >= size() ? *this : drop_right(size() - n);
}
inline any_tuple any_tuple::take_right(size_t n) const {
inline message message::take_right(size_t n) const {
return n >= size() ? *this : drop(size() - n);
}
template<typename T, bool IsIterable = true>
struct any_tuple_view_trait_impl {
static constexpr bool is_mutable_ref = std::is_reference<T>::value
&& !std::is_const<T>::value;
typedef std::integral_constant<bool, is_mutable_ref> can_optimize;
typedef std::integral_constant<bool, true> is_container;
};
template<typename T>
struct any_tuple_view_trait_impl<T, false> {
typedef typename util::rm_const_and_ref<T>::type type;
typedef typename detail::implicit_conversions<type>::type mapped;
static_assert(util::is_legal_tuple_type<mapped>::value,
"T is not a valid tuple type");
static constexpr bool is_mutable_ref = std::is_same<mapped, type>::value
&& std::is_reference<T>::value
&& not std::is_const<T>::value;
typedef std::integral_constant<bool, is_mutable_ref> can_optimize;
typedef std::integral_constant<bool, false> is_container;
};
template<typename T>
struct any_tuple_view_trait {
typedef typename util::rm_const_and_ref<T>::type type;
typedef any_tuple_view_trait_impl<T, util::is_iterable<type>::value> impl;
typedef typename impl::can_optimize can_optimize;
typedef typename impl::is_container is_container;
struct move_from_tuple_helper {
template<typename... Ts>
inline message operator()(Ts&... vs) {
return make_message(std::move(vs)...);
}
};
template<typename T>
inline any_tuple any_tuple::view(T&& value) {
typedef any_tuple_view_trait<T> trait;
typename trait::can_optimize can_optimize;
typename trait::is_container is_container;
return view(std::forward<T>(value), is_container, can_optimize);
}
template<typename T, typename CanOptimize>
any_tuple any_tuple::view(T&& v, std::true_type, CanOptimize t) {
return any_tuple{container_view(std::forward<T>(v), t)};
}
template<typename T, typename CanOptimize>
any_tuple any_tuple::view(T&& v, std::false_type, CanOptimize t) {
return any_tuple{simple_view(std::forward<T>(v), t)};
}
template<typename T>
auto any_tuple::simple_view(T& v, std::true_type) -> raw_ptr {
return new detail::tuple_view<T>(&v);
}
template<typename T, typename U>
auto any_tuple::simple_view(std::pair<T, U>& p, std::true_type) -> raw_ptr {
return new detail::tuple_view<T, U>(&p.first, &p.second);
}
template<typename T>
auto any_tuple::simple_view(T&& v, std::false_type) -> raw_ptr {
typedef typename util::rm_const_and_ref<T>::type vtype;
typedef typename detail::implicit_conversions<vtype>::type converted;
return new detail::tuple_vals<converted>(std::forward<T>(v));
}
template<typename T, typename U>
any_tuple any_tuple::view(std::pair<T, U> p, std::false_type) {
return new detail::tuple_vals<T, U>(std::move(p.first), std::move(p.second));
}
template<typename T>
auto any_tuple::container_view(T& v, std::true_type) -> raw_ptr {
return new detail::container_tuple_view<T>(&v);
template<typename... Ts>
inline message message::move_from_tuple(std::tuple<Ts...>&& tup) {
move_from_tuple_helper f;
return detail::apply_args(f, util::get_indices(tup), tup);
}
template<typename T>
auto any_tuple::container_view(T&& v, std::false_type) -> raw_ptr {
auto vptr = new typename util::rm_const_and_ref<T>::type(std::forward<T>(v));
return new detail::container_tuple_view<T>(vptr, true);
template<typename... Ts>
bool message::has_types() const {
if (size() != sizeof...(Ts)) return false;
const std::type_info* ts[] = {&typeid(Ts)...};
for (size_t i = 0; i < sizeof...(Ts); ++i) {
if (!type_at(i)->equal_to(*ts[i])) return false;
}
return true;
}
} // namespace cppa
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_MESSAGE_BUILDER_HPP
#define CPPA_MESSAGE_BUILDER_HPP
#include <vector>
#include "cppa/message.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/message_data.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
class message_builder {
public:
message_builder() = default;
message_builder(const message_builder&) = delete;
message_builder& operator=(const message_builder&) = delete;
template<typename Iter>
message_builder(Iter first, Iter last) {
append(first, last);
}
template<typename T>
message_builder& append(T what) {
return append_impl<T>(std::move(what));
}
template<typename Iter>
message_builder& append(Iter first, Iter last) {
using vtype = typename util::rm_const_and_ref<decltype(*first)>::type;
using converted = typename detail::implicit_conversions<vtype>::type;
auto uti = uniform_typeid<converted>();
for (; first != last; ++first) {
auto uval = uti->create();
*reinterpret_cast<converted*>(uval->val) = *first;
append(std::move(uval));
}
return *this;
}
message_builder& append(uniform_value what);
message to_message();
optional<message> apply(message_handler handler);
private:
template<typename T>
message_builder&
append_impl(typename detail::implicit_conversions<T>::type what) {
typedef decltype(what) type;
auto uti = uniform_typeid<type>();
auto uval = uti->create();
*reinterpret_cast<type*>(uval->val) = std::move(what);
return append(std::move(uval));
}
std::vector<uniform_value> m_elements;
};
} // namespace cppa
#endif // CPPA_MESSAGE_BUILDER_HPP
......@@ -28,7 +28,7 @@
#include "cppa/on.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/may_have_timeout.hpp"
......@@ -44,9 +44,9 @@ class behavior;
/**
* @brief A partial function implementation
* for {@link cppa::any_tuple any_tuples}.
* for {@link cppa::message messages}.
*/
class partial_function {
class message_handler {
friend class behavior;
......@@ -58,24 +58,18 @@ class partial_function {
inline auto as_behavior_impl() const -> impl_ptr;
partial_function(impl_ptr ptr);
message_handler(impl_ptr ptr);
/** @endcond */
partial_function() = default;
partial_function(partial_function&&) = default;
partial_function(const partial_function&) = default;
partial_function& operator=(partial_function&&) = default;
partial_function& operator=(const partial_function&) = default;
message_handler() = default;
message_handler(message_handler&&) = default;
message_handler(const message_handler&) = default;
message_handler& operator=(message_handler&&) = default;
message_handler& operator=(const message_handler&) = default;
template<typename T, typename... Ts>
partial_function(const T& arg, Ts&&... args);
/**
* @brief Returns @p true if this partial function is defined for the
* types of @p value, false otherwise.
*/
inline bool defined_at(const any_tuple& value);
message_handler(const T& arg, Ts&&... args);
/**
* @brief Returns a value if @p arg was matched by one of the
......@@ -85,7 +79,7 @@ class partial_function {
* does not evaluate guards.
*/
template<typename T>
inline optional<any_tuple> operator()(T&& arg);
inline optional<message> operator()(T&& arg);
/**
* @brief Adds a fallback which is used where
......@@ -97,7 +91,7 @@ class partial_function {
may_have_timeout<typename util::rm_const_and_ref<Ts>::type>::value...
>::value,
behavior,
partial_function
message_handler
>::type
or_else(Ts&&... args) const;
......@@ -108,13 +102,13 @@ class partial_function {
};
template<typename... Cases>
partial_function operator,(const match_expr<Cases...>& mexpr,
const partial_function& pfun) {
message_handler operator,(const match_expr<Cases...>& mexpr,
const message_handler& pfun) {
return mexpr.as_behavior_impl()->or_else(pfun.as_behavior_impl());
}
template<typename... Cases>
partial_function operator,(const partial_function& pfun,
message_handler operator,(const message_handler& pfun,
const match_expr<Cases...>& mexpr) {
return pfun.as_behavior_impl()->or_else(mexpr.as_behavior_impl());
}
......@@ -124,17 +118,13 @@ partial_function operator,(const partial_function& pfun,
******************************************************************************/
template<typename T, typename... Ts>
partial_function::partial_function(const T& arg, Ts&&... args)
message_handler::message_handler(const T& arg, Ts&&... args)
: m_impl(detail::match_expr_concat(
detail::lift_to_match_expr(arg),
detail::lift_to_match_expr(std::forward<Ts>(args))...)) { }
inline bool partial_function::defined_at(const any_tuple& value) {
return (m_impl) && m_impl->defined_at(value);
}
template<typename T>
inline optional<any_tuple> partial_function::operator()(T&& arg) {
inline optional<message> message_handler::operator()(T&& arg) {
return (m_impl) ? m_impl->invoke(std::forward<T>(arg)) : none;
}
......@@ -144,16 +134,16 @@ typename std::conditional<
may_have_timeout<typename util::rm_const_and_ref<Ts>::type>::value...
>::value,
behavior,
partial_function
message_handler
>::type
partial_function::or_else(Ts&&... args) const {
message_handler::or_else(Ts&&... args) const {
// using a behavior is safe here, because we "cast"
// it back to a partial_function when appropriate
behavior tmp{std::forward<Ts>(args)...};
return m_impl->or_else(tmp.as_behavior_impl());
}
inline auto partial_function::as_behavior_impl() const -> impl_ptr {
inline auto message_handler::as_behavior_impl() const -> impl_ptr {
return m_impl;
}
......
......@@ -27,11 +27,11 @@
namespace cppa {
class any_tuple;
class message;
/**
* @brief Encapsulates information about sender, receiver and (synchronous)
* message ID of a message. The message itself is usually an any_tuple.
* message ID of a message. The message itself is usually an message.
*/
class message_header {
......@@ -54,7 +54,7 @@ class message_header {
channel dest,
message_id mid = message_id::invalid);
void deliver(any_tuple msg) const;
void deliver(message msg) const;
};
......
......@@ -16,20 +16,18 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_ON_HPP
#define CPPA_ON_HPP
#include <chrono>
#include <memory>
#include <functional>
#include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/atom.hpp"
#include "cppa/anything.hpp"
#include "cppa/arg_match.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/message.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/may_have_timeout.hpp"
......@@ -41,40 +39,50 @@
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/unboxed.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/arg_match_t.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
namespace detail {
template<bool IsFun, typename T>
struct add_ptr_to_fun_ { typedef T* type; };
struct add_ptr_to_fun_ {
typedef T* type;
};
template<typename T>
struct add_ptr_to_fun_<false, T> { typedef T type; };
struct add_ptr_to_fun_<false, T> {
typedef T type;
};
template<typename T>
struct add_ptr_to_fun : add_ptr_to_fun_<std::is_function<T>::value, T> { };
struct add_ptr_to_fun : add_ptr_to_fun_<std::is_function<T>::value, T> {};
template<bool ToVoid, typename T>
struct to_void_impl { typedef unit_t type; };
struct to_void_impl {
typedef unit_t type;
};
template<typename T>
struct to_void_impl<false, T> { typedef typename add_ptr_to_fun<T>::type type; };
struct to_void_impl<false, T> {
typedef typename add_ptr_to_fun<T>::type type;
};
template<typename T>
struct boxed_to_void : to_void_impl<is_boxed<T>::value, T> {};
template<typename T>
struct boxed_and_not_callable_to_void
: to_void_impl<is_boxed<T>::value || !util::is_callable<T>::value, T> { };
struct boxed_to_void<std::function<
optional<T>(const T&)>> : to_void_impl<is_boxed<T>::value, T> {};
template<typename T>
struct boxed_and_callable_to_void
: to_void_impl<is_boxed<T>::value || util::is_callable<T>::value, T> { };
: to_void_impl<is_boxed<T>::value || util::is_callable<T>::value, T> {};
class behavior_rvalue_builder {
public:
constexpr behavior_rvalue_builder(const util::duration& d) : m_tout(d) { }
constexpr behavior_rvalue_builder(const util::duration& d) : m_tout(d) {}
template<typename F>
timeout_definition<F> operator>>(F&& f) const {
......@@ -82,115 +90,97 @@ class behavior_rvalue_builder {
}
private:
util::duration m_tout;
};
struct rvalue_builder_args_ctor { };
struct rvalue_builder_args_ctor {};
template<class Left, class Right>
struct disjunct_rvalue_builders {
public:
disjunct_rvalue_builders(Left l, Right r)
: m_left(std::move(l)), m_right(std::move(r)) { }
: m_left(std::move(l)), m_right(std::move(r)) {}
template<typename Expr>
auto operator>>(Expr expr)
-> decltype((*(static_cast<Left*>(nullptr)) >> expr).or_else(
*(static_cast<Right*>(nullptr)) >> expr)) const {
-> decltype((*(static_cast<Left*>(nullptr)) >> expr)
.or_else(*(static_cast<Right*>(nullptr)) >>
expr)) const {
return (m_left >> expr).or_else(m_right >> expr);
}
private:
Left m_left;
Right m_right;
};
struct tuple_maker {
template<typename... Ts>
inline auto operator()(Ts&&... args)
-> decltype(std::make_tuple(std::forward<Ts>(args)...)) {
return std::make_tuple(std::forward<Ts>(args)...);
}
};
template<class Guard, class Transformers, class Pattern>
template<class Transformers, class Pattern>
struct rvalue_builder {
typedef typename util::tl_back<Pattern>::type back_type;
static constexpr bool is_complete =
!std::is_same<arg_match_t, back_type>::value;
!std::is_same<detail::arg_match_t, back_type>::value;
typedef typename util::tl_apply<Transformers, tdata>::type fun_container;
typedef typename util::tl_apply<Transformers, std::tuple>::type
fun_container;
Guard m_guard;
fun_container m_funs;
public:
rvalue_builder() = default;
template<typename... Ts>
rvalue_builder(rvalue_builder_args_ctor, const Ts&... args)
: m_guard(args...), m_funs(args...) { }
rvalue_builder(Guard arg0, fun_container arg1)
: m_guard(std::move(arg0)), m_funs(std::move(arg1)) { }
template<typename NewGuard>
rvalue_builder<
guard_expr<
logical_and_op,
guard_expr<exec_xfun_op, Guard, unit_t>,
NewGuard>,
Transformers,
Pattern>
when(NewGuard ng,
typename std::enable_if<
std::is_same<NewGuard, NewGuard>::value
&& !std::is_same<Guard, empty_value_guard>::value
>::type* = 0 ) const {
return {(ge_sub_function(m_guard) && ng), std::move(m_funs)};
}
: m_funs(args...) {}
template<typename NewGuard>
rvalue_builder<NewGuard, Transformers, Pattern>
when(NewGuard ng,
typename std::enable_if<
std::is_same<NewGuard, NewGuard>::value
&& std::is_same<Guard, empty_value_guard>::value
>::type* = 0 ) const {
return {std::move(ng), std::move(m_funs)};
}
rvalue_builder(fun_container arg1) : m_funs(std::move(arg1)) {}
template<typename Expr>
match_expr<typename get_case<is_complete, Expr, Guard, Transformers, Pattern>::type>
match_expr<
typename get_case<is_complete, Expr, Transformers, Pattern>::type>
operator>>(Expr expr) const {
typedef typename get_case<
is_complete,
Expr,
Guard,
Transformers,
Pattern
>::type
tpair;
return tpair{typename tpair::first_type{m_funs},
typename tpair::second_type{std::move(expr),
std::move(m_guard)}};
typedef typename get_case<is_complete, Expr, Transformers,
Pattern>::type lifted_expr;
// adjust m_funs to exactly match expected projections in match case
typedef typename lifted_expr::projections_list target;
typedef typename util::tl_trim<Transformers>::type trimmed_projections;
tuple_maker f;
auto lhs = apply_args(f, get_indices(trimmed_projections{}), m_funs);
typename util::tl_apply<
typename util::tl_slice<target,
util::tl_size<trimmed_projections>::value,
util::tl_size<target>::value>::type,
std::tuple>::type
rhs;
// done
return lifted_expr{std::move(expr), std::tuple_cat(lhs, rhs)};
}
template<class G, class T, class P>
disjunct_rvalue_builders<rvalue_builder, rvalue_builder<G, T, P> >
operator||(rvalue_builder<G, T, P> other) const {
template<class T, class P>
disjunct_rvalue_builders<rvalue_builder, rvalue_builder<T, P>>
operator||(rvalue_builder<T, P> other) const {
return {*this, std::move(other)};
}
};
template<bool IsCallable, typename T>
struct pattern_type_ {
typedef util::get_callable_trait<T> ctrait;
typedef typename ctrait::arg_types args;
static_assert(util::tl_size<args>::value == 1, "only unary functions allowed");
typedef typename util::rm_const_and_ref<typename util::tl_head<args>::type>::type type;
static_assert(util::tl_size<args>::value == 1,
"only unary functions allowed");
typedef typename util::rm_const_and_ref<
typename util::tl_head<args>::type>::type type;
};
template<typename T>
......@@ -204,9 +194,9 @@ struct pattern_type_<false, T> {
};
template<typename T>
struct pattern_type : pattern_type_<util::is_callable<T>::value && !detail::is_boxed<T>::value, T> {
};
struct pattern_type
: pattern_type_<
util::is_callable<T>::value && !is_boxed<T>::value, T> {};
} // namespace detail
} // namespace cppa
......@@ -284,44 +274,86 @@ constexpr typename detail::boxed<T>::type val() {
return typename detail::boxed<T>::type();
}
typedef typename detail::boxed<arg_match_t>::type boxed_arg_match_t;
typedef typename detail::boxed<detail::arg_match_t>::type boxed_arg_match_t;
constexpr boxed_arg_match_t arg_match = boxed_arg_match_t();
//constexpr boxed_arg_match_t arg_match = boxed_arg_match_t();
template<typename T, typename Predicate>
std::function<optional<T>(const T&)> guarded(Predicate p, T value) {
return[=](const T & other)->optional<T> {
if (p(other, value)) return value;
return none;
};
}
// special case covering arg_match as argument to guarded()
template<typename T, typename Predicate>
unit_t guarded(Predicate, const util::wrapped<T>&) {
return {};
}
template<typename T, bool Callable = util::is_callable<T>::value>
struct to_guard {
static std::function<optional<T>(const T&)> _(const T& value) {
return guarded<T>(std::equal_to<T>{}, value);
}
};
template<>
struct to_guard<anything, false> {
template<typename U>
static unit_t _(const U&) {
return {};
}
};
template<typename T>
struct to_guard<util::wrapped<T>, false> : to_guard<anything> {};
template<typename T>
struct is_optional : std::false_type {};
template<typename T>
struct is_optional<optional<T>> : std::true_type {};
template<typename T>
struct to_guard<T, true> {
typedef typename util::get_callable_trait<T>::type ct;
typedef typename ct::arg_types arg_types;
static_assert(util::tl_size<arg_types>::value == 1,
"projection/guard must take exactly one argument");
static_assert(is_optional<typename ct::result_type>::value,
"projection/guard must return an optional value");
typedef typename std::conditional<std::is_function<T>::value, T*, T>::type
value_type;
static value_type _(value_type val) { return val; }
};
template<typename T>
struct to_guard<util::wrapped<T>(), true> : to_guard<anything> {};
template<typename T, typename... Ts>
detail::rvalue_builder<
detail::value_guard<
typename util::tl_filter_not<
typename util::tl_trim<
typename util::tl_map<
util::type_list<T, Ts...>,
detail::boxed_and_callable_to_void,
detail::implicit_conversions
>::type
>::type,
is_anything
>::type
>,
typename util::tl_map<
util::type_list<T, Ts...>,
detail::boxed_and_not_callable_to_void
>::type,
auto on(const T& arg, const Ts&... args)
-> detail::rvalue_builder<
util::type_list<
decltype(to_guard<typename detail::strip_and_convert<T>::type>::_(
arg)),
decltype(to_guard<
typename detail::strip_and_convert<Ts>::type>::_(args))...>,
util::type_list<typename detail::pattern_type<T>::type,
typename detail::pattern_type<Ts>::type...> >
on(const T& arg, const Ts&... args) {
return {detail::rvalue_builder_args_ctor{}, arg, args...};
typename detail::pattern_type<Ts>::type...>> {
return {detail::rvalue_builder_args_ctor{},
to_guard<typename detail::strip_and_convert<T>::type>::_(arg),
to_guard<typename detail::strip_and_convert<Ts>::type>::_(args)...};
}
inline detail::rvalue_builder<detail::empty_value_guard,
util::empty_type_list,
util::empty_type_list > on() {
inline detail::rvalue_builder<util::empty_type_list, util::empty_type_list>
on() {
return {};
}
template<typename T0, typename... Ts>
detail::rvalue_builder<detail::empty_value_guard,
util::empty_type_list,
util::type_list<T0, Ts...> >
detail::rvalue_builder<util::empty_type_list, util::type_list<T0, Ts...>>
on() {
return {};
}
......@@ -350,12 +382,10 @@ decltype(on(A0, A1, A2, A3, val<Ts>()...)) on() {
template<class Rep, class Period>
constexpr detail::behavior_rvalue_builder
after(const std::chrono::duration<Rep, Period>& d) {
return { util::duration(d) };
return {duration(d)};
}
inline decltype(on<anything>()) others() {
return on<anything>();
}
inline decltype(on<anything>()) others() { return on<anything>(); }
// some more convenience
......@@ -364,38 +394,16 @@ namespace detail {
class on_the_fly_rvalue_builder {
public:
constexpr on_the_fly_rvalue_builder() { }
template<typename Guard>
auto when(Guard g) const -> decltype(on(arg_match).when(g)) {
return on(arg_match).when(g);
}
constexpr on_the_fly_rvalue_builder() {}
template<typename Expr>
match_expr<
typename get_case<
false,
Expr,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type>
match_expr<typename get_case<false, Expr, util::empty_type_list,
util::empty_type_list>::type>
operator>>(Expr expr) const {
typedef typename get_case<
false,
Expr,
empty_value_guard,
util::empty_type_list,
util::empty_type_list
>::type
result_type;
return result_type{typename result_type::first_type{},
typename result_type::second_type{
std::move(expr),
empty_value_guard{}}};
typedef typename get_case<false, Expr, util::empty_type_list,
util::empty_type_list>::type result_type;
return result_type{std::move(expr)};
}
};
} // namespace detail
......
......@@ -77,7 +77,7 @@ struct cl_spawn_helper<R (Ts...), void> {
Us&&... args) const {
using std::move;
using std::forward;
map_arg_fun f0 = [] (any_tuple msg) {
map_arg_fun f0 = [] (message msg) {
return tuple_cast<
typename util::rm_const_and_ref<
typename carr_to_vec<Ts>::type
......@@ -85,7 +85,7 @@ struct cl_spawn_helper<R (Ts...), void> {
>(msg);
};
map_res_fun f1 = [] (result_type& result) {
return make_any_tuple(move(result));
return make_message(move(result));
};
return impl::create(p, fname, move(f0), move(f1), forward<Us>(args)...);
}
......@@ -93,8 +93,8 @@ struct cl_spawn_helper<R (Ts...), void> {
};
template<typename R, typename... Ts>
struct cl_spawn_helper<std::function<optional<cow_tuple<Ts...>> (any_tuple)>,
std::function<any_tuple (R&)>>
struct cl_spawn_helper<std::function<optional<cow_tuple<Ts...>> (message)>,
std::function<message (R&)>>
: cl_spawn_helper<R (Ts...)> { };
} // namespace detail
......
......@@ -59,10 +59,10 @@ namespace opencl {
class opencl_metainfo;
template <typename Signature>
template<typename Signature>
class actor_facade;
template <typename Ret, typename... Args>
template<typename Ret, typename... Args>
class actor_facade<Ret(Args...)> : public abstract_actor {
friend class command<actor_facade, Ret>;
......@@ -72,8 +72,8 @@ class actor_facade<Ret(Args...)> : public abstract_actor {
typedef cow_tuple<typename util::rm_const_and_ref<Args>::type...>
args_tuple;
typedef std::function<optional<args_tuple>(any_tuple)> arg_mapping;
typedef std::function<any_tuple(Ret&)> result_mapping;
typedef std::function<optional<args_tuple>(message)> arg_mapping;
typedef std::function<message(Ret&)> result_mapping;
static intrusive_ptr<actor_facade>
create(const program& prog, const char* kernel_name,
......@@ -120,7 +120,7 @@ class actor_facade<Ret(Args...)> : public abstract_actor {
};
}
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit*) override {
void enqueue(msg_hdr_cref hdr, message msg, execution_unit*) override {
CPPA_LOG_TRACE("");
typename util::il_indices<util::type_list<Args...>>::type indices;
enqueue_impl(hdr.sender, std::move(msg), hdr.id, indices);
......@@ -149,8 +149,8 @@ class actor_facade<Ret(Args...)> : public abstract_actor {
CPPA_LOG_TRACE("id: " << this->id());
}
template <long... Is>
void enqueue_impl(const actor_addr& sender, any_tuple msg, message_id id,
template<long... Is>
void enqueue_impl(const actor_addr& sender, message msg, message_id id,
util::int_list<Is...>) {
auto opt = m_map_args(std::move(msg));
if (opt) {
......
......@@ -57,7 +57,7 @@ class command : public ref_counted {
std::vector<cl_event> events,
std::vector<mem_ptr> arguments,
size_t result_size,
any_tuple msg)
message msg)
: m_result_size(result_size)
, m_handle(handle)
, m_actor_facade(actor_facade)
......@@ -151,7 +151,7 @@ class command : public ref_counted {
std::vector<cl_event> m_events;
std::vector<mem_ptr> m_arguments;
R m_result;
any_tuple m_msg; // required to keep the argument buffers alive (for async copy)
message m_msg; // required to keep the argument buffers alive (for async copy)
void handle_results () {
m_handle.deliver(m_actor_facade->m_map_result(m_result));
......
......@@ -33,11 +33,6 @@
namespace cppa {
//template<typename T>
//optional<T> conv_arg(const std::string& arg) {
// return detail::conv_arg_impl<T>::_(arg);
//}
/**
* @brief Right-hand side of a match expression for a program option
* reading an argument of type @p T.
......@@ -74,11 +69,15 @@ struct option_info {
typedef std::map<std::string, std::map<std::pair<char, std::string>, option_info> >
options_description;
using opt_rvalue_builder = decltype(on(std::function<optional<std::string> (const std::string&)>{}) || on(std::string{}, val<std::string>));
using opt0_rvalue_builder = decltype(on(std::string{}) || on(std::string{}));
/**
* @brief Left-hand side of a match expression for a program option with
* one argument.
*/
detail::opt1_rvalue_builder<true> on_opt1(char short_opt,
opt_rvalue_builder on_opt1(char short_opt,
std::string long_opt,
options_description* desc = nullptr,
std::string help_text = "",
......@@ -88,7 +87,7 @@ detail::opt1_rvalue_builder<true> on_opt1(char short_opt,
* @brief Left-hand side of a match expression for a program option with
* no argument.
*/
detail::opt0_rvalue_builder on_opt0(char short_opt,
opt0_rvalue_builder on_opt0(char short_opt,
std::string long_opt,
options_description* desc = nullptr,
std::string help_text = "",
......
......@@ -287,13 +287,6 @@ class optional<void> {
};
/** @relates option */
template<typename T>
struct is_optional { static constexpr bool value = false; };
template<typename T>
struct is_optional<optional<T>> { static constexpr bool value = true; };
/** @relates option */
template<typename T, typename U>
bool operator==(const optional<T>& lhs, const optional<U>& rhs) {
......
......@@ -22,7 +22,7 @@
#include <atomic>
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/singletons.hpp"
#include "cppa/message_header.hpp"
......@@ -50,7 +50,7 @@ class cooperative_scheduling {
template<class Actor>
void enqueue(Actor* self, msg_hdr_cref hdr,
any_tuple& msg, execution_unit* host) {
message& msg, execution_unit* host) {
auto e = self->new_mailbox_element(hdr, std::move(msg));
switch (self->mailbox().enqueue(e)) {
case intrusive::enqueue_result::unblocked_reader: {
......
......@@ -33,7 +33,7 @@
#include "cppa/exit_reason.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/response_promise.hpp"
#include "cppa/detail/memory.hpp"
......@@ -113,7 +113,7 @@ class invoke_policy {
std::list<std::unique_ptr<mailbox_element, detail::disposer> > m_cache;
inline void handle_timeout(partial_function&) {
inline void handle_timeout(message_handler&) {
CPPA_CRITICAL("handle_timeout(partial_function&)");
}
......@@ -136,7 +136,7 @@ class invoke_policy {
template<class Actor>
msg_type filter_msg(Actor* self, mailbox_element* node) {
const any_tuple& msg = node->msg;
const message& msg = node->msg;
auto mid = node->mid;
auto& arr = detail::static_types_array<exit_msg,
timeout_msg,
......@@ -187,8 +187,8 @@ class invoke_policy {
// - extracts response message from handler
// - returns true if fun was successfully invoked
template<class Actor, class Fun, class MaybeResponseHandle = int>
optional<any_tuple> invoke_fun(Actor* self,
any_tuple& msg,
optional<message> invoke_fun(Actor* self,
message& msg,
message_id& mid,
Fun& fun,
MaybeResponseHandle hdl = MaybeResponseHandle{}) {
......@@ -209,7 +209,7 @@ class invoke_policy {
<< " did not reply to a "
"synchronous request message");
auto fhdl = fetch_response_promise(self, hdl);
if (fhdl) fhdl.deliver(make_any_tuple(unit));
if (fhdl) fhdl.deliver(make_message(unit));
}
} else {
if ( detail::matches<atom_value, std::uint64_t>(*res)
......@@ -226,11 +226,11 @@ class invoke_policy {
if (ref_opt) {
behavior cpy = *ref_opt;
*ref_opt = cpy.add_continuation(
[=](any_tuple& intermediate) -> optional<any_tuple> {
[=](message& intermediate) -> optional<message> {
if (!intermediate.empty()) {
// do no use lamba expresion type to
// avoid recursive template instantiaton
behavior::continuation_fun f2 = [=](any_tuple& m) -> optional<any_tuple> {
behavior::continuation_fun f2 = [=](message& m) -> optional<message> {
return std::move(m);
};
auto mutable_mid = mid;
......@@ -257,7 +257,7 @@ class invoke_policy {
if (fhdl) {
fhdl.deliver(std::move(*res));
// inform caller about success
return any_tuple{};
return message{};
}
}
}
......
......@@ -44,7 +44,7 @@ class middleman_scheduling {
typedef intrusive_ptr<Actor> pointer;
continuation(pointer ptr, msg_hdr_cref hdr, any_tuple&& msg)
continuation(pointer ptr, msg_hdr_cref hdr, message&& msg)
: m_self(std::move(ptr)), m_hdr(hdr), m_data(std::move(msg)) { }
inline void operator()() const {
......@@ -55,7 +55,7 @@ class middleman_scheduling {
pointer m_self;
message_header m_hdr;
any_tuple m_data;
message m_data;
};
......@@ -80,7 +80,7 @@ class middleman_scheduling {
}
template<class Actor>
void enqueue(Actor* self, msg_hdr_cref hdr, any_tuple& msg) {
void enqueue(Actor* self, msg_hdr_cref hdr, message& msg) {
get_middleman()->run_later(continuation<Actor>{self, hdr, std::move(msg)});
}
......
......@@ -53,7 +53,7 @@ class no_scheduling {
template<class Actor>
void enqueue(Actor* self, msg_hdr_cref hdr,
any_tuple& msg, execution_unit*) {
message& msg, execution_unit*) {
auto ptr = self->new_mailbox_element(hdr, std::move(msg));
// returns false if mailbox has been closed
if (!self->mailbox().synchronized_enqueue(m_mtx, m_cv, ptr)) {
......
......@@ -90,7 +90,7 @@ class scheduling_policy {
template<class Actor>
void enqueue(Actor* self,
msg_hdr_cref hdr,
any_tuple& msg,
message& msg,
execution_unit* host);
/**
......
......@@ -24,7 +24,7 @@
#include <QApplication>
#include "cppa/actor_companion.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/policy/sequential_invoke.hpp"
......
......@@ -53,7 +53,7 @@ struct blocking_response_handle_tag { };
* and enables <tt>sync_send(...).then(...)</tt>.
*
* @tparam Self The type of the actor this handle belongs to.
* @tparam Result Either any_tuple or type_list<R1, R2, ... Rn>.
* @tparam Result Either message or type_list<R1, R2, ... Rn>.
* @tparam Tag Either {@link nonblocking_response_handle_tag} or
* {@link blocking_response_handle_tag}.
*/
......@@ -64,7 +64,7 @@ class response_handle;
* nonblocking + untyped *
******************************************************************************/
template<class Self>
class response_handle<Self, any_tuple, nonblocking_response_handle_tag> {
class response_handle<Self, message, nonblocking_response_handle_tag> {
public:
......@@ -149,7 +149,7 @@ class response_handle<Self, util::type_list<Ts...>, nonblocking_response_handle_
* blocking + untyped *
******************************************************************************/
template<class Self>
class response_handle<Self, any_tuple, blocking_response_handle_tag> {
class response_handle<Self, message, blocking_response_handle_tag> {
public:
......
......@@ -21,7 +21,7 @@
#define CPPA_RESPONSE_PROMISE_HPP
#include "cppa/actor.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/actor_addr.hpp"
#include "cppa/message_id.hpp"
......@@ -58,7 +58,7 @@ class response_promise {
/**
* @brief Sends @p response_message and invalidates this handle afterwards.
*/
void deliver(any_tuple response_message);
void deliver(message response_message);
private:
......
......@@ -30,7 +30,7 @@
#include "cppa/atom.hpp"
#include "cppa/actor.hpp"
#include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/attachable.hpp"
#include "cppa/scoped_actor.hpp"
......@@ -160,8 +160,8 @@ class coordinator {
template<typename Duration, typename... Data>
void delayed_send(message_header hdr,
const Duration& rel_time,
any_tuple data ) {
auto tup = make_any_tuple(atom("SEND"),
message data ) {
auto tup = make_message(atom("SEND"),
util::duration{rel_time},
std::move(hdr),
std::move(data));
......@@ -171,9 +171,9 @@ class coordinator {
template<typename Duration, typename... Data>
void delayed_reply(message_header hdr,
const Duration& rel_time,
any_tuple data ) {
message data ) {
CPPA_REQUIRE(hdr.id.valid() && hdr.id.is_response());
auto tup = make_any_tuple(atom("SEND"),
auto tup = make_message(atom("SEND"),
util::duration{rel_time},
std::move(hdr),
std::move(data));
......
......@@ -20,7 +20,7 @@
#ifndef CPPA_SINGLE_TIMEOUT_HPP
#define CPPA_SINGLE_TIMEOUT_HPP
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/system_messages.hpp"
#include "cppa/util/duration.hpp"
......@@ -39,7 +39,7 @@ class single_timeout : public Base {
typedef single_timeout combined_type;
template <typename... Ts>
template<typename... Ts>
single_timeout(Ts&&... args)
: super(std::forward<Ts>(args)...), m_has_timeout(false)
, m_timeout_id(0) { }
......@@ -48,7 +48,7 @@ class single_timeout : public Base {
if (d.valid()) {
m_has_timeout = true;
auto tid = ++m_timeout_id;
auto msg = make_any_tuple(timeout_msg{tid});
auto msg = make_message(timeout_msg{tid});
if (d.is_zero()) {
// immediately enqueue timeout message if duration == 0s
this->enqueue({this->address(), this}, std::move(msg),
......
......@@ -21,7 +21,7 @@
#define CPPA_SYNC_SENDER_HPP
#include "cppa/actor.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/response_handle.hpp"
#include "cppa/message_priority.hpp"
......@@ -35,7 +35,7 @@ class sync_sender_impl : public Base {
public:
typedef response_handle<Subtype,
any_tuple,
message,
ResponseHandleTag>
response_handle_type;
......@@ -54,12 +54,12 @@ class sync_sender_impl : public Base {
*/
response_handle_type sync_send_tuple(message_priority prio,
const actor& dest,
any_tuple what) {
message what) {
return {dptr()->sync_send_tuple_impl(prio, dest, std::move(what)),
dptr()};
}
response_handle_type sync_send_tuple(const actor& dest, any_tuple what) {
response_handle_type sync_send_tuple(const actor& dest, message what) {
return sync_send_tuple(message_priority::normal, dest, std::move(what));
}
......@@ -79,14 +79,14 @@ class sync_sender_impl : public Base {
Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return sync_send_tuple(prio, dest,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
template<typename... Ts>
response_handle_type sync_send(const actor& dest, Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return sync_send_tuple(message_priority::normal,
dest, make_any_tuple(std::forward<Ts>(what)...));
dest, make_message(std::forward<Ts>(what)...));
}
/**************************************************************************
......@@ -96,7 +96,7 @@ class sync_sender_impl : public Base {
response_handle_type timed_sync_send_tuple(message_priority prio,
const actor& dest,
const util::duration& rtime,
any_tuple what) {
message what) {
return {dptr()->timed_sync_send_tuple_impl(prio, dest, rtime,
std::move(what)),
dptr()};
......@@ -104,7 +104,7 @@ class sync_sender_impl : public Base {
response_handle_type timed_sync_send_tuple(const actor& dest,
const util::duration& rtime,
any_tuple what) {
message what) {
return {dptr()->timed_sync_send_tuple_impl(message_priority::normal,
dest, rtime,
std::move(what)),
......@@ -118,7 +118,7 @@ class sync_sender_impl : public Base {
Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return timed_sync_send_tuple(prio, dest, rtime,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
template<typename... Ts>
......@@ -127,7 +127,7 @@ class sync_sender_impl : public Base {
Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return timed_sync_send_tuple(message_priority::normal, dest, rtime,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
/**************************************************************************
......@@ -263,7 +263,7 @@ class sync_sender_impl : public Base {
Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return timed_sync_send_tuple(prio, dest, rtime,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
template<typename... Rs, typename... Ts>
......@@ -284,7 +284,7 @@ class sync_sender_impl : public Base {
Ts&&... what) {
static_assert(sizeof...(Ts) > 0, "no message to send");
return timed_sync_send_tuple(message_priority::normal, dest, rtime,
make_any_tuple(std::forward<Ts>(what)...));
make_message(std::forward<Ts>(what)...));
}
private:
......
......@@ -28,7 +28,7 @@
#include "cppa/channel.hpp"
#include "cppa/node_id.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/abstract_group.hpp"
#include "cppa/message_header.hpp"
......@@ -49,7 +49,7 @@ inline std::string to_string_impl(const T& what) {
} // namespace detail
inline std::string to_string(const any_tuple& what) {
inline std::string to_string(const message& what) {
return detail::to_string_impl(what);
}
......
......@@ -39,10 +39,10 @@ namespace cppa {
* @param tup Dynamically typed tuple.
* @returns An {@link option} for a {@link cow_tuple} with the types
* deduced from {T...}.
* @relates any_tuple
* @relates message
*/
template<typename... T>
auto moving_tuple_cast(any_tuple& tup);
auto moving_tuple_cast(message& tup);
/**
* @brief Tries to cast @p tup to {@link cow_tuple cow_tuple<T...>} and moves
......@@ -50,35 +50,35 @@ auto moving_tuple_cast(any_tuple& tup);
* @param tup Dynamically typed tuple.
* @returns An {@link option} for a {@link cow_tuple} with the types
* deduced from {T...}.
* @relates any_tuple
* @relates message
*/
template<typename... T>
auto moving_tuple_cast(any_tuple& tup, const util::type_list<T...>&);
auto moving_tuple_cast(message& tup, const util::type_list<T...>&);
/**
* @brief Tries to cast @p tup to {@link cow_tuple cow_tuple<T...>}.
* @param tup Dynamically typed tuple.
* @returns An {@link option} for a {@link cow_tuple} with the types
* deduced from {T...}.
* @relates any_tuple
* @relates message
*/
template<typename... T>
auto tuple_cast(any_tuple tup);
auto tuple_cast(message tup);
/**
* @brief Tries to cast @p tup to {@link cow_tuple cow_tuple<T...>}.
* @param tup Dynamically typed tuple.
* @returns An {@link option} for a {@link cow_tuple} with the types
* deduced from {T...}.
* @relates any_tuple
* @relates message
*/
template<typename... T>
auto tuple_cast(any_tuple tup, const util::type_list<T...>&);
auto tuple_cast(message tup, const util::type_list<T...>&);
#else
template<typename... T>
auto moving_tuple_cast(any_tuple& tup)
auto moving_tuple_cast(message& tup)
-> optional<
typename cow_tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>,
......@@ -92,13 +92,13 @@ auto moving_tuple_cast(any_tuple& tup)
}
template<typename... T>
auto moving_tuple_cast(any_tuple& tup, const util::type_list<T...>&)
auto moving_tuple_cast(message& tup, const util::type_list<T...>&)
-> decltype(moving_tuple_cast<T...>(tup)) {
return moving_tuple_cast<T...>(tup);
}
template<typename... T>
auto tuple_cast(any_tuple tup)
auto tuple_cast(message tup)
-> optional<
typename cow_tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>,
......@@ -108,7 +108,7 @@ auto tuple_cast(any_tuple tup)
}
template<typename... T>
auto tuple_cast(any_tuple tup, const util::type_list<T...>&)
auto tuple_cast(message tup, const util::type_list<T...>&)
-> decltype(tuple_cast<T...>(tup)) {
return moving_tuple_cast<T...>(tup);
}
......@@ -116,7 +116,7 @@ auto tuple_cast(any_tuple tup, const util::type_list<T...>&)
// ************************ for in-library use only! ************************ //
template<typename... T>
auto unsafe_tuple_cast(any_tuple& tup, const util::type_list<T...>&)
auto unsafe_tuple_cast(message& tup, const util::type_list<T...>&)
-> decltype(tuple_cast<T...>(tup)) {
return tuple_cast<T...>(tup);
}
......
......@@ -206,11 +206,6 @@ class typed_behavior {
template<typename... Cs>
void set(match_expr<Cs...>&& expr) {
// check for (the lack of) guards
static_assert(util::conjunction<
detail::match_expr_has_no_guard<Cs>::value...
>::value,
"typed actors are not allowed to use guard expressions");
// do some transformation before type-checking the input signatures
typedef typename util::tl_map<
util::type_list<
......
......@@ -246,9 +246,9 @@ class uniform_type_info {
virtual void deserialize(void* instance, deserializer* source) const = 0;
/**
* @brief Returns @p instance encapsulated as an @p any_tuple.
* @brief Returns @p instance encapsulated as an @p message.
*/
virtual any_tuple as_any_tuple(void* instance) const = 0;
virtual message as_message(void* instance) const = 0;
protected:
......
......@@ -20,7 +20,7 @@
#ifndef CPPA_UTIL_ABSTRACT_UNIFORM_TYPE_INFO_HPP
#define CPPA_UTIL_ABSTRACT_UNIFORM_TYPE_INFO_HPP
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp"
......@@ -49,8 +49,8 @@ class abstract_uniform_type_info : public uniform_type_info {
return m_name.c_str();
}
any_tuple as_any_tuple(void* instance) const override {
return make_any_tuple(deref(instance));
message as_message(void* instance) const override {
return make_message(deref(instance));
}
bool equals(const void* lhs, const void* rhs) const override {
......
......@@ -22,7 +22,6 @@
#include <functional>
#include "cppa/guard_expr.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/util/rebindable_reference.hpp"
......
......@@ -152,7 +152,7 @@ struct is_builtin {
std::u16string,
std::u32string,
atom_value,
any_tuple,
message,
message_header,
actor,
group,
......
......@@ -14,7 +14,7 @@ using namespace cppa;
ChatWidget::ChatWidget(QWidget* parent, Qt::WindowFlags f)
: super(parent, f), m_input(nullptr), m_output(nullptr) {
set_message_handler ([=](local_actor* self) -> partial_function {
set_message_handler ([=](local_actor* self) -> message_handler {
return {
on(atom("join"), arg_match) >> [=](const group& what) {
if (m_chatroom) {
......
......@@ -39,16 +39,16 @@ istream& operator>>(istream& is, line& l) {
return is;
}
any_tuple s_last_line;
message s_last_line;
any_tuple split_line(const line& l) {
message 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));
s_last_line = message::view(std::move(result));
return s_last_line;
}
......
......@@ -28,11 +28,11 @@ using namespace cppa::placeholders;
// our "service"
void calculator(event_based_actor* self) {
self->become (
on(atom("plus"), arg_match) >> [](int a, int b) -> any_tuple {
return make_any_tuple(atom("result"), a + b);
on(atom("plus"), arg_match) >> [](int a, int b) -> message {
return make_message(atom("result"), a + b);
},
on(atom("minus"), arg_match) >> [](int a, int b) -> any_tuple {
return make_any_tuple(atom("result"), a - b);
on(atom("minus"), arg_match) >> [](int a, int b) -> message {
return make_message(atom("result"), a - b);
},
on(atom("quit")) >> [=] {
self->quit();
......
......@@ -31,7 +31,7 @@ istream& operator>>(istream& is, line& l) {
namespace { string s_last_line; }
any_tuple split_line(const line& l) {
message split_line(const line& l) {
istringstream strs(l.str);
s_last_line = move(l.str);
string tmp;
......@@ -39,7 +39,7 @@ any_tuple split_line(const line& l) {
while (getline(strs, tmp, ' ')) {
if (!tmp.empty()) result.push_back(std::move(tmp));
}
return any_tuple::view(std::move(result));
return message::view(std::move(result));
}
void client(event_based_actor* self, const string& name) {
......
......@@ -40,9 +40,9 @@ behavior ping(event_based_actor* self, size_t num_pings) {
on(atom("kickoff"), arg_match) >> [=](const actor& pong) {
self->send(pong, atom("ping"), int32_t(1));
self->become (
on(atom("pong"), arg_match) >> [=](int32_t value) -> any_tuple {
on(atom("pong"), arg_match) >> [=](int32_t value) -> message {
if (++*count >= num_pings) self->quit();
return make_any_tuple(atom("ping"), value + 1);
return make_message(atom("ping"), value + 1);
}
);
}
......@@ -52,7 +52,7 @@ behavior ping(event_based_actor* self, size_t num_pings) {
behavior pong() {
return {
on(atom("ping"), arg_match) >> [](int32_t value) {
return make_any_tuple(atom("pong"), value);
return make_message(atom("pong"), value);
}
};
}
......
......@@ -27,7 +27,7 @@
#include "cppa/atom.hpp"
#include "cppa/config.hpp"
#include "cppa/logging.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/singletons.hpp"
#include "cppa/actor_addr.hpp"
#include "cppa/abstract_actor.hpp"
......@@ -67,7 +67,7 @@ bool abstract_actor::link_to_impl(const actor_addr& other) {
// send exit message if already exited
if (exited()) {
ptr->enqueue({address(), ptr},
make_any_tuple(exit_msg{address(), exit_reason()}),
make_message(exit_msg{address(), exit_reason()}),
m_host);
}
// add link if not already linked to other
......@@ -151,7 +151,7 @@ bool abstract_actor::establish_backlink(const actor_addr& other) {
if (reason != exit_reason::not_exited) {
auto ptr = detail::raw_access::unsafe_cast(other);
ptr->enqueue({address(), ptr},
make_any_tuple(exit_msg{address(), exit_reason()}),
make_message(exit_msg{address(), exit_reason()}),
m_host);
}
return false;
......@@ -202,7 +202,7 @@ void abstract_actor::cleanup(std::uint32_t reason) {
<< " attached functors; exit reason = " << reason
<< ", class = " << detail::demangle(typeid(*this)));
// send exit messages
auto msg = make_any_tuple(exit_msg{address(), reason});
auto msg = make_message(exit_msg{address(), reason});
CPPA_LOGM_DEBUG("cppa::actor", "send EXIT to " << mlinks.size() << " links");
for (auto& aptr : mlinks) {
aptr->enqueue({address(), aptr, message_id{}.with_high_priority()},
......
......@@ -19,7 +19,7 @@
#include "cppa/cppa.hpp"
#include "cppa/abstract_group.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/singletons.hpp"
#include "cppa/util/shared_spinlock.hpp"
#include "cppa/util/shared_lock_guard.hpp"
......@@ -81,7 +81,7 @@ void publish_local_groups(std::uint16_t port, const char* addr) {
}
catch (std::exception&) {
gn->enqueue({invalid_actor_addr, nullptr},
make_any_tuple(atom("SHUTDOWN")),
make_message(atom("SHUTDOWN")),
nullptr);
throw;
}
......
......@@ -35,7 +35,7 @@ void actor_companion::on_enqueue(enqueue_handler handler) {
m_on_enqueue = std::move(handler);
}
void actor_companion::enqueue(msg_hdr_cref hdr, any_tuple ct, execution_unit*) {
void actor_companion::enqueue(msg_hdr_cref hdr, message ct, execution_unit*) {
message_pointer ptr;
ptr.reset(detail::memory::create<mailbox_element>(hdr, std::move(ct)));
util::shared_lock_guard<lock_type> guard(m_lock);
......
......@@ -22,7 +22,7 @@
#include "cppa/atom.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/singletons.hpp"
#include "cppa/actor_proxy.hpp"
......
......@@ -18,7 +18,7 @@
#include "cppa/behavior.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
namespace cppa {
......@@ -45,18 +45,14 @@ class continuation_decorator : public detail::behavior_impl {
return none;
}
bhvr_invoke_result invoke(any_tuple& tup) {
bhvr_invoke_result invoke(message& tup) {
return invoke_impl(tup);
}
bhvr_invoke_result invoke(const any_tuple& tup) {
bhvr_invoke_result invoke(const message& tup) {
return invoke_impl(tup);
}
bool defined_at(const any_tuple& tup) {
return m_decorated->defined_at(tup);
}
pointer copy(const generic_timeout_definition& tdef) const {
return new continuation_decorator(m_fun, m_decorated->copy(tdef));
}
......@@ -71,7 +67,7 @@ class continuation_decorator : public detail::behavior_impl {
};
} // namespace <anonymous>
behavior::behavior(const partial_function& fun) : m_impl(fun.m_impl) { }
behavior::behavior(const message_handler& fun) : m_impl(fun.m_impl) { }
behavior behavior::add_continuation(continuation_fun fun) {
return behavior::impl_ptr{new continuation_decorator(std::move(fun),
......
......@@ -70,7 +70,7 @@ class broker::continuation {
public:
continuation(broker_ptr ptr, msg_hdr_cref hdr, any_tuple&& msg)
continuation(broker_ptr ptr, msg_hdr_cref hdr, message&& msg)
: m_self(move(ptr)), m_hdr(hdr), m_data(move(msg)) { }
inline void operator()() {
......@@ -83,7 +83,7 @@ class broker::continuation {
broker_ptr m_self;
message_header m_hdr;
any_tuple m_data;
message m_data;
};
......@@ -125,7 +125,7 @@ class broker::servant : public continuable {
}
}
virtual any_tuple disconnect_message() = 0;
virtual message disconnect_message() = 0;
bool m_disconnected;
......@@ -216,9 +216,9 @@ class broker::scribe : public extend<broker::servant>::with<buffered_writing> {
protected:
any_tuple disconnect_message() override {
message disconnect_message() override {
auto hdl = connection_handle::from_int(m_in->read_handle());
return make_any_tuple(connection_closed_msg{hdl});
return make_message(connection_closed_msg{hdl});
}
private:
......@@ -270,9 +270,9 @@ class broker::doorman : public broker::servant {
protected:
any_tuple disconnect_message() override {
message disconnect_message() override {
auto hdl = accept_handle::from_int(m_ptr->file_handle());
return make_any_tuple(acceptor_closed_msg{hdl});
return make_message(acceptor_closed_msg{hdl});
}
private:
......@@ -285,7 +285,7 @@ class broker::doorman : public broker::servant {
// avoid weak-vtables warning by providing dtor out-of-line
broker::doorman::~doorman() { }
void broker::invoke_message(msg_hdr_cref hdr, any_tuple msg) {
void broker::invoke_message(msg_hdr_cref hdr, message msg) {
CPPA_LOG_TRACE(CPPA_TARG(msg, to_string));
if (planned_exit_reason() != exit_reason::not_exited || bhvr_stack().empty()) {
CPPA_LOG_DEBUG("actor already finished execution"
......@@ -372,7 +372,7 @@ bool broker::invoke_message_from_cache() {
return false;
}
void broker::enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit*) {
void broker::enqueue(msg_hdr_cref hdr, message msg, execution_unit*) {
get_middleman()->run_later(continuation{this, hdr, move(msg)});
}
......@@ -441,7 +441,7 @@ broker_ptr init_and_launch(broker_ptr ptr) {
}
);
ptr->enqueue({invalid_actor_addr, ptr},
make_any_tuple(atom("INITMSG")),
make_message(atom("INITMSG")),
nullptr);
return ptr;
}
......
......@@ -19,7 +19,7 @@
#include "cppa/actor.hpp"
#include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/detail/raw_access.hpp"
......
......@@ -19,7 +19,7 @@
#include "cppa/group.hpp"
#include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/singletons.hpp"
#include "cppa/detail/group_manager.hpp"
......
......@@ -27,7 +27,7 @@
#include "cppa/cppa.hpp"
#include "cppa/group.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/message_header.hpp"
......@@ -60,7 +60,7 @@ class local_group : public abstract_group {
public:
void send_all_subscribers(msg_hdr_cref hdr, const any_tuple& msg,
void send_all_subscribers(msg_hdr_cref hdr, const message& msg,
execution_unit* eu) {
CPPA_LOG_TRACE(CPPA_TARG(hdr.sender, to_string) << ", "
<< CPPA_TARG(msg, to_string));
......@@ -70,7 +70,7 @@ class local_group : public abstract_group {
}
}
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit* eu) override {
void enqueue(msg_hdr_cref hdr, message msg, execution_unit* eu) override {
CPPA_LOG_TRACE(CPPA_TARG(hdr, to_string) << ", "
<< CPPA_TARG(msg, to_string));
send_all_subscribers(hdr, msg, eu);
......@@ -146,7 +146,7 @@ class local_broker : public event_based_actor {
demonitor(other);
}
},
on(atom("FORWARD"), arg_match) >> [=](const any_tuple& what) {
on(atom("FORWARD"), arg_match) >> [=](const message& what) {
CPPA_LOGC_TRACE("cppa::local_broker", "init$FORWARD",
CPPA_TARG(what, to_string));
// local forwarding
......@@ -179,7 +179,7 @@ class local_broker : public event_based_actor {
private:
void send_to_acquaintances(const any_tuple& what) {
void send_to_acquaintances(const message& what) {
// send to all remote subscribers
auto sender = last_sender();
CPPA_LOG_DEBUG("forward message to " << m_acquaintances.size()
......@@ -240,9 +240,9 @@ class local_group_proxy : public local_group {
}
}
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit* eu) override {
void enqueue(msg_hdr_cref hdr, message msg, execution_unit* eu) override {
// forward message to the broker
m_broker->enqueue(hdr, make_any_tuple(atom("FORWARD"), move(msg)), eu);
m_broker->enqueue(hdr, make_message(atom("FORWARD"), move(msg)), eu);
}
private:
......@@ -369,7 +369,7 @@ class remote_group : public abstract_group {
CPPA_LOG_ERROR("should never be called");
}
void enqueue(msg_hdr_cref hdr, any_tuple msg, execution_unit* eu) override {
void enqueue(msg_hdr_cref hdr, message msg, execution_unit* eu) override {
CPPA_LOG_TRACE("");
m_decorated->enqueue(hdr, std::move(msg), eu);
}
......@@ -380,7 +380,7 @@ class remote_group : public abstract_group {
CPPA_LOG_TRACE("");
group_down_msg gdm{group{this}};
m_decorated->send_all_subscribers({invalid_actor_addr, nullptr},
make_any_tuple(gdm), nullptr);
make_message(gdm), nullptr);
}
private:
......
......@@ -46,7 +46,7 @@ class down_observer : public attachable {
void actor_exited(std::uint32_t reason) {
auto ptr = detail::raw_access::get(m_observer);
message_header hdr{m_observed, ptr, message_id{}.with_high_priority()};
hdr.deliver(make_any_tuple(down_msg{m_observed, reason}));
hdr.deliver(make_message(down_msg{m_observed, reason}));
}
bool matches(const attachable::token& match_token) {
......@@ -104,7 +104,7 @@ std::vector<group> local_actor::joined_groups() const {
return result;
}
void local_actor::reply_message(any_tuple&& what) {
void local_actor::reply_message(message&& what) {
auto& whom = m_current_node->sender;
if (!whom) return;
auto& id = m_current_node->mid;
......@@ -130,7 +130,7 @@ void local_actor::forward_message(const actor& dest, message_priority prio) {
m_current_node->mid = message_id::invalid;
}
void local_actor::send_tuple(message_priority prio, const channel& dest, any_tuple what) {
void local_actor::send_tuple(message_priority prio, const channel& dest, message what) {
if (!dest) return;
message_id id;
if (prio == message_priority::high) id = id.with_high_priority();
......@@ -144,7 +144,7 @@ void local_actor::send_exit(const actor_addr& whom, std::uint32_t reason) {
void local_actor::delayed_send_tuple(message_priority prio,
const channel& dest,
const util::duration& rel_time,
cppa::any_tuple msg) {
cppa::message msg) {
message_id mid;
if (prio == message_priority::high) mid = mid.with_high_priority();
get_scheduling_coordinator()->delayed_send({address(), dest, mid},
......@@ -173,7 +173,7 @@ void local_actor::quit(std::uint32_t reason) {
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp,
const actor& dest,
const util::duration& rtime,
any_tuple&& what) {
message&& what) {
if (!dest) {
throw std::invalid_argument("cannot send synchronous message "
"to invalid_actor");
......@@ -183,13 +183,13 @@ message_id local_actor::timed_sync_send_tuple_impl(message_priority mp,
dest->enqueue({address(), dest, nri}, std::move(what), m_host);
auto rri = nri.response_id();
get_scheduling_coordinator()->delayed_send({address(), this, rri}, rtime,
make_any_tuple(sync_timeout_msg{}));
make_message(sync_timeout_msg{}));
return rri;
}
message_id local_actor::sync_send_tuple_impl(message_priority mp,
const actor& dest,
any_tuple&& what) {
message&& what) {
if (!dest) {
throw std::invalid_argument("cannot send synchronous message "
"to invalid_actor");
......@@ -204,7 +204,7 @@ void anon_send_exit(const actor_addr& whom, std::uint32_t reason) {
if (!whom) return;
auto ptr = detail::raw_access::get(whom);
ptr->enqueue({invalid_actor_addr, ptr, message_id{}.with_high_priority()},
make_any_tuple(exit_msg{invalid_actor_addr, reason}), nullptr);
make_message(exit_msg{invalid_actor_addr, reason}), nullptr);
}
} // namespace cppa
......@@ -21,7 +21,7 @@
namespace cppa {
mailbox_element::mailbox_element(msg_hdr_cref hdr, any_tuple data)
mailbox_element::mailbox_element(msg_hdr_cref hdr, message data)
: next(nullptr), marked(false), sender(hdr.sender)
, msg(std::move(data)), mid(hdr.id) { }
......
......@@ -20,6 +20,7 @@
#include <vector>
#include <string>
#include <sstream>
#include "cppa/match.hpp"
using namespace std;
......@@ -27,13 +28,13 @@ using namespace std;
namespace cppa {
detail::match_helper match_split(const std::string& str, char delim, bool keep_empties) {
vector<string> result;
message_builder result;
stringstream strs(str);
string tmp;
while (getline(strs, tmp, delim)) {
if (!tmp.empty() && !keep_empties) result.push_back(std::move(tmp));
if (!tmp.empty() && !keep_empties) result.append(std::move(tmp));
}
return match(any_tuple::view(std::move(result)));
return result.to_message();
}
} // namespace cppa
......@@ -16,63 +16,78 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#include "cppa/message.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/singletons.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa {
any_tuple::any_tuple(detail::abstract_tuple* ptr) : m_vals(ptr) { }
message::message(detail::message_data* ptr) : m_vals(ptr) {}
any_tuple::any_tuple(any_tuple&& other) : m_vals(std::move(other.m_vals)) { }
message::message(message&& other) : m_vals(std::move(other.m_vals)) {}
any_tuple::any_tuple(const data_ptr& vals) : m_vals(vals) { }
message::message(const data_ptr& vals) : m_vals(vals) {}
any_tuple& any_tuple::operator=(any_tuple&& other) {
message& message::operator=(message&& other) {
m_vals.swap(other.m_vals);
return *this;
}
void any_tuple::reset() {
m_vals.reset();
}
void message::reset() { m_vals.reset(); }
void* any_tuple::mutable_at(size_t p) {
CPPA_REQUIRE(m_vals != nullptr);
void* message::mutable_at(size_t p) {
CPPA_REQUIRE(m_vals);
return m_vals->mutable_at(p);
}
const void* any_tuple::at(size_t p) const {
CPPA_REQUIRE(m_vals != nullptr);
const void* message::at(size_t p) const {
CPPA_REQUIRE(m_vals);
return m_vals->at(p);
}
const uniform_type_info* any_tuple::type_at(size_t p) const {
CPPA_REQUIRE(m_vals != nullptr);
const uniform_type_info* message::type_at(size_t p) const {
CPPA_REQUIRE(m_vals);
return m_vals->type_at(p);
}
bool any_tuple::equals(const any_tuple& other) const {
CPPA_REQUIRE(m_vals != nullptr);
bool message::equals(const message& other) const {
CPPA_REQUIRE(m_vals);
return m_vals->equals(*other.vals());
}
any_tuple any_tuple::drop(size_t n) const {
CPPA_REQUIRE(m_vals != nullptr);
message message::drop(size_t n) const {
CPPA_REQUIRE(m_vals);
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
return any_tuple{detail::decorated_tuple::create(m_vals, n)};
if (n >= size()) return message{};
return message{detail::decorated_tuple::create(m_vals, n)};
}
any_tuple any_tuple::drop_right(size_t n) const {
CPPA_REQUIRE(m_vals != nullptr);
using namespace std;
message message::drop_right(size_t n) const {
CPPA_REQUIRE(m_vals);
if (n == 0) return *this;
if (n >= size()) return any_tuple{};
vector<size_t> mapping(size() - n);
if (n >= size()) return message{};
std::vector<size_t> mapping(size() - n);
size_t i = 0;
generate(mapping.begin(), mapping.end(), [&] { return i++; });
return any_tuple{detail::decorated_tuple::create(m_vals, move(mapping))};
std::generate(mapping.begin(), mapping.end(), [&] { return i++; });
return message{detail::decorated_tuple::create(m_vals, std::move(mapping))};
}
optional<message> message::apply(message_handler handler) {
return handler(*this);
}
bool message::apply_iterative(message_handler handler) {
if (empty()) return true;
for (size_t chunk_size = 1; chunk_size <= size(); ++chunk_size) {
auto chunk = take(chunk_size);
auto remainder = drop(chunk_size);
if (handler(chunk)) {
return remainder.empty() ? true
: remainder.apply_iterative(std::move(handler));
}
}
return false;
}
} // namespace cppa
......@@ -16,76 +16,77 @@
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#include <vector>
#ifndef CPPA_DETAIL_CONTAINER_TUPLE_VIEW_HPP
#define CPPA_DETAIL_CONTAINER_TUPLE_VIEW_HPP
#include <iostream>
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/disablable_delete.hpp"
#include "cppa/message_builder.hpp"
#include "cppa/message_handler.hpp"
#include "cppa/uniform_type_info.hpp"
namespace cppa {
namespace detail {
template<class Container>
class container_tuple_view : public abstract_tuple {
namespace {
typedef abstract_tuple super;
class dynamic_msg_data : public detail::message_data {
typedef typename Container::difference_type difference_type;
typedef message_data super;
public:
typedef typename Container::value_type value_type;
using message_data::const_iterator;
container_tuple_view(Container* c, bool take_ownership = false)
: super(true), m_ptr(c) {
CPPA_REQUIRE(c != nullptr);
if (!take_ownership) m_ptr.get_deleter().disable();
dynamic_msg_data(const dynamic_msg_data& other) : super(true) {
for (auto& d : other.m_data) {
m_data.push_back(d->copy());
}
size_t size() const override {
return m_ptr->size();
}
abstract_tuple* copy() const override {
return new container_tuple_view{new Container(*m_ptr), true};
}
dynamic_msg_data(std::vector<uniform_value>&& data)
: super(true), m_data(std::move(data)) {}
const void* at(size_t pos) const override {
CPPA_REQUIRE(pos < size());
CPPA_REQUIRE(static_cast<difference_type>(pos) >= 0);
auto i = m_ptr->cbegin();
std::advance(i, static_cast<difference_type>(pos));
return &(*i);
return m_data[pos]->val;
}
void* mutable_at(size_t pos) override {
CPPA_REQUIRE(pos < size());
CPPA_REQUIRE(static_cast<difference_type>(pos) >= 0);
auto i = m_ptr->begin();
std::advance(i, static_cast<difference_type>(pos));
return &(*i);
return m_data[pos]->val;
}
const uniform_type_info* type_at(size_t) const override {
return static_types_array<value_type>::arr[0];
size_t size() const override { return m_data.size(); }
dynamic_msg_data* copy() const override {
return new dynamic_msg_data(*this);
}
const uniform_type_info* type_at(size_t pos) const override {
CPPA_REQUIRE(pos < size());
return m_data[pos]->ti;
}
const std::string* tuple_type_names() const override {
static std::string result = demangle<value_type>();
return &result;
return nullptr; // get_tuple_type_names(*this);
}
private:
std::unique_ptr<Container, disablable_delete> m_ptr;
std::vector<uniform_value> m_data;
};
} // namespace detail
} // namespace cppa
} // namespace <anonymous>
message_builder& message_builder::append(uniform_value what) {
m_elements.push_back(std::move(what));
return *this;
}
#endif // CPPA_DETAIL_CONTAINER_TUPLE_VIEW_HPP
message message_builder::to_message() {
return message{new dynamic_msg_data(std::move(m_elements))};
}
optional<message> message_builder::apply(message_handler handler) {
return to_message().apply(std::move(handler));
}
} // namespace cppa
......@@ -20,11 +20,11 @@
#include "cppa/to_string.hpp"
#include "cppa/config.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/message_handler.hpp"
namespace cppa {
partial_function::partial_function(impl_ptr ptr) : m_impl(std::move(ptr)) { }
message_handler::message_handler(impl_ptr ptr) : m_impl(std::move(ptr)) { }
void detail::behavior_impl::handle_timeout() { }
......@@ -33,15 +33,15 @@ void detail::behavior_impl::handle_timeout() { }
namespace cppa {
namespace detail {
behavior_impl_ptr combine(behavior_impl_ptr lhs, const partial_function& rhs) {
behavior_impl_ptr combine(behavior_impl_ptr lhs, const message_handler& rhs) {
return lhs->or_else(rhs.as_behavior_impl());
}
behavior_impl_ptr combine(const partial_function& lhs, behavior_impl_ptr rhs) {
behavior_impl_ptr combine(const message_handler& lhs, behavior_impl_ptr rhs) {
return lhs.as_behavior_impl()->or_else(rhs);
}
behavior_impl_ptr extract(const partial_function& arg) {
behavior_impl_ptr extract(const message_handler& arg) {
return arg.as_behavior_impl();
}
......
......@@ -17,7 +17,7 @@
\******************************************************************************/
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/message_header.hpp"
namespace cppa {
......@@ -37,7 +37,7 @@ bool operator!=(const message_header& lhs, const message_header& rhs) {
return !(lhs == rhs);
}
void message_header::deliver(any_tuple msg) const {
void message_header::deliver(message msg) const {
if (receiver) receiver->enqueue(*this, std::move(msg), nullptr);
}
......
......@@ -221,7 +221,7 @@ class middleman_impl : public middleman {
void deliver(const node_id& node,
msg_hdr_cref hdr,
any_tuple msg ) override {
message msg ) override {
auto& entry = m_peers[node];
if (entry.impl) {
CPPA_REQUIRE(entry.queue != nullptr);
......@@ -295,7 +295,7 @@ class middleman_impl : public middleman {
const node_id& node) {
deliver(node,
{invalid_actor_addr, nullptr},
make_any_tuple(atom("MONITOR"),
make_message(atom("MONITOR"),
m_node,
aid));
});
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#include "cppa/detail/object_array.hpp"
namespace cppa {
namespace detail {
object_array::object_array() : super(true) {
// nop
}
object_array::object_array(const object_array& other) : super(true) {
m_elements.reserve(other.m_elements.size());
for (auto& e : other.m_elements) m_elements.push_back(e->copy());
}
object_array::~object_array() {
// nop
}
void object_array::push_back(uniform_value what) {
CPPA_REQUIRE(what && what->val != nullptr && what->ti != nullptr);
m_elements.push_back(std::move(what));
}
void* object_array::mutable_at(size_t pos) {
CPPA_REQUIRE(pos < size());
return m_elements[pos]->val;
}
size_t object_array::size() const {
return m_elements.size();
}
object_array* object_array::copy() const {
return new object_array(*this);
}
const void* object_array::at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_elements[pos]->val;
}
const uniform_type_info* object_array::type_at(size_t pos) const {
CPPA_REQUIRE(pos < size());
return m_elements[pos]->ti;
}
const std::string* object_array::tuple_type_names() const {
return nullptr; // get_tuple_type_names(*this);
}
} // namespace util
} // namespace cppa
......@@ -22,11 +22,21 @@
#include "cppa/opt.hpp"
using namespace std;
using cppa::placeholders::_x1;
namespace cppa {
detail::opt1_rvalue_builder<true> on_opt1(char short_opt,
using string_proj = function<optional<string> (const string&)>;
string_proj extract_longopt_arg(const string& prefix) {
return [prefix](const string& arg) -> optional<string> {
if (arg.compare(0, prefix.size(), prefix)) {
return string(arg.begin() + prefix.size(), arg.end());
}
return none;
};
}
opt_rvalue_builder on_opt1(char short_opt,
string long_opt,
options_description* desc,
string help_text,
......@@ -53,11 +63,11 @@ detail::opt1_rvalue_builder<true> on_opt1(char short_opt,
opts.push_back(lhs_str);
opts.push_back("--" + long_opt);
opts.push_back("-" + long_opt);
return {short_opt, long_opt, on<string, string>().when(_x1.in(opts)), on(kvp)};
return on(extract_longopt_arg(prefix)) || on(lhs_str, val<string>);
//return {short_opt, long_opt, on<string, string>().when(_x1.in(opts)), on(kvp)};
}
decltype(on<string>().when(_x1.in(vector<string>())))
on_opt0(char short_opt,
opt0_rvalue_builder on_opt0(char short_opt,
string long_opt,
options_description* desc,
string help_text,
......@@ -67,10 +77,8 @@ on_opt0(char short_opt,
(*desc)[help_group].insert(make_pair(make_pair(short_opt, long_opt), move(oinf)));
}
const char short_flag_arr[] = {'-', short_opt, '\0' };
vector<string> opt_strs = { short_flag_arr };
opt_strs.push_back("-" + long_opt);
opt_strs.push_back("--" + move(long_opt));
return on<string>().when(_x1.in(move(opt_strs)));
string short_opt_string = short_flag_arr;
return on(long_opt) || on(short_opt_string);
}
function<void()> print_desc(options_description* desc, ostream& out) {
......
......@@ -63,7 +63,7 @@ peer::peer(middleman* parent,
// in this case, this peer must be erased if no proxy of it remains
m_stop_on_last_proxy_exited = m_state == wait_for_msg_size;
m_meta_hdr = uniform_typeid<message_header>();
m_meta_msg = uniform_typeid<any_tuple>();
m_meta_msg = uniform_typeid<message>();
}
void peer::io_failed(event_bitmask mask) {
......@@ -133,7 +133,7 @@ continue_reading_result peer::continue_reading() {
case read_message: {
//DEBUG("peer_connection::continue_reading: read_message");
message_header hdr;
any_tuple msg;
message msg;
binary_deserializer bd(m_rd_buf.data(), m_rd_buf.size(),
&(parent()->get_namespace()), &m_incoming_types);
try {
......@@ -208,7 +208,7 @@ void peer::monitor(const actor_addr&,
// this actor already finished execution;
// reply with KILL_PROXY message
// get corresponding peer
enqueue(make_any_tuple(atom("KILL_PROXY"), pself, aid, entry.second));
enqueue(make_message(atom("KILL_PROXY"), pself, aid, entry.second));
}
}
else {
......@@ -220,7 +220,7 @@ void peer::monitor(const actor_addr&,
"monitor$kill_proxy_helper",
"reason = " << reason);
auto p = mm->get_peer(*node);
if (p) p->enqueue(make_any_tuple(atom("KILL_PROXY"), pself, aid, reason));
if (p) p->enqueue(make_message(atom("KILL_PROXY"), pself, aid, reason));
});
});
}
......@@ -256,7 +256,7 @@ void peer::kill_proxy(const actor_addr& sender,
}
}
void peer::deliver(msg_hdr_cref hdr, any_tuple msg) {
void peer::deliver(msg_hdr_cref hdr, message msg) {
CPPA_LOG_TRACE("");
if (hdr.sender && hdr.sender.is_remote()) {
// is_remote() is guaranteed to return true if and only if
......@@ -347,11 +347,11 @@ void peer::add_type_if_needed(const std::string& tname) {
auto imap = get_uniform_type_info_map();
auto uti = imap->by_uniform_name(tname);
m_outgoing_types.emplace(id, uti);
enqueue_impl({invalid_actor_addr, nullptr}, make_any_tuple(atom("ADD_TYPE"), id, tname));
enqueue_impl({invalid_actor_addr, nullptr}, make_message(atom("ADD_TYPE"), id, tname));
}
}
void peer::enqueue_impl(msg_hdr_cref hdr, const any_tuple& msg) {
void peer::enqueue_impl(msg_hdr_cref hdr, const message& msg) {
CPPA_LOG_TRACE("");
auto tname = msg.tuple_type_names();
add_type_if_needed((tname) ? *tname : detail::get_tuple_type_names(*msg.vals()));
......@@ -372,7 +372,7 @@ void peer::enqueue_impl(msg_hdr_cref hdr, const any_tuple& msg) {
memcpy(wbuf.offset_data(before), &size, sizeof(std::uint32_t));
}
void peer::enqueue(msg_hdr_cref hdr, const any_tuple& msg) {
void peer::enqueue(msg_hdr_cref hdr, const message& msg) {
enqueue_impl(hdr, msg);
register_for_writing();
}
......
......@@ -73,7 +73,7 @@ remote_actor_proxy::~remote_actor_proxy() {
});
}
void remote_actor_proxy::deliver(msg_hdr_cref hdr, any_tuple msg) {
void remote_actor_proxy::deliver(msg_hdr_cref hdr, message msg) {
// this member function is exclusively called from default_peer from inside
// the middleman's thread, therefore we can safely access
// m_pending_requests here
......@@ -87,7 +87,7 @@ void remote_actor_proxy::deliver(msg_hdr_cref hdr, any_tuple msg) {
hdr.deliver(std::move(msg));
}
void remote_actor_proxy::forward_msg(msg_hdr_cref hdr, any_tuple msg) {
void remote_actor_proxy::forward_msg(msg_hdr_cref hdr, message msg) {
CPPA_LOG_TRACE(CPPA_ARG(m_id) << ", " << CPPA_TSARG(hdr)
<< ", " << CPPA_TSARG(msg));
if (hdr.receiver != this) {
......@@ -129,7 +129,7 @@ void remote_actor_proxy::forward_msg(msg_hdr_cref hdr, any_tuple msg) {
});
}
void remote_actor_proxy::enqueue(msg_hdr_cref hdr, any_tuple msg,
void remote_actor_proxy::enqueue(msg_hdr_cref hdr, message msg,
execution_unit*) {
CPPA_REQUIRE(m_parent != nullptr);
CPPA_LOG_TRACE(CPPA_TARG(hdr, to_string)
......@@ -166,21 +166,21 @@ void remote_actor_proxy::link_to(const actor_addr& other) {
if (link_to_impl(other)) {
// causes remote actor to link to (proxy of) other
// receiving peer will call: this->local_link_to(other)
forward_msg({address(), this}, make_any_tuple(atom("LINK"), other));
forward_msg({address(), this}, make_message(atom("LINK"), other));
}
}
void remote_actor_proxy::unlink_from(const actor_addr& other) {
if (unlink_from_impl(other)) {
// causes remote actor to unlink from (proxy of) other
forward_msg({address(), this}, make_any_tuple(atom("UNLINK"), other));
forward_msg({address(), this}, make_message(atom("UNLINK"), other));
}
}
bool remote_actor_proxy::establish_backlink(const actor_addr& other) {
if (super::establish_backlink(other)) {
// causes remote actor to unlink from (proxy of) other
forward_msg({address(), this}, make_any_tuple(atom("LINK"), other));
forward_msg({address(), this}, make_message(atom("LINK"), other));
return true;
}
return false;
......@@ -189,7 +189,7 @@ bool remote_actor_proxy::establish_backlink(const actor_addr& other) {
bool remote_actor_proxy::remove_backlink(const actor_addr& other) {
if (super::remove_backlink(other)) {
// causes remote actor to unlink from (proxy of) other
forward_msg({address(), this}, make_any_tuple(atom("UNLINK"), other));
forward_msg({address(), this}, make_message(atom("UNLINK"), other));
return true;
}
return false;
......
......@@ -35,7 +35,7 @@ response_promise::response_promise(const actor_addr& from,
CPPA_REQUIRE(id.is_response() || !id.valid());
}
void response_promise::deliver(any_tuple msg) {
void response_promise::deliver(message msg) {
if (m_to) {
auto to = detail::raw_access::get(m_to);
auto from = detail::raw_access::get(m_from);
......
......@@ -64,7 +64,7 @@ class delayed_msg {
public:
delayed_msg(message_header&& arg1,
any_tuple&& arg2)
message&& arg2)
: hdr(move(arg1)), msg(move(arg2)) { }
delayed_msg(delayed_msg&&) = default;
......@@ -79,13 +79,13 @@ class delayed_msg {
private:
message_header hdr;
any_tuple msg;
message msg;
};
template<class Map>
inline void insert_dmsg(Map& storage, const util::duration& d,
message_header&& hdr, any_tuple&& tup) {
message_header&& hdr, message&& tup) {
auto tout = hrc::now();
tout += d;
delayed_msg dmsg{move(hdr), move(tup)};
......@@ -119,13 +119,13 @@ class timer_actor final : public detail::proper_actor<blocking_actor,
auto mfun = (
on(atom("SEND"), arg_match) >> [&](const util::duration& d,
message_header& hdr,
any_tuple& tup) {
message& tup) {
insert_dmsg(messages, d, move(hdr), move(tup));
},
on(atom("DIE")) >> [&] {
done = true;
},
others() >> [&]() {
others() >> [&] {
CPPA_LOG_WARNING("coordinator::timer_loop: UNKNOWN MESSAGE: "
<< to_string(msg_ptr->msg));
}
......@@ -175,7 +175,7 @@ void printer_loop(blocking_actor* self) {
}
};
bool running = true;
self->receive_while (gref(running)) (
self->receive_while ([&] { return running; }) (
on(atom("add"), arg_match) >> [&](std::string& str) {
auto s = self->last_sender();
if (!str.empty() && s) {
......@@ -285,7 +285,7 @@ void coordinator::destroy() {
}
// shutdown utility actors
CPPA_LOG_DEBUG("send 'DIE' messages to timer & printer");
auto msg = make_any_tuple(atom("DIE"));
auto msg = make_message(atom("DIE"));
m_timer->enqueue({invalid_actor_addr, nullptr}, msg, nullptr);
m_printer->enqueue({invalid_actor_addr, nullptr}, msg, nullptr);
CPPA_LOG_DEBUG("join threads of utility actors");
......
......@@ -23,7 +23,7 @@
#include "cppa/logging.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/exception.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/io/middleman.hpp"
......
......@@ -46,7 +46,7 @@ namespace cppa {
namespace {
bool isbuiltin(const string& type_name) {
return type_name == "@str" || type_name == "@atom" || type_name == "@tuple";
return type_name == "@str" || type_name == "@atom" || type_name == "@msg";
}
// serializes types as type_name(...) except:
......@@ -289,7 +289,7 @@ class string_deserializer : public deserializer {
type_name = "@atom";
}
else if (*m_pos == '{') {
type_name = "@tuple";
type_name = "@msg";
}
else {
auto substr_end = next_delimiter();
......
......@@ -39,7 +39,7 @@ void sync_request_bouncer::operator()(const actor_addr& sender,
if (sender && mid.is_request()) {
auto ptr = detail::raw_access::get(sender);
ptr->enqueue({invalid_actor_addr, ptr, mid.response_id()},
make_any_tuple(sync_exited_msg{sender, rsn}),
make_message(sync_exited_msg{sender, rsn}),
// TODO: this breaks out of the execution unit
nullptr);
}
......
......@@ -30,8 +30,8 @@
#include "cppa/actor.hpp"
#include "cppa/abstract_group.hpp"
#include "cppa/channel.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/message.hpp"
#include "cppa/message_header.hpp"
#include "cppa/util/algorithm.hpp"
......
......@@ -32,9 +32,9 @@
#include "cppa/atom.hpp"
#include "cppa/actor.hpp"
#include "cppa/logging.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp"
......
......@@ -28,9 +28,10 @@
#include "cppa/group.hpp"
#include "cppa/logging.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/message_header.hpp"
#include "cppa/abstract_group.hpp"
#include "cppa/message_builder.hpp"
#include "cppa/actor_namespace.hpp"
#include "cppa/util/duration.hpp"
......@@ -41,7 +42,6 @@
#include "cppa/util/shared_lock_guard.hpp"
#include "cppa/detail/raw_access.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/uniform_type_info_map.hpp"
#include "cppa/detail/default_uniform_type_info.hpp"
......@@ -55,7 +55,6 @@ namespace detail {
{ "cppa::acceptor_closed_msg", "@acceptor_closed" },
{ "cppa::actor", "@actor" },
{ "cppa::actor_addr", "@addr" },
{ "cppa::any_tuple", "@tuple" },
{ "cppa::atom_value", "@atom" },
{ "cppa::channel", "@channel" },
{ "cppa::connection_closed_msg", "@conn_closed" },
......@@ -66,6 +65,7 @@ namespace detail {
{ "cppa::intrusive_ptr<cppa::node_id>", "@proc" },
{ "cppa::io::accept_handle", "@ac_hdl" },
{ "cppa::io::connection_handle", "@cn_hdl" },
{ "cppa::message", "@msg" },
{ "cppa::message_header", "@header" },
{ "cppa::new_connection_msg", "@new_conn" },
{ "cppa::new_data_msg", "@new_data" },
......@@ -276,7 +276,7 @@ void deserialize_impl(channel& ptrref, deserializer* source) {
}
}
void serialize_impl(const any_tuple& tup, serializer* sink) {
void serialize_impl(const message& tup, serializer* sink) {
std::string dynamic_name; // used if tup holds an object_array
// ttn can be nullptr even if tuple is not empty (in case of object_array)
const std::string* ttn = tup.empty() ? nullptr : tup.tuple_type_names();
......@@ -301,12 +301,12 @@ void serialize_impl(const any_tuple& tup, serializer* sink) {
sink->end_object();
}
void deserialize_impl(any_tuple& atref, deserializer* source) {
void deserialize_impl(message& atref, deserializer* source) {
auto uti = source->begin_object();
auto uval = uti->create();
uti->deserialize(uval->val, source);
source->end_object();
atref = uti->as_any_tuple(uval->val);
atref = uti->as_message(uval->val);
}
void serialize_impl(msg_hdr_cref hdr, serializer* sink) {
......@@ -492,8 +492,8 @@ class uti_base : public uniform_type_info {
return create_impl<T>(other);
}
any_tuple as_any_tuple(void* instance) const override {
return make_any_tuple(deref(instance));
message as_message(void* instance) const override {
return make_message(deref(instance));
}
static inline const T& deref(const void* ptr) {
......@@ -580,8 +580,8 @@ class int_tinfo : public abstract_int_tinfo {
return static_name();
}
any_tuple as_any_tuple(void* instance) const override {
return make_any_tuple(deref(instance));
message as_message(void* instance) const override {
return make_message(deref(instance));
}
protected:
......@@ -637,8 +637,8 @@ class buffer_type_info_impl : public uniform_type_info {
return static_name();
}
any_tuple as_any_tuple(void* instance) const override {
return make_any_tuple(deref(instance));
message as_message(void* instance) const override {
return make_message(deref(instance));
}
protected:
......@@ -675,13 +675,13 @@ class buffer_type_info_impl : public uniform_type_info {
};
class default_meta_tuple : public uniform_type_info {
class default_meta_message : public uniform_type_info {
public:
default_meta_tuple(const std::string& name) {
default_meta_message(const std::string& name) {
m_name = name;
auto elements = util::split(name, '+', false);
std::vector<std::string> elements = util::split(name, '+');
auto uti_map = get_uniform_type_info_map();
CPPA_REQUIRE(elements.size() > 0 && elements.front() == "@<>");
// ignore first element, because it's always "@<>"
......@@ -694,17 +694,18 @@ class default_meta_tuple : public uniform_type_info {
}
uniform_value create(const uniform_value& other) const override {
auto res = create_impl<object_array>(other);
auto res = create_impl<message>(other);
if (!other) {
// res is not a copy => fill it with values
auto& oarr = *cast(res->val);
for (auto uti : m_elements) oarr.push_back(uti->create());
// res is not a copy => fill with values
message_builder mb;
for (auto& e : m_elements) mb.append(e->create());
*cast(res->val) = mb.to_message();
}
return res;
}
any_tuple as_any_tuple(void* ptr) const override {
return any_tuple{static_cast<any_tuple::raw_ptr>(cast(ptr))};
message as_message(void* ptr) const override {
return *cast(ptr);
}
const char* name() const override {
......@@ -712,17 +713,19 @@ class default_meta_tuple : public uniform_type_info {
}
void serialize(const void* ptr, serializer* sink) const override {
auto& oarr = *cast(ptr);
auto& msg = *cast(ptr);
CPPA_REQUIRE(msg.size() == m_elements.size());
for (size_t i = 0; i < m_elements.size(); ++i) {
m_elements[i]->serialize(oarr.at(i), sink);
m_elements[i]->serialize(msg.at(i), sink);
}
}
void deserialize(void* ptr, deserializer* source) const override {
auto& oarr = *cast(ptr);
message_builder mb;
for (size_t i = 0; i < m_elements.size(); ++i) {
m_elements[i]->deserialize(oarr.mutable_at(i), source);
mb.append(m_elements[i]->deserialize(source));
}
*cast(ptr) = mb.to_message();
}
bool equal_to(const std::type_info&) const override {
......@@ -741,12 +744,12 @@ class default_meta_tuple : public uniform_type_info {
std::string m_name;
std::vector<const uniform_type_info*> m_elements;
inline object_array* cast(void* ptr) const {
return reinterpret_cast<object_array*>(ptr);
inline message* cast(void* ptr) const {
return reinterpret_cast<message*>(ptr);
}
inline const object_array* cast(const void* ptr) const {
return reinterpret_cast<const object_array*>(ptr);
inline const message* cast(const void* ptr) const {
return reinterpret_cast<const message*>(ptr);
}
};
......@@ -845,7 +848,7 @@ class utim_impl : public uniform_type_info_map {
*i++ = &m_type_sync_exited; // @sync_exited
*i++ = &m_type_sync_timeout; // @sync_timeout
*i++ = &m_type_timeout; // @timeout
*i++ = &m_type_tuple; // @tuple
*i++ = &m_type_tuple; // @msg
*i++ = &m_type_u16; // @u16
*i++ = &m_type_u16str; // @u16str
*i++ = &m_type_u32; // @u32
......@@ -903,7 +906,7 @@ class utim_impl : public uniform_type_info_map {
}
if (!result && name.compare(0, 3, "@<>") == 0) {
// create tuple UTI on-the-fly
result = insert(create_unique<default_meta_tuple>(name));
result = insert(create_unique<default_meta_message>(name));
}
return result; //(res) ? res : find_name(m_user_types, name);
}
......@@ -963,7 +966,7 @@ class utim_impl : public uniform_type_info_map {
// 10-19
uti_impl<group_down_msg> m_type_group_down;
uti_impl<any_tuple> m_type_tuple;
uti_impl<message> m_type_tuple;
uti_impl<util::duration> m_type_duration;
uti_impl<sync_exited_msg> m_type_sync_exited;
uti_impl<sync_timeout_msg> m_type_sync_timeout;
......
......@@ -18,7 +18,7 @@ size_t s_pongs = 0;
behavior ping_behavior(local_actor* self, size_t num_pings) {
return (
on(atom("pong"), arg_match) >> [=](int value) -> any_tuple {
on(atom("pong"), arg_match) >> [=](int value) -> message {
if (!self->last_sender()) {
CPPA_PRINT("last_sender() invalid!");
}
......@@ -30,7 +30,7 @@ behavior ping_behavior(local_actor* self, size_t num_pings) {
self->send_exit(self->last_sender(), exit_reason::user_shutdown);
self->quit();
}
return make_any_tuple(atom("ping"), value);
return make_message(atom("ping"), value);
},
others() >> [=] {
CPPA_LOGF_ERROR("unexpected message; "
......@@ -42,9 +42,9 @@ behavior ping_behavior(local_actor* self, size_t num_pings) {
behavior pong_behavior(local_actor* self) {
return (
on(atom("ping"), arg_match) >> [](int value) -> any_tuple {
on(atom("ping"), arg_match) >> [](int value) -> message {
CPPA_PRINT("received {'ping', " << value << "}");
return make_any_tuple(atom("pong"), value + 1);
return make_message(atom("pong"), value + 1);
},
others() >> [=] {
CPPA_LOGF_ERROR("unexpected message; "
......
......@@ -33,7 +33,7 @@ const char* cppa_strip_path(const char* file) {
return res;
}
void cppa_unexpected_message(const char* file, size_t line, cppa::any_tuple t) {
void cppa_unexpected_message(const char* file, size_t line, cppa::message t) {
CPPA_PRINTERRC(file, line, "unexpected message: " << to_string(t));
}
......
......@@ -28,7 +28,7 @@ size_t cppa_error_count();
void cppa_inc_error_count();
std::string cppa_fill4(size_t value);
const char* cppa_strip_path(const char* file);
void cppa_unexpected_message(const char* file, size_t line, cppa::any_tuple t);
void cppa_unexpected_message(const char* file, size_t line, cppa::message t);
void cppa_unexpected_timeout(const char* file, size_t line);
#define CPPA_STREAMIFY(fname, line, message) \
......
......@@ -167,19 +167,19 @@ void test_gref() {
on<anything>().when(gref(enable_case1) == false) >> [] { return 1; },
on<anything>() >> [] { return 2; }
);
any_tuple expr19_tup = make_cow_tuple("hello guard!");
message expr19_tup = make_cow_tuple("hello guard!");
auto res19 = expr19(expr19_tup);
CPPA_CHECK(get<int>(&res19) && get<int>(res19) == 2);
partial_function expr20 = expr19;
message_handler expr20 = expr19;
enable_case1 = false;
CPPA_CHECK(expr20(expr19_tup) == make_any_tuple(1));
partial_function expr21 {
CPPA_CHECK(expr20(expr19_tup) == make_message(1));
message_handler expr21 {
on(atom("add"), arg_match) >> [](int a, int b) {
return a + b;
}
};
CPPA_CHECK(expr21(make_any_tuple(atom("add"), 1, 2)) == make_any_tuple(3));
CPPA_CHECK(!expr21(make_any_tuple(atom("sub"), 1, 2)));
CPPA_CHECK(expr21(make_message(atom("add"), 1, 2)) == make_message(3));
CPPA_CHECK(!expr21(make_message(atom("sub"), 1, 2)));
}
void test_match_function() {
......@@ -305,11 +305,11 @@ void test_behavior() {
last_invoked_fun = "<*>@4";
}
};
bhvr_check(bhvr1, make_any_tuple(42), true, "<int>@3");
bhvr_check(bhvr1, make_any_tuple(24), true, "<int>@1");
bhvr_check(bhvr1, make_any_tuple(2.f), true, "<float>@2");
bhvr_check(bhvr1, make_any_tuple(""), true, "<*>@4");
partial_function pf0 {
bhvr_check(bhvr1, make_message(42), true, "<int>@3");
bhvr_check(bhvr1, make_message(24), true, "<int>@1");
bhvr_check(bhvr1, make_message(2.f), true, "<float>@2");
bhvr_check(bhvr1, make_message(""), true, "<*>@4");
message_handler pf0 {
on<int, int>() >> [&] { last_invoked_fun = "<int, int>@1"; },
on<float>() >> [&] { last_invoked_fun = "<float>@2"; }
};
......@@ -317,24 +317,24 @@ void test_behavior() {
on<int, int>() >> [&] { last_invoked_fun = "<int, int>@3"; },
on<string>() >> [&] { last_invoked_fun = "<string>@4"; }
);
bhvr_check(pf0, make_any_tuple(1, 2), true, "<int, int>@1");
bhvr_check(pf1, make_any_tuple(1, 2), true, "<int, int>@1");
bhvr_check(pf0, make_any_tuple("hi"), false, "");
bhvr_check(pf1, make_any_tuple("hi"), true, "<string>@4");
partial_function pf11 {
bhvr_check(pf0, make_message(1, 2), true, "<int, int>@1");
bhvr_check(pf1, make_message(1, 2), true, "<int, int>@1");
bhvr_check(pf0, make_message("hi"), false, "");
bhvr_check(pf1, make_message("hi"), true, "<string>@4");
message_handler pf11 {
on_arg_match >> [&](int) { last_invoked_fun = "<int>@1"; }
};
partial_function pf12 {
message_handler pf12 {
on_arg_match >> [&](int) { last_invoked_fun = "<int>@2"; },
on_arg_match >> [&](float) { last_invoked_fun = "<float>@2"; }
};
auto pf13 = pf11.or_else(pf12);
bhvr_check(pf13, make_any_tuple(42), true, "<int>@1");
bhvr_check(pf13, make_any_tuple(42.24f), true, "<float>@2");
bhvr_check(pf13, make_message(42), true, "<int>@1");
bhvr_check(pf13, make_message(42.24f), true, "<float>@2");
}
void test_pattern_matching() {
auto res = match(make_any_tuple(42, 4.2f)) (
auto res = match(make_message(42, 4.2f)) (
on(42, arg_match) >> [](double d) {
return d;
},
......@@ -343,7 +343,7 @@ void test_pattern_matching() {
}
);
CPPA_CHECK(get<float>(&res) && util::safe_equal(get<float>(res), 4.2f));
auto res2 = match(make_any_tuple(23, 4.2f)) (
auto res2 = match(make_message(23, 4.2f)) (
on(42, arg_match) >> [](double d) {
return d;
},
......@@ -365,10 +365,10 @@ void make_dynamically_typed_impl(detail::object_array& arr, T0&& arg0, Ts&&... a
}
template<typename... Ts>
any_tuple make_dynamically_typed(Ts&&... args) {
message make_dynamically_typed(Ts&&... args) {
auto oarr = new detail::object_array;
make_dynamically_typed_impl(*oarr, std::forward<Ts>(args)...);
return any_tuple{static_cast<any_tuple::raw_ptr>(oarr)};
return message{static_cast<message::raw_ptr>(oarr)};
}
void test_wildcards() {
......@@ -382,88 +382,88 @@ void test_wildcards() {
CPPA_CHECK_NOT(expr0(1));
CPPA_CHECK(expr0(1, 2));
CPPA_CHECK(expr0(0, 1, 2));
partial_function pf0 = expr0;
CPPA_CHECK(not pf0(make_any_tuple(1)));
CPPA_CHECK(pf0(make_any_tuple(1, 2)));
CPPA_CHECK(pf0(make_any_tuple(0, 1, 2)));
message_handler pf0 = expr0;
CPPA_CHECK(not pf0(make_message(1)));
CPPA_CHECK(pf0(make_message(1, 2)));
CPPA_CHECK(pf0(make_message(0, 1, 2)));
CPPA_CHECK(not pf0(make_dynamically_typed(1)));
CPPA_CHECK(pf0(make_dynamically_typed(1, 2)));
CPPA_CHECK(pf0(make_dynamically_typed(0, 1, 2)));
behavior bhvr0 = expr0;
CPPA_CHECK(bhvr0(make_any_tuple(1, 2)));
CPPA_CHECK(bhvr0(make_any_tuple(0, 1, 2)));
CPPA_CHECK(bhvr0(make_message(1, 2)));
CPPA_CHECK(bhvr0(make_message(0, 1, 2)));
CPPA_CHECK(bhvr0(make_dynamically_typed(1, 2)));
CPPA_CHECK(bhvr0(make_dynamically_typed(0, 1, 2)));
// wildcard in between
partial_function pf1 {
message_handler pf1 {
on<int, anything, int>() >> [](int a, int b) {
CPPA_CHECK_EQUAL(a, 10);
CPPA_CHECK_EQUAL(b, 20);
}
};
CPPA_CHECK(pf1(make_any_tuple(10, 20)));
CPPA_CHECK(pf1(make_any_tuple(10, 15, 20)));
CPPA_CHECK(pf1(make_any_tuple(10, "hello world", 15, 20)));
CPPA_CHECK(pf1(make_message(10, 20)));
CPPA_CHECK(pf1(make_message(10, 15, 20)));
CPPA_CHECK(pf1(make_message(10, "hello world", 15, 20)));
CPPA_CHECK(pf1(make_dynamically_typed(10, 20)));
CPPA_CHECK(pf1(make_dynamically_typed(10, 15, 20)));
CPPA_CHECK(pf1(make_dynamically_typed(10, "hello world", 15, 20)));
// multiple wildcards: one leading
partial_function pf2 {
message_handler pf2 {
on<anything, int, anything, int>() >> [](int a, int b) {
CPPA_CHECK_EQUAL(a, 10);
CPPA_CHECK_EQUAL(b, 20);
}
};
CPPA_CHECK(pf2(make_any_tuple(10, 20)));
CPPA_CHECK(pf2(make_any_tuple(10, 15, 20)));
CPPA_CHECK(pf2(make_any_tuple(10, "hello world", 15, 20)));
CPPA_CHECK(pf2(make_any_tuple("hello world", 10, 20)));
CPPA_CHECK(pf2(make_any_tuple("hello", 10, "world", 15, 20)));
CPPA_CHECK(pf2(make_message(10, 20)));
CPPA_CHECK(pf2(make_message(10, 15, 20)));
CPPA_CHECK(pf2(make_message(10, "hello world", 15, 20)));
CPPA_CHECK(pf2(make_message("hello world", 10, 20)));
CPPA_CHECK(pf2(make_message("hello", 10, "world", 15, 20)));
CPPA_CHECK(pf2(make_dynamically_typed(10, 20)));
CPPA_CHECK(pf2(make_dynamically_typed(10, 15, 20)));
CPPA_CHECK(pf2(make_dynamically_typed(10, "hello world", 15, 20)));
CPPA_CHECK(pf2(make_dynamically_typed("hello world", 10, 20)));
CPPA_CHECK(pf2(make_dynamically_typed("hello", 10, "world", 15, 20)));
// multiple wildcards: in between
partial_function pf3 {
message_handler pf3 {
on<int, anything, int, anything, int>() >> [](int a, int b, int c) {
CPPA_CHECK_EQUAL(a, 10);
CPPA_CHECK_EQUAL(b, 20);
CPPA_CHECK_EQUAL(c, 30);
}
};
CPPA_CHECK(pf3(make_any_tuple(10, 20, 30)));
CPPA_CHECK(pf3(make_any_tuple(10, 20, 25, 30)));
CPPA_CHECK(pf3(make_any_tuple(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf3(make_any_tuple(10, "hello", 20, "world", 1, 2, 30)));
CPPA_CHECK(pf3(make_message(10, 20, 30)));
CPPA_CHECK(pf3(make_message(10, 20, 25, 30)));
CPPA_CHECK(pf3(make_message(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf3(make_message(10, "hello", 20, "world", 1, 2, 30)));
CPPA_CHECK(pf3(make_dynamically_typed(10, 20, 30)));
CPPA_CHECK(pf3(make_dynamically_typed(10, 20, 25, 30)));
CPPA_CHECK(pf3(make_dynamically_typed(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf3(make_dynamically_typed(10, "hello", 20, "world", 1, 2, 30)));
// multiple wildcards: one trailing
partial_function pf4 {
message_handler pf4 {
on<int, anything, int, anything>() >> [](int a, int b) {
CPPA_CHECK_EQUAL(a, 10);
CPPA_CHECK_EQUAL(b, 20);
}
};
CPPA_CHECK(pf4(make_any_tuple(10, 20, 30)));
CPPA_CHECK(pf4(make_any_tuple(10, 20, 25, 30)));
CPPA_CHECK(pf4(make_any_tuple(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf4(make_any_tuple(10, "hello", 20, "world", 1, 2, 30)));
CPPA_CHECK(pf4(make_message(10, 20, 30)));
CPPA_CHECK(pf4(make_message(10, 20, 25, 30)));
CPPA_CHECK(pf4(make_message(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf4(make_message(10, "hello", 20, "world", 1, 2, 30)));
CPPA_CHECK(pf4(make_dynamically_typed(10, 20, 30)));
CPPA_CHECK(pf4(make_dynamically_typed(10, 20, 25, 30)));
CPPA_CHECK(pf4(make_dynamically_typed(10, "hello", 20, "world", 30)));
CPPA_CHECK(pf4(make_dynamically_typed(10, "hello", 20, "world", 1, 2, 30)));
// multiple wildcards: leading and trailing
partial_function pf5 {
message_handler pf5 {
on<anything, int, anything>() >> [](int a) {
CPPA_CHECK_EQUAL(a, 10);
}
};
CPPA_CHECK(pf5(make_any_tuple(10, 20, 30)));
CPPA_CHECK(pf5(make_any_tuple("hello", 10, "world", 30)));
CPPA_CHECK(pf5(make_any_tuple("hello", "world", 10)));
CPPA_CHECK(pf5(make_message(10, 20, 30)));
CPPA_CHECK(pf5(make_message("hello", 10, "world", 30)));
CPPA_CHECK(pf5(make_message("hello", "world", 10)));
CPPA_CHECK(pf5(make_dynamically_typed(10, 20, 30)));
CPPA_CHECK(pf5(make_dynamically_typed("hello", 10, "world", 30)));
CPPA_CHECK(pf5(make_dynamically_typed("hello", "world", 10)));
......
......@@ -122,13 +122,13 @@ void spawn5_client(event_based_actor* self) {
CPPA_PRINT("received {'GetGroup'}");
return group::get("local", "foobar");
},
on(atom("Spawn5"), arg_match) >> [=](const group& grp) -> any_tuple {
on(atom("Spawn5"), arg_match) >> [=](const group& grp) -> message {
CPPA_PRINT("received {'Spawn5'}");
actor_vector vec;
for (int i = 0; i < 5; ++i) {
vec.push_back(spawn_in_group(grp, reflector));
}
return make_any_tuple(atom("ok"), std::move(vec));
return make_message(atom("ok"), std::move(vec));
},
on(atom("Spawn5Done")) >> [=] {
CPPA_PRINT("received {'Spawn5Done'}");
......@@ -216,7 +216,7 @@ class client : public event_based_actor {
void test_group_comm_inverted() {
CPPA_PRINT("test group communication via network (inverted setup)");
become (
on(atom("GClient")) >> [=]() -> any_tuple {
on(atom("GClient")) >> [=]() -> message {
CPPA_CHECKPOINT();
auto cptr = last_sender();
auto s5c = spawn<monitored>(spawn5_client);
......@@ -225,7 +225,7 @@ class client : public event_based_actor {
CPPA_CHECKPOINT();
quit();
});
return make_any_tuple(atom("GClient"), s5c);
return make_message(atom("GClient"), s5c);
}
);
}
......@@ -247,7 +247,7 @@ class server : public event_based_actor {
behavior await_spawn_ping() {
CPPA_PRINT("await {'SpawnPing'}");
return (
on(atom("SpawnPing")) >> [=]() -> any_tuple {
on(atom("SpawnPing")) >> [=]() -> message {
CPPA_PRINT("received {'SpawnPing'}");
auto client = last_sender();
if (!client) {
......@@ -260,7 +260,7 @@ class server : public event_based_actor {
CPPA_CHECK_EQUAL(pongs(), num_pings);
await_sync_msg();
});
return make_any_tuple(atom("PingPtr"), pptr);
return make_message(atom("PingPtr"), pptr);
}
);
}
......@@ -281,7 +281,7 @@ class server : public event_based_actor {
CPPA_PRINT("await foobars");
auto foobars = make_shared<int>(0);
become (
on(atom("foo"), atom("bar"), arg_match) >> [=](int i) -> any_tuple {
on(atom("foo"), atom("bar"), arg_match) >> [=](int i) -> message {
++*foobars;
if (i == 99) {
CPPA_CHECK_EQUAL(*foobars, 100);
......@@ -295,7 +295,7 @@ class server : public event_based_actor {
void test_group_comm() {
CPPA_PRINT("test group communication via network");
become (
on(atom("GClient")) >> [=]() -> any_tuple {
on(atom("GClient")) >> [=]() -> message {
CPPA_CHECKPOINT();
auto cptr = last_sender();
auto s5c = spawn<monitored>(spawn5_client);
......@@ -303,7 +303,7 @@ class server : public event_based_actor {
CPPA_CHECKPOINT();
test_group_comm_inverted(detail::raw_access::unsafe_cast(cptr));
});
return make_any_tuple(atom("GClient"), s5c);
return make_message(atom("GClient"), s5c);
}
);
}
......
......@@ -25,10 +25,10 @@
#include "test.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/announce.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/to_string.hpp"
#include "cppa/serializer.hpp"
#include "cppa/from_string.hpp"
......@@ -151,7 +151,7 @@ int main() {
oarr->push_back(object::from(static_cast<uint32_t>(42)));
oarr->push_back(object::from("foo" ));
any_tuple atuple1{static_cast<any_tuple::raw_ptr>(oarr)};
message atuple1{static_cast<message::raw_ptr>(oarr)};
try {
auto opt = tuple_cast<uint32_t, string>(atuple1);
CPPA_CHECK(opt.valid());
......@@ -204,29 +204,29 @@ int main() {
//try {
scoped_actor self;
auto ttup = make_any_tuple(1, 2, actor{self.get()});
auto ttup = make_message(1, 2, actor{self.get()});
util::buffer wr_buf;
binary_serializer bs(&wr_buf, &addressing);
bs << ttup;
binary_deserializer bd(wr_buf.data(), wr_buf.size(), &addressing);
any_tuple ttup2;
uniform_typeid<any_tuple>()->deserialize(&ttup2, &bd);
message ttup2;
uniform_typeid<message>()->deserialize(&ttup2, &bd);
CPPA_CHECK(ttup == ttup2);
//}
//catch (exception& e) { CPPA_FAILURE(to_verbose_string(e)); }
try {
scoped_actor self;
auto ttup = make_any_tuple(1, 2, actor{self.get()});
auto ttup = make_message(1, 2, actor{self.get()});
util::buffer wr_buf;
binary_serializer bs(&wr_buf, &addressing);
bs << ttup;
bs << ttup;
binary_deserializer bd(wr_buf.data(), wr_buf.size(), &addressing);
any_tuple ttup2;
any_tuple ttup3;
uniform_typeid<any_tuple>()->deserialize(&ttup2, &bd);
uniform_typeid<any_tuple>()->deserialize(&ttup3, &bd);
message ttup2;
message ttup3;
uniform_typeid<message>()->deserialize(&ttup2, &bd);
uniform_typeid<message>()->deserialize(&ttup3, &bd);
CPPA_CHECK(ttup == ttup2);
CPPA_CHECK(ttup == ttup3);
CPPA_CHECK(ttup2 == ttup3);
......@@ -240,8 +240,8 @@ int main() {
bs << atuple1;
// deserialize b2 from buf
binary_deserializer bd(wr_buf.data(), wr_buf.size(), &addressing);
any_tuple atuple2;
uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd);
message atuple2;
uniform_typeid<message>()->deserialize(&atuple2, &bd);
auto opt = tuple_cast<uint32_t, string>(atuple2);
CPPA_CHECK(opt.valid());
if (opt.valid()) {
......@@ -274,15 +274,15 @@ int main() {
// test serialization of enums
try {
auto enum_tuple = make_any_tuple(test_enum::b);
auto enum_tuple = make_message(test_enum::b);
// serialize b1 to buf
util::buffer wr_buf;
binary_serializer bs(&wr_buf, &addressing);
bs << enum_tuple;
// deserialize b2 from buf
binary_deserializer bd(wr_buf.data(), wr_buf.size(), &addressing);
any_tuple enum_tuple2;
uniform_typeid<any_tuple>()->deserialize(&enum_tuple2, &bd);
message enum_tuple2;
uniform_typeid<message>()->deserialize(&enum_tuple2, &bd);
auto opt = tuple_cast<test_enum>(enum_tuple2);
CPPA_CHECK(opt.valid());
if (opt.valid()) {
......
......@@ -254,7 +254,7 @@ class fixed_stack : public sb_actor<fixed_stack> {
behavior echo_actor(event_based_actor* self) {
return (
others() >> [=]() -> any_tuple {
others() >> [=]() -> message {
self->quit(exit_reason::normal);
return self->last_dequeued();
}
......@@ -268,7 +268,7 @@ struct simple_mirror : sb_actor<simple_mirror> {
simple_mirror() {
init_state = (
others() >> [=]() -> any_tuple {
others() >> [=]() -> message {
return last_dequeued();
}
);
......@@ -332,7 +332,7 @@ struct slave : event_based_actor {
void test_serial_reply() {
auto mirror_behavior = [=](event_based_actor* self) {
self->become(others() >> [=]() -> any_tuple {
self->become(others() >> [=]() -> message {
CPPA_PRINT("return self->last_dequeued()");
return self->last_dequeued();
});
......@@ -394,13 +394,13 @@ void test_serial_reply() {
void test_or_else() {
scoped_actor self;
partial_function handle_a {
message_handler handle_a {
on("a") >> [] { return 1; }
};
partial_function handle_b {
message_handler handle_b {
on("b") >> [] { return 2; }
};
partial_function handle_c {
message_handler handle_c {
on("c") >> [] { return 3; }
};
auto run_testee([&](actor testee) {
......@@ -469,8 +469,8 @@ void test_continuation() {
void test_simple_reply_response() {
auto s = spawn([](event_based_actor* self) -> behavior {
return (
others() >> [=]() -> any_tuple {
CPPA_CHECK(self->last_dequeued() == make_any_tuple(atom("hello")));
others() >> [=]() -> message {
CPPA_CHECK(self->last_dequeued() == make_message(atom("hello")));
self->quit();
return self->last_dequeued();
}
......@@ -480,7 +480,7 @@ void test_simple_reply_response() {
self->send(s, atom("hello"));
self->receive(
others() >> [&] {
CPPA_CHECK(self->last_dequeued() == make_any_tuple(atom("hello")));
CPPA_CHECK(self->last_dequeued() == make_message(atom("hello")));
}
);
self->await_all_other_actors_done();
......@@ -507,7 +507,7 @@ void test_spawn() {
CPPA_PRINT("test self->send()");
self->send(self, 1, 2, 3, true);
self->receive(on(1, 2, 3, true) >> [] { });
self->send_tuple(self, any_tuple{});
self->send_tuple(self, message{});
self->receive(on() >> [] { });
self->await_all_other_actors_done();
CPPA_CHECKPOINT();
......@@ -775,7 +775,7 @@ void test_spawn() {
others() >> CPPA_UNEXPECTED_MSG_CB_REF(self)
);
// kill joe and bob
auto poison_pill = make_any_tuple(atom("done"));
auto poison_pill = make_message(atom("done"));
anon_send_tuple(joe, poison_pill);
anon_send_tuple(bob, poison_pill);
self->await_all_other_actors_done();
......
......@@ -121,7 +121,7 @@ struct D : popular_actor {
quit();
});
//*/
return sync_send_tuple(buddy(), last_dequeued()).then([=]() -> any_tuple {
return sync_send_tuple(buddy(), last_dequeued()).then([=]() -> message {
quit();
return last_dequeued();
});//*/
......
......@@ -14,20 +14,17 @@
#include "cppa/on.hpp"
#include "cppa/cppa.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_traits.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/projection.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/object_array.hpp"
using std::cout;
using std::endl;
......@@ -212,7 +209,7 @@ void check_guards() {
auto f08 = on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; };
CPPA_CHECK_INVOKED(f08, (f08_val));
CPPA_CHECK_EQUAL(f08_val, 8);
any_tuple f08_any_val = make_cow_tuple(666);
message f08_any_val = make_cow_tuple(666);
CPPA_CHECK(f08(f08_any_val));
CPPA_CHECK_EQUAL(f08_any_val.get_as<int>(0), 8);
......@@ -221,11 +218,11 @@ void check_guards() {
CPPA_CHECK_NOT_INVOKED(f09, ("hello lambda", f09_val));
CPPA_CHECK_INVOKED(f09, ("0", f09_val));
CPPA_CHECK_EQUAL(f09_val, 9);
any_tuple f09_any_val = make_cow_tuple("0", 666);
message f09_any_val = make_cow_tuple("0", 666);
CPPA_CHECK(f09(f09_any_val));
CPPA_CHECK_EQUAL(f09_any_val.get_as<int>(1), 9);
f09_any_val.get_as_mutable<int>(1) = 666;
any_tuple f09_any_val_copy{f09_any_val};
message f09_any_val_copy{f09_any_val};
CPPA_CHECK(f09_any_val.at(0) == f09_any_val_copy.at(0));
// detaches f09_any_val from f09_any_val_copy
CPPA_CHECK(f09(f09_any_val));
......@@ -340,7 +337,7 @@ void check_wildcards() {
CPPA_CHECK_EQUAL("1", t0_0);
CPPA_CHECK_EQUAL(2, t0_1);
// use tuple cast to get a subtuple
any_tuple at0(t0);
message at0(t0);
auto v0opt = tuple_cast<std::string, anything>(at0);
CPPA_CHECK((std::is_same<decltype(v0opt), optional<cow_tuple<std::string>>>::value));
CPPA_CHECK((v0opt));
......@@ -366,7 +363,7 @@ void check_wildcards() {
CPPA_CHECK(lhs == rhs);
CPPA_CHECK(rhs == lhs);
}
any_tuple at1 = make_cow_tuple("one", 2, 3.f, 4.0); {
message at1 = make_cow_tuple("one", 2, 3.f, 4.0); {
// perfect match
auto opt0 = tuple_cast<std::string, int, float, double>(at1);
CPPA_CHECK(opt0);
......@@ -404,7 +401,7 @@ void check_wildcards() {
auto opt4 = tuple_cast<anything, double>(at1);
CPPA_CHECK(opt4);
if (opt4) {
CPPA_CHECK((*opt4 == make_any_tuple(4.0)));
CPPA_CHECK((*opt4 == make_message(4.0)));
CPPA_CHECK_EQUAL(get<0>(*opt4), 4.0);
CPPA_CHECK(&get<0>(*opt4) == at1.at(3));
}
......@@ -441,17 +438,17 @@ void check_move_ops() {
void check_drop() {
CPPA_PRINT(__func__);
auto t0 = make_any_tuple(0, 1, 2, 3);
auto t0 = make_message(0, 1, 2, 3);
auto t1 = t0.drop(2);
CPPA_CHECK_EQUAL(t1.size(), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(0), 2);
CPPA_CHECK_EQUAL(t1.get_as<int>(1), 3);
CPPA_CHECK(t1 == make_any_tuple(2, 3));
CPPA_CHECK(t1 == make_message(2, 3));
auto t2 = t0.drop_right(2);
CPPA_CHECK_EQUAL(t2.size(), 2);
CPPA_CHECK_EQUAL(t2.get_as<int>(0), 0);
CPPA_CHECK_EQUAL(t2.get_as<int>(1), 1);
CPPA_CHECK(t2 == make_any_tuple(0, 1));
CPPA_CHECK(t2 == make_message(0, 1));
CPPA_CHECK(t0.take(3) == t0.drop_right(1));
CPPA_CHECK(t0.take_right(3) == t0.drop(1));
CPPA_CHECK(t0 == t0.take(4));
......
......@@ -17,7 +17,7 @@
#include "cppa/atom.hpp"
#include "cppa/announce.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message.hpp"
#include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp"
#include "cppa/uniform_type_info.hpp"
......@@ -76,7 +76,7 @@ int main() {
"@cn_hdl", // io::connection_handle
"@atom", // atom_value
"@addr", // actor address
"@tuple", // any_tuple
"@msg", // message
"@header", // message_header
"@actor", // actor_ptr
"@group", // group
......@@ -147,7 +147,7 @@ int main() {
std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t,
std::string, std::u16string, std::u32string,
float, double,
atom_value, any_tuple, message_header,
atom_value, message, message_header,
actor, group,
channel, node_id_ptr
>::arr;
......@@ -169,7 +169,7 @@ int main() {
uniform_typeid<float>(),
uniform_typeid<double>(),
uniform_typeid<atom_value>(),
uniform_typeid<any_tuple>(),
uniform_typeid<message>(),
uniform_typeid<message_header>(),
uniform_typeid<actor>(),
uniform_typeid<group>(),
......
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