Commit 86c82bfc authored by Dominik Charousset's avatar Dominik Charousset

forward results of pattern matching callbacks

this patch enhances the pattern matching of libcppa, i.e., the result
of invoked callbacks is forwarded to the caller
parent 399b1b84
...@@ -24,7 +24,7 @@ if (CMAKE_CXX_FLAGS) ...@@ -24,7 +24,7 @@ if (CMAKE_CXX_FLAGS)
else (CMAKE_CXX_FLAGS) else (CMAKE_CXX_FLAGS)
set(CXXFLAGS_PROVIDED false) set(CXXFLAGS_PROVIDED false)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic") set(CMAKE_CXX_FLAGS "-std=c++11 -Wextra -Wall -pedantic")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -ftemplate-backtrace-limit=0")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
......
...@@ -107,6 +107,7 @@ cppa/mailbox_based.hpp ...@@ -107,6 +107,7 @@ cppa/mailbox_based.hpp
cppa/mailbox_element.hpp cppa/mailbox_element.hpp
cppa/match.hpp cppa/match.hpp
cppa/match_expr.hpp cppa/match_expr.hpp
cppa/match_hint.hpp
cppa/memory_cached.hpp cppa/memory_cached.hpp
cppa/memory_managed.hpp cppa/memory_managed.hpp
cppa/message_future.hpp cppa/message_future.hpp
...@@ -155,6 +156,7 @@ cppa/tpartial_function.hpp ...@@ -155,6 +156,7 @@ cppa/tpartial_function.hpp
cppa/tuple_cast.hpp cppa/tuple_cast.hpp
cppa/type_lookup_table.hpp cppa/type_lookup_table.hpp
cppa/uniform_type_info.hpp cppa/uniform_type_info.hpp
cppa/unit.hpp
cppa/util/abstract_uniform_type_info.hpp cppa/util/abstract_uniform_type_info.hpp
cppa/util/algorithm.hpp cppa/util/algorithm.hpp
cppa/util/arg_match_t.hpp cppa/util/arg_match_t.hpp
...@@ -184,7 +186,6 @@ cppa/util/type_list.hpp ...@@ -184,7 +186,6 @@ cppa/util/type_list.hpp
cppa/util/type_pair.hpp cppa/util/type_pair.hpp
cppa/util/type_traits.hpp cppa/util/type_traits.hpp
cppa/util/upgrade_lock_guard.hpp cppa/util/upgrade_lock_guard.hpp
cppa/util/void_type.hpp
cppa/util/wrapped.hpp cppa/util/wrapped.hpp
cppa/weak_intrusive_ptr.hpp cppa/weak_intrusive_ptr.hpp
cppa/weak_ptr_anchor.hpp cppa/weak_ptr_anchor.hpp
......
...@@ -179,6 +179,12 @@ struct cow_tuple_from_type_list< util::type_list<Ts...> > { ...@@ -179,6 +179,12 @@ struct cow_tuple_from_type_list< util::type_list<Ts...> > {
typedef cow_tuple<Ts...> type; typedef cow_tuple<Ts...> type;
}; };
template<typename T>
struct is_cow_tuple { static constexpr bool value = false; };
template<typename... Ts>
struct is_cow_tuple<cow_tuple<Ts...>> { static constexpr bool value = true; };
/** /**
* @ingroup CopyOnWrite * @ingroup CopyOnWrite
* @brief Gets a const-reference to the <tt>N</tt>th element of @p tup. * @brief Gets a const-reference to the <tt>N</tt>th element of @p tup.
......
...@@ -98,8 +98,9 @@ class behavior_impl : public ref_counted { ...@@ -98,8 +98,9 @@ class behavior_impl : public ref_counted {
}; };
struct dummy_match_expr { struct dummy_match_expr {
inline bool invoke(const any_tuple&) { return false; } inline optional_variant<void> invoke(const any_tuple&) const { return none; }
inline bool can_invoke(const any_tuple&) { return false; } inline bool can_invoke(const any_tuple&) const { return false; }
inline optional_variant<void> operator()(const any_tuple&) const { return none; }
}; };
template<class MatchExpr, typename F> template<class MatchExpr, typename F>
...@@ -118,11 +119,11 @@ class default_behavior_impl : public behavior_impl { ...@@ -118,11 +119,11 @@ class default_behavior_impl : public behavior_impl {
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { } : super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { }
bool invoke(any_tuple& tup) { bool invoke(any_tuple& tup) {
return m_expr.invoke(tup); return eval_res(m_expr(tup));
} }
bool invoke(const any_tuple& tup) { bool invoke(const any_tuple& tup) {
return m_expr.invoke(tup); return eval_res(m_expr(tup));
} }
bool defined_at(const any_tuple& tup) { bool defined_at(const any_tuple& tup) {
...@@ -137,8 +138,26 @@ class default_behavior_impl : public behavior_impl { ...@@ -137,8 +138,26 @@ class default_behavior_impl : public behavior_impl {
private: private:
MatchExpr m_expr; template<typename T>
F m_fun; typename std::enable_if<T::has_match_hint == true, bool>::type
eval_res(const T& res) {
if (res) {
if (res.template is<match_hint>()) {
return get<match_hint>(res) == match_hint::handle;
}
return true;
}
return false;
}
template<typename T>
typename std::enable_if<T::has_match_hint == false, bool>::type
eval_res(const T& res) {
return static_cast<bool>(res);
}
MatchExpr m_expr;
F m_fun;
}; };
......
...@@ -33,11 +33,11 @@ ...@@ -33,11 +33,11 @@
#include <memory> #include <memory>
#include "cppa/unit.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
#include "cppa/util/abstract_uniform_type_info.hpp" #include "cppa/util/abstract_uniform_type_info.hpp"
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <stdexcept> #include <stdexcept>
#include <type_traits> #include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/none.hpp" #include "cppa/none.hpp"
#define CPPA_OPTIONAL_VARIANT_DATA_CONCAT(x, y) x ## y #define CPPA_OPTIONAL_VARIANT_DATA_CONCAT(x, y) x ## y
...@@ -54,19 +55,19 @@ template<typename T> ...@@ -54,19 +55,19 @@ template<typename T>
struct lift_void { typedef T type; }; struct lift_void { typedef T type; };
template<> template<>
struct lift_void<void> { typedef util::void_type type; }; struct lift_void<void> { typedef unit_t type; };
template<typename T> template<typename T>
struct unlift_void { typedef T type; }; struct unlift_void { typedef T type; };
template<> template<>
struct unlift_void<util::void_type> { typedef void type; }; struct unlift_void<unit_t> { typedef void type; };
template<typename T0, typename T1 = util::void_type, template<typename T0, typename T1 = unit_t,
typename T2 = util::void_type, typename T3 = util::void_type, typename T2 = unit_t, typename T3 = unit_t,
typename T4 = util::void_type, typename T5 = util::void_type, typename T4 = unit_t, typename T5 = unit_t,
typename T6 = util::void_type, typename T7 = util::void_type, typename T6 = unit_t, typename T7 = unit_t,
typename T8 = util::void_type, typename T9 = util::void_type> typename T8 = unit_t, typename T9 = unit_t>
struct optional_variant_data { struct optional_variant_data {
union { union {
......
...@@ -68,6 +68,11 @@ struct collected_args_tuple { ...@@ -68,6 +68,11 @@ struct collected_args_tuple {
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. * @brief Projection implemented by a set of functors.
*/ */
...@@ -90,6 +95,7 @@ class projection { ...@@ -90,6 +95,7 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores * @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result. * the result of @p fun in @p result.
*/ */
/*
template<class PartFun> template<class PartFun>
bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const { bool invoke(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs; typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
...@@ -102,35 +108,21 @@ class projection { ...@@ -102,35 +108,21 @@ class projection {
} }
return false; return false;
} }
*/
/** /**
* @brief Invokes @p fun with a projection of <tt>args...</tt>. * @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/ */
template<class PartFun> template<class PartFun>
bool operator()(PartFun& fun, Ts... args) const { optional<typename PartFun::result_type> operator()(PartFun& fun, Ts... args) const {
typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs; typename collected_args_tuple<ProjectionFuns, Ts...>::type pargs;
auto indices = util::get_indices(pargs); auto indices = util::get_indices(pargs);
if (collect(pargs, m_funs, std::forward<Ts>(args)...)) { if (collect(pargs, m_funs, std::forward<Ts>(args)...)) {
if (is_defined_at(fun, pargs, indices)) { if (is_defined_at(fun, pargs, indices)) {
util::apply_args(fun, pargs, indices); return util::apply_args(fun, pargs, indices);
return true;
} }
} }
return false; return none;
}
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template<class PartFun>
inline bool operator()(PartFun& fun, typename PartFun::result_type& result, Ts... args) const {
return invoke(fun, result, args...);
}
template<class PartFun>
inline bool operator()(PartFun& fun, const util::void_type&, Ts... args) const {
return (*this)(fun, args...);
} }
private: private:
...@@ -151,7 +143,7 @@ class projection { ...@@ -151,7 +143,7 @@ class projection {
} }
template<typename T> template<typename T>
static inline auto fetch(const util::void_type&, T&& arg) static inline auto fetch(const unit_t&, T&& arg)
-> decltype(std::forward<T>(arg)) { -> decltype(std::forward<T>(arg)) {
return std::forward<T>(arg); return std::forward<T>(arg);
} }
...@@ -187,30 +179,11 @@ class projection<util::empty_type_list> { ...@@ -187,30 +179,11 @@ class projection<util::empty_type_list> {
projection(const projection&) = default; projection(const projection&) = default;
template<class PartFun> template<class PartFun>
bool operator()(PartFun& fun) const { optional<typename PartFun::result_type> operator()(PartFun& fun) const {
if (fun.defined_at()) {
fun();
return true;
}
return false;
}
template<class PartFun>
bool operator()(PartFun& fun, const util::void_type&) const {
if (fun.defined_at()) { if (fun.defined_at()) {
fun(); return fun();
return true;
} }
return false; return none;
}
template<class PartFun>
bool operator()(PartFun& fun, typename PartFun::result_type& res) const {
if (fun.defined_at()) {
res = fun();
return true;
}
return false;
} }
}; };
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <type_traits> #include <type_traits>
#include "cppa/get.hpp" #include "cppa/get.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp" #include "cppa/optional.hpp"
#include "cppa/util/wrapped.hpp" #include "cppa/util/wrapped.hpp"
...@@ -100,7 +101,7 @@ struct boxed_or_void { ...@@ -100,7 +101,7 @@ struct boxed_or_void {
}; };
template<> template<>
struct boxed_or_void<util::void_type> { struct boxed_or_void<unit_t> {
static constexpr bool value = true; static constexpr bool value = true;
}; };
...@@ -130,18 +131,18 @@ struct tdata<> { ...@@ -130,18 +131,18 @@ struct tdata<> {
typedef tdata super; typedef tdata super;
util::void_type head; unit_t head;
typedef util::void_type head_type; typedef unit_t head_type;
typedef tdata<> tail_type; typedef tdata<> tail_type;
typedef util::void_type back_type; typedef unit_t back_type;
typedef util::empty_type_list types; typedef util::empty_type_list types;
static constexpr size_t num_elements = 0; static constexpr size_t num_elements = 0;
constexpr tdata() { } constexpr tdata() { }
// swallow any number of additional boxed or void_type arguments silently // swallow any number of additional boxed or unit_t arguments silently
template<typename... Ts> template<typename... Ts>
tdata(Ts&&...) { tdata(Ts&&...) {
typedef util::type_list<typename util::rm_const_and_ref<Ts>::type...> incoming; typedef util::type_list<typename util::rm_const_and_ref<Ts>::type...> incoming;
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include "cppa/cppa_fwd.hpp" #include "cppa/cppa_fwd.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/unit.hpp"
#include "cppa/none.hpp"
#include "cppa/process_information.hpp" #include "cppa/process_information.hpp"
#include "cppa/util/buffer.hpp" #include "cppa/util/buffer.hpp"
...@@ -68,9 +70,9 @@ using mapped_type_list = util::type_list< ...@@ -68,9 +70,9 @@ using mapped_type_list = util::type_list<
io::connection_handle, io::connection_handle,
message_header, message_header,
std::nullptr_t, std::nullptr_t,
unit_t,
util::buffer, util::buffer,
util::duration, util::duration,
util::void_type,
double, double,
float, float,
long double, long double,
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <type_traits> #include <type_traits>
#include "cppa/util/void_type.hpp" #include "cppa/unit.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
...@@ -47,13 +47,13 @@ const T& vg_fwd(const T& arg, typename std::enable_if<not util::is_callable<T>:: ...@@ -47,13 +47,13 @@ const T& vg_fwd(const T& arg, typename std::enable_if<not util::is_callable<T>::
return arg; return arg;
} }
inline util::void_type vg_fwd(const anything&) { inline unit_t vg_fwd(const anything&) {
return {}; return unit;
} }
template<typename T> template<typename T>
util::void_type vg_fwd(const T&, typename std::enable_if<util::is_callable<T>::value>::type* = 0) { unit_t vg_fwd(const T&, typename std::enable_if<util::is_callable<T>::value>::type* = 0) {
return {}; return unit;
} }
template<typename T> template<typename T>
...@@ -65,9 +65,9 @@ struct vg_cmp { ...@@ -65,9 +65,9 @@ struct vg_cmp {
}; };
template<> template<>
struct vg_cmp<util::void_type> { struct vg_cmp<unit_t> {
template<typename T> template<typename T>
inline static bool _(const util::void_type&, const T&) { inline static bool _(const unit_t&, const T&) {
return true; return true;
} }
}; };
...@@ -102,7 +102,7 @@ class value_guard { ...@@ -102,7 +102,7 @@ class value_guard {
return vg_cmp<T>::_(lhs, rhs.get()); return vg_cmp<T>::_(lhs, rhs.get());
} }
static inline bool _eval(const util::void_type&, const tdata<>&) { static inline bool _eval(const unit_t&, const tdata<>&) {
return true; return true;
} }
......
...@@ -37,11 +37,11 @@ ...@@ -37,11 +37,11 @@
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/optional.hpp" #include "cppa/optional.hpp"
#include "cppa/util/call.hpp" #include "cppa/util/call.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
#include "cppa/util/rebindable_reference.hpp" #include "cppa/util/rebindable_reference.hpp"
...@@ -168,8 +168,8 @@ typename gcall3<Fun, T1, T2, T3>::result gcall(Fun fun, T1 t1, T2 t2, T3 t3) { ...@@ -168,8 +168,8 @@ typename gcall3<Fun, T1, T2, T3>::result gcall(Fun fun, T1 t1, T2 t2, T3 t3) {
* The functor @p fun must return a boolean. * The functor @p fun must return a boolean.
*/ */
template<typename Fun> template<typename Fun>
guard_expr<exec_xfun_op, Fun, util::void_type> ge_sub_function(Fun fun) { guard_expr<exec_xfun_op, Fun, unit_t> ge_sub_function(Fun fun) {
return {fun, util::void_type{}}; return {fun, unit};
} }
struct ge_search_container { struct ge_search_container {
...@@ -449,7 +449,7 @@ struct ge_result_<guard_expr<OP, First, Second>, Tuple> { ...@@ -449,7 +449,7 @@ struct ge_result_<guard_expr<OP, First, Second>, Tuple> {
}; };
template<typename Fun, class Tuple> template<typename Fun, class Tuple>
struct ge_result_<guard_expr<exec_xfun_op, Fun, util::void_type>, Tuple> { struct ge_result_<guard_expr<exec_xfun_op, Fun, unit_t>, Tuple> {
typedef bool type; typedef bool type;
}; };
...@@ -574,8 +574,8 @@ struct ge_eval_<logical_or_op, Tuple, First, Second> { ...@@ -574,8 +574,8 @@ struct ge_eval_<logical_or_op, Tuple, First, Second> {
}; };
template<class Tuple, typename Fun> template<class Tuple, typename Fun>
struct ge_eval_<exec_xfun_op, Tuple, Fun, util::void_type> { struct ge_eval_<exec_xfun_op, Tuple, Fun, unit_t> {
static inline bool _(const Tuple& tup, const Fun& fun, const util::void_type&) { static inline bool _(const Tuple& tup, const Fun& fun, const unit_t&) {
return util::apply_args(fun, tup, util::get_indices(tup)); return util::apply_args(fun, tup, util::get_indices(tup));
} }
}; };
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <type_traits> #include <type_traits>
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/match_expr.hpp" #include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
...@@ -147,23 +148,15 @@ struct unwind_and_call { ...@@ -147,23 +148,15 @@ struct unwind_and_call {
typedef unwind_and_call<N+1, Size> next; typedef unwind_and_call<N+1, Size> next;
template<class Target, typename T, typename... Unwinded> template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, std::vector<T>& vec, Unwinded&&... args) { static inline bool _(Target& target, bool& skipped, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, vec, std::forward<Unwinded>(args)..., vec[N]); return next::_(target, skipped, vec, std::forward<Unwinded>(args)..., vec[N]);
}
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, sub_result, vec, std::forward<Unwinded>(args)..., vec[N]);
} }
template<typename T, typename InputIterator, class MatchExpr> template<typename T, typename InputIterator, class MatchExpr>
static inline bool _(std::vector<T>& vec, InputIterator& pos, InputIterator end, MatchExpr& ex) { static inline bool _(std::vector<T>& vec, InputIterator& pos, InputIterator end, MatchExpr& ex) {
bool match_returned_false = false; bool skipped = false;
if (run_case(vec, match_returned_false, pos, end, get<N>(ex.cases())) == 0) { if (run_case(vec, skipped, pos, end, get<N>(ex.cases())) == 0) {
if (match_returned_false) { return (skipped) ? false : next::_(vec, pos, end, ex);
return false;
}
return next::_(vec, pos, end, ex);
} }
return true; return true;
} }
...@@ -173,14 +166,25 @@ struct unwind_and_call { ...@@ -173,14 +166,25 @@ struct unwind_and_call {
template<size_t Size> template<size_t Size>
struct unwind_and_call<Size, Size> { struct unwind_and_call<Size, Size> {
template<class Target, typename T, typename... Unwinded> template<typename T>
static inline bool _(Target& target, std::vector<T>&, Unwinded&&... args) { static inline bool eval_res(const optional<T>& res, bool&) {
return target.first(target.second, std::forward<Unwinded>(args)...); return static_cast<bool>(res);
}
static inline bool eval_res(const optional<match_hint>& res, bool& skipped) {
if (res) {
if (*res == match_hint::skip) {
skipped = true;
return false;
}
return true;
}
return false;
} }
template<class Target, typename T, typename... Unwinded> template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>&, Unwinded&&... args) { static inline bool _(Target& target, bool& skipped, std::vector<T>&, Unwinded&&... args) {
return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...); return eval_res(target.first(target.second, std::forward<Unwinded>(args)...), skipped);
} }
template<typename T, typename... Ts> template<typename T, typename... Ts>
...@@ -188,33 +192,15 @@ struct unwind_and_call<Size, Size> { ...@@ -188,33 +192,15 @@ struct unwind_and_call<Size, Size> {
}; };
template<bool EvaluateSubResult> // default = false template<class Case, typename T>
struct run_case_impl { inline bool run_case_impl(Case& target, std::vector<T>& vec, bool& skipped) {
template<class Case, typename T> return unwind_and_call<0, util::tl_size<typename Case::pattern_type>::value>::_(target, skipped, vec);
static inline bool _(Case& target, std::vector<T>& vec, bool&) { }
return unwind_and_call<0, util::tl_size<typename Case::pattern_type>::value>::_(target, vec);
}
};
template<>
struct run_case_impl<true> {
template<class Case, typename T>
static inline bool _(Case& target, std::vector<T>& vec, bool& match_returned_false) {
bool sub_result;
if (unwind_and_call<0, util::tl_size<typename Case::pattern_type>::value>::_(target, sub_result, vec)) {
if (sub_result == false) {
match_returned_false = true;
}
return true;
}
return false;
}
};
// Case is a projection_partial_function_pair // Case is a projection_partial_function_pair
template<typename T, typename InputIterator, class Case> template<typename T, typename InputIterator, class Case>
size_t run_case(std::vector<T>& vec, size_t run_case(std::vector<T>& vec,
bool& match_returned_false, bool& skipped,
InputIterator& pos, InputIterator& pos,
const InputIterator& end, const InputIterator& end,
Case& target) { Case& target) {
...@@ -234,7 +220,7 @@ size_t run_case(std::vector<T>& vec, ...@@ -234,7 +220,7 @@ size_t run_case(std::vector<T>& vec,
} }
vec.emplace_back(*pos++); vec.emplace_back(*pos++);
} }
if (run_case_impl<std::is_same<result_type, bool>::value>::_(target, vec, match_returned_false)) { if (run_case_impl(target, vec, skipped)) {
if (vec.size() == num_args) { if (vec.size() == num_args) {
vec.clear(); vec.clear();
} }
...@@ -242,7 +228,7 @@ size_t run_case(std::vector<T>& vec, ...@@ -242,7 +228,7 @@ size_t run_case(std::vector<T>& vec,
auto i = vec.begin(); auto i = vec.begin();
vec.erase(i, i + num_args); vec.erase(i, i + num_args);
} }
return match_returned_false ? 0 : num_args; return skipped ? 0 : num_args;
} }
return 0; return 0;
} }
......
This diff is collapsed.
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_MATCH_HINT_HPP
#define CPPA_MATCH_HINT_HPP
namespace cppa {
/**
* @brief Optional return type for functors used in pattern matching
* expressions. This type is evaluated by the runtime system of libcppa
* and can be used to intentionally skip messages.
*/
enum class match_hint {
skip,
handle
};
} // namespace cppa
#endif // CPPA_MATCH_HINT_HPP
...@@ -142,9 +142,9 @@ class message_future { ...@@ -142,9 +142,9 @@ class message_future {
template<typename... Fs> template<typename... Fs>
behavior fs2bhvr(Fs... fs) { behavior fs2bhvr(Fs... fs) {
auto handle_sync_timeout = []() -> bool { auto handle_sync_timeout = []() -> match_hint {
self->handle_sync_timeout(); self->handle_sync_timeout();
return false; return match_hint::skip;
}; };
return { return {
on(atom("EXITED"), val<std::uint32_t>) >> skip_message, on(atom("EXITED"), val<std::uint32_t>) >> skip_message,
......
...@@ -95,7 +95,7 @@ class object { ...@@ -95,7 +95,7 @@ class object {
/** /**
* @brief Creates an empty object. * @brief Creates an empty object.
* @post {type() == *uniform_typeid<util::void_type>()} * @post {type() == *uniform_typeid<unit_t>()}
*/ */
object(); object();
......
...@@ -35,11 +35,13 @@ ...@@ -35,11 +35,13 @@
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/guard_expr.hpp" #include "cppa/guard_expr.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/match_expr.hpp" #include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
...@@ -65,7 +67,7 @@ template<typename T> ...@@ -65,7 +67,7 @@ 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> template<bool ToVoid, typename T>
struct to_void_impl { typedef util::void_type type; }; struct to_void_impl { typedef unit_t type; };
template<typename T> 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; };
...@@ -138,19 +140,16 @@ struct rvalue_builder { ...@@ -138,19 +140,16 @@ struct rvalue_builder {
template<typename... Ts> template<typename... Ts>
rvalue_builder(rvalue_builder_args_ctor, const Ts&... args) rvalue_builder(rvalue_builder_args_ctor, const Ts&... args)
: m_guard(args...) : m_guard(args...), m_funs(args...) { }
, m_funs(args...) {
}
rvalue_builder(Guard arg0, fun_container arg1) rvalue_builder(Guard arg0, fun_container arg1)
: m_guard(std::move(arg0)), m_funs(std::move(arg1)) { : m_guard(std::move(arg0)), m_funs(std::move(arg1)) { }
}
template<typename NewGuard> template<typename NewGuard>
rvalue_builder< rvalue_builder<
guard_expr< guard_expr<
logical_and_op, logical_and_op,
guard_expr<exec_xfun_op, Guard, util::void_type>, guard_expr<exec_xfun_op, Guard, unit_t>,
NewGuard>, NewGuard>,
Transformers, Transformers,
Pattern> Pattern>
...@@ -228,6 +227,11 @@ namespace cppa { ...@@ -228,6 +227,11 @@ namespace cppa {
*/ */
constexpr anything any_vals = anything{}; constexpr anything any_vals = anything{};
/**
* @brief Returns {@link match_hint skipped}.
*/
match_hint skip_message();
#ifdef CPPA_DOCUMENTATION #ifdef CPPA_DOCUMENTATION
/** /**
...@@ -244,11 +248,6 @@ constexpr __unspecified__ arg_match; ...@@ -244,11 +248,6 @@ constexpr __unspecified__ arg_match;
*/ */
constexpr __unspecified__ on_arg_match; constexpr __unspecified__ on_arg_match;
/**
* @brief Right-hand side expression to *not* match a particular pattern.
*/
constexpr __unspecified__ skip_message;
/** /**
* @brief A wildcard that matches any value of type @p T. * @brief A wildcard that matches any value of type @p T.
* @see {@link math_actor_example.cpp Math Actor Example} * @see {@link math_actor_example.cpp Math Actor Example}
...@@ -286,8 +285,6 @@ __unspecified__ on(); ...@@ -286,8 +285,6 @@ __unspecified__ on();
#else #else
bool skip_message();
template<typename T> template<typename T>
constexpr typename detail::boxed<T>::type val() { constexpr typename detail::boxed<T>::type val() {
return typename detail::boxed<T>::type(); return typename detail::boxed<T>::type();
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <utility> #include <utility>
#include "cppa/none.hpp" #include "cppa/none.hpp"
#include "cppa/unit.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
namespace cppa { namespace cppa {
...@@ -122,6 +123,8 @@ class optional { ...@@ -122,6 +123,8 @@ class optional {
*/ */
inline bool operator!() const { return empty(); } inline bool operator!() const { return empty(); }
inline bool operator==(const none_t&) { return empty(); }
/** /**
* @brief Returns the value. * @brief Returns the value.
*/ */
...@@ -208,6 +211,8 @@ class optional<T&> { ...@@ -208,6 +211,8 @@ class optional<T&> {
inline bool operator!() const { return empty(); } inline bool operator!() const { return empty(); }
inline bool operator==(const none_t&) { return empty(); }
inline T& operator*() { inline T& operator*() {
CPPA_REQUIRE(valid()); CPPA_REQUIRE(valid());
return *m_value; return *m_value;
...@@ -242,7 +247,9 @@ class optional<T&> { ...@@ -242,7 +247,9 @@ class optional<T&> {
template<> template<>
class optional<void> { class optional<void> {
optional() : m_valid(true) { } public:
optional(const unit_t&) : m_valid(true) { }
optional(const none_t&) : m_valid(false) { } optional(const none_t&) : m_valid(false) { }
...@@ -254,6 +261,10 @@ class optional<void> { ...@@ -254,6 +261,10 @@ class optional<void> {
inline bool operator!() const { return empty(); } inline bool operator!() const { return empty(); }
inline bool operator==(const none_t&) { return empty(); }
inline const unit_t& operator*() const { return unit; }
private: private:
bool m_valid; bool m_valid;
......
...@@ -35,9 +35,11 @@ ...@@ -35,9 +35,11 @@
#include <type_traits> #include <type_traits>
#include "cppa/none.hpp" #include "cppa/none.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp"
#include "cppa/match_hint.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
#include "cppa/detail/optional_variant_data.hpp" #include "cppa/detail/optional_variant_data.hpp"
...@@ -55,6 +57,45 @@ constexpr std::integral_constant<int, Value> make_int_token() { return {}; } ...@@ -55,6 +57,45 @@ constexpr std::integral_constant<int, Value> make_int_token() { return {}; }
template<bool Value> template<bool Value>
constexpr std::integral_constant<bool, Value> make_bool_token() { return {}; } constexpr std::integral_constant<bool, Value> make_bool_token() { return {}; }
template<typename T>
struct optional_variant_copy_helper {
T& lhs;
optional_variant_copy_helper(T& lhs_ref) : lhs(lhs_ref) { }
template<typename U>
inline void operator()(const U& rhs) const {
lhs = rhs;
}
inline void operator()() const {
lhs = unit;
}
};
template<typename T>
struct optional_variant_move_helper {
T& lhs;
optional_variant_move_helper(T& lhs_ref) : lhs(lhs_ref) { }
template<typename U>
inline void operator()(const U& rhs) const {
lhs = std::move(rhs);
}
inline void operator()() const {
lhs = unit;
}
};
template<typename... Ts>
class optional_variant;
template<typename T>
struct is_optional_variant {
static constexpr bool value = false;
};
template<typename... Ts>
struct is_optional_variant<optional_variant<Ts...>> {
static constexpr bool value = true;
};
/** /**
* @brief A optional_variant is either invalid or holds * @brief A optional_variant is either invalid or holds
a value of one of the types <tt>Ts</tt>. a value of one of the types <tt>Ts</tt>.
...@@ -68,6 +109,8 @@ class optional_variant { ...@@ -68,6 +109,8 @@ class optional_variant {
static constexpr int void_pos = util::tl_find<types, void>::value; static constexpr int void_pos = util::tl_find<types, void>::value;
static constexpr bool has_match_hint = util::tl_find<types, match_hint>::value != -1;
/** /**
* @brief Checks whether this objects holds a value of type @p T. * @brief Checks whether this objects holds a value of type @p T.
*/ */
...@@ -83,6 +126,20 @@ class optional_variant { ...@@ -83,6 +126,20 @@ class optional_variant {
return *this; return *this;
} }
optional_variant& operator=(const optional_variant& other) {
destroy_data();
optional_variant_copy_helper<optional_variant> helper{*this};
other.apply(helper);
return *this;
}
optional_variant& operator=(optional_variant&& other) {
destroy_data();
optional_variant_move_helper<optional_variant> helper{*this};
other.apply(helper);
return *this;
}
optional_variant() : m_type(-1) { } optional_variant() : m_type(-1) { }
template<typename U> template<typename U>
...@@ -90,6 +147,16 @@ class optional_variant { ...@@ -90,6 +147,16 @@ class optional_variant {
set(std::forward<U>(arg)); set(std::forward<U>(arg));
} }
optional_variant(const optional_variant& other) : m_type(-1) {
optional_variant_copy_helper<optional_variant> helper{*this};
other.apply(helper);
}
optional_variant(optional_variant&& other) : m_type(-1) {
optional_variant_move_helper<optional_variant> helper{*this};
other.apply(helper);
}
~optional_variant() { ~optional_variant() {
destroy_data(); destroy_data();
} }
...@@ -197,7 +264,9 @@ class optional_variant { ...@@ -197,7 +264,9 @@ class optional_variant {
template<typename U> template<typename U>
typename std::enable_if< typename std::enable_if<
!std::is_same<typename util::rm_const_and_ref<U>::type, none_t>::value !std::is_same<typename util::rm_const_and_ref<U>::type, none_t>::value
&& !is_optional_variant<typename util::rm_const_and_ref<U>::type>::value
&& !is_optional<typename util::rm_const_and_ref<U>::type>::value
>::type >::type
set(U&& arg) { set(U&& arg) {
typedef typename util::rm_const_and_ref<U>::type stripped_type; typedef typename util::rm_const_and_ref<U>::type stripped_type;
...@@ -209,6 +278,28 @@ class optional_variant { ...@@ -209,6 +278,28 @@ class optional_variant {
new (&ref) stripped_type (std::forward<U>(arg)); new (&ref) stripped_type (std::forward<U>(arg));
} }
inline void set(const optional_variant& other) {
optional_variant_copy_helper<optional_variant> helper{*this};
other.apply(helper);
}
inline void set(optional_variant&& other) {
optional_variant_move_helper<optional_variant> helper{*this};
other.apply(helper);
}
template<typename T>
inline void set(const optional<T>& arg) {
if (arg) set(*arg);
else set(none);
}
template<typename T>
inline void set(optional<T>&& arg) {
if (arg) set(std::move(*arg));
else set(none);
}
inline void set(const none_t&) { m_type = -1; } inline void set(const none_t&) { m_type = -1; }
int m_type; int m_type;
...@@ -250,6 +341,14 @@ auto apply_visitor(const Visitor& visitor, optional_variant<Ts...>& data) -> dec ...@@ -250,6 +341,14 @@ auto apply_visitor(const Visitor& visitor, optional_variant<Ts...>& data) -> dec
return data.apply(visitor); return data.apply(visitor);
} }
template<typename T>
struct optional_variant_from_type_list;
template<typename... Ts>
struct optional_variant_from_type_list<util::type_list<Ts...>> {
typedef optional_variant<Ts...> type;
};
} // namespace cppa } // namespace cppa
#endif // OPTIONAL_VARIANT_HPP #endif // OPTIONAL_VARIANT_HPP
...@@ -34,6 +34,10 @@ ...@@ -34,6 +34,10 @@
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include "cppa/none.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp"
#include "cppa/util/call.hpp" #include "cppa/util/call.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp" #include "cppa/util/type_traits.hpp"
...@@ -41,6 +45,28 @@ ...@@ -41,6 +45,28 @@
namespace cppa { namespace cppa {
template<typename Result, typename... Ts>
struct tpartial_function_helper {
template<typename Fun>
inline optional<Result> operator()(const Fun& fun, Ts... args) {
if (fun.defined_at(args...)) return fun.invoke(args...);
return none;
}
};
template<typename... Ts>
struct tpartial_function_helper<void, Ts...> {
template<typename Fun>
inline optional<void> operator()(const Fun& fun, Ts... args) {
if (fun.defined_at(args...)) {
fun.invoke(args...);
return unit;
}
return none;
}
};
template<class Expr, class Guard, typename Result, typename... Ts> template<class Expr, class Guard, typename Result, typename... Ts>
class tpartial_function { class tpartial_function {
...@@ -76,16 +102,24 @@ class tpartial_function { ...@@ -76,16 +102,24 @@ class tpartial_function {
tpartial_function(const tpartial_function&) = default; tpartial_function(const tpartial_function&) = default;
bool defined_at(Ts... args) const { inline bool defined_at(Ts... args) const {
return m_guard(args...); return m_guard(args...);
} }
result_type operator()(Ts... args) const { /**
* @brief Invokes the function without evaluating the guard.
*/
result_type invoke(Ts... args) const {
auto targs = std::forward_as_tuple(args...); auto targs = std::forward_as_tuple(args...);
auto indices = util::get_right_indices<num_expr_args>(targs); auto indices = util::get_right_indices<num_expr_args>(targs);
return util::apply_args(m_expr, targs, indices); return util::apply_args(m_expr, targs, indices);
} }
inline optional<result_type> operator()(Ts... args) const {
tpartial_function_helper<result_type, Ts...> helper;
return helper(*this, args...);
}
private: private:
Guard m_guard; Guard m_guard;
...@@ -94,7 +128,7 @@ class tpartial_function { ...@@ -94,7 +128,7 @@ class tpartial_function {
}; };
template<class Expr, class Guard, typename Ts, template<class Expr, class Guard, typename Ts,
typename Result = util::void_type, size_t Step = 0> typename Result = unit_t, size_t Step = 0>
struct get_tpartial_function; struct get_tpartial_function;
template<class Expr, class Guard, typename... Ts, typename Result> template<class Expr, class Guard, typename... Ts, typename Result>
...@@ -104,7 +138,7 @@ struct get_tpartial_function<Expr, Guard, util::type_list<Ts...>, Result, 1> { ...@@ -104,7 +138,7 @@ struct get_tpartial_function<Expr, Guard, util::type_list<Ts...>, Result, 1> {
template<class Expr, class Guard, typename... Ts> template<class Expr, class Guard, typename... Ts>
struct get_tpartial_function<Expr, Guard, struct get_tpartial_function<Expr, Guard,
util::type_list<Ts...>, util::void_type, 0> { util::type_list<Ts...>, unit_t, 0> {
typedef typename util::get_callable_trait<Expr>::type ctrait; typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types arg_types; typedef typename ctrait::arg_types arg_types;
......
...@@ -28,19 +28,18 @@ ...@@ -28,19 +28,18 @@
\******************************************************************************/ \******************************************************************************/
#ifndef CPPA_UTIL_VOID_TYPE_HPP #ifndef CPPA_UNIT_HPP
#define CPPA_UTIL_VOID_TYPE_HPP #define CPPA_UNIT_HPP
namespace cppa { namespace util { namespace cppa {
struct void_type { struct unit_t {
constexpr void_type() { } constexpr unit_t() { }
constexpr void_type(const void_type&) { } template<typename T> constexpr unit_t(T&&) { }
// anything could be used to initialize a void...
template<typename Arg>
constexpr void_type(const Arg&) { }
}; };
} } // namespace cppa::util static constexpr unit_t unit = unit_t{};
#endif // CPPA_UTIL_VOID_TYPE_HPP } // namespace cppa
#endif // CPPA_UNIT_HPP
...@@ -31,12 +31,12 @@ ...@@ -31,12 +31,12 @@
#ifndef CPPA_LEFT_OR_RIGHT_HPP #ifndef CPPA_LEFT_OR_RIGHT_HPP
#define CPPA_LEFT_OR_RIGHT_HPP #define CPPA_LEFT_OR_RIGHT_HPP
#include "cppa/util/void_type.hpp" #include "cppa/unit.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
/** /**
* @brief Evaluates to @p Right if @p Left == void_type, @p Left otherwise. * @brief Evaluates to @p Right if @p Left == unit_t, @p Left otherwise.
*/ */
template<typename Left, typename Right> template<typename Left, typename Right>
struct left_or_right { struct left_or_right {
...@@ -44,30 +44,30 @@ struct left_or_right { ...@@ -44,30 +44,30 @@ struct left_or_right {
}; };
template<typename Right> template<typename Right>
struct left_or_right<util::void_type, Right> { struct left_or_right<unit_t, Right> {
typedef Right type; typedef Right type;
}; };
template<typename Right> template<typename Right>
struct left_or_right<util::void_type&, Right> { struct left_or_right<unit_t&, Right> {
typedef Right type; typedef Right type;
}; };
template<typename Right> template<typename Right>
struct left_or_right<const util::void_type&, Right> { struct left_or_right<const unit_t&, Right> {
typedef Right type; typedef Right type;
}; };
/** /**
* @brief Evaluates to @p Right if @p Left != void_type, @p void_type otherwise. * @brief Evaluates to @p Right if @p Left != unit_t, @p unit_t otherwise.
*/ */
template<typename Left, typename Right> template<typename Left, typename Right>
struct if_not_left { struct if_not_left {
typedef void_type type; typedef unit_t type;
}; };
template<typename Right> template<typename Right>
struct if_not_left<util::void_type, Right> { struct if_not_left<unit_t, Right> {
typedef Right type; typedef Right type;
}; };
......
...@@ -34,9 +34,10 @@ ...@@ -34,9 +34,10 @@
#include <typeinfo> #include <typeinfo>
#include <type_traits> #include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/util/tbind.hpp" #include "cppa/util/tbind.hpp"
#include "cppa/util/type_pair.hpp" #include "cppa/util/type_pair.hpp"
#include "cppa/util/void_type.hpp"
namespace cppa { namespace cppa {
...@@ -135,7 +136,7 @@ struct tl_back; ...@@ -135,7 +136,7 @@ struct tl_back;
template<template<typename...> class List> template<template<typename...> class List>
struct tl_back<List<>> { struct tl_back<List<>> {
typedef void_type type; typedef unit_t type;
}; };
template<template<typename...> class List, typename T0> template<template<typename...> class List, typename T0>
...@@ -212,7 +213,7 @@ struct tl_slice_impl<0, 0, PadType, empty_type_list, T...> { ...@@ -212,7 +213,7 @@ struct tl_slice_impl<0, 0, PadType, empty_type_list, T...> {
}; };
template<class List, size_t ListSize, size_t First, size_t Last, template<class List, size_t ListSize, size_t First, size_t Last,
typename PadType = void_type> typename PadType = unit_t>
struct tl_slice_ { struct tl_slice_ {
typedef typename tl_slice_impl< typedef typename tl_slice_impl<
First, (Last - First), First, (Last - First),
...@@ -274,8 +275,8 @@ struct tl_zip { ...@@ -274,8 +275,8 @@ struct tl_zip {
template<class ListA, template<class ListA,
class ListB, class ListB,
typename PadA = void_type, typename PadA = unit_t,
typename PadB = void_type, typename PadB = unit_t,
template<typename, typename> class Fun = to_type_pair> template<typename, typename> class Fun = to_type_pair>
struct tl_zip_all { struct tl_zip_all {
static constexpr size_t result_size = (tl_size<ListA>::value > tl_size<ListB>::value) ? tl_size<ListA>::value static constexpr size_t result_size = (tl_size<ListA>::value > tl_size<ListB>::value) ? tl_size<ListA>::value
...@@ -863,7 +864,7 @@ struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType> { ...@@ -863,7 +864,7 @@ struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType> {
* @brief Resizes the list to contain @p NewSize elements and uses * @brief Resizes the list to contain @p NewSize elements and uses
* @p FillType to initialize the new elements with. * @p FillType to initialize the new elements with.
*/ */
template<class List, size_t NewSize, typename FillType = void_type> template<class List, size_t NewSize, typename FillType = unit_t>
struct tl_pad_right { struct tl_pad_right {
typedef typename tl_pad_right_impl< typedef typename tl_pad_right_impl<
List, (tl_size<List>::value < NewSize), tl_size<List>::value, NewSize, FillType List, (tl_size<List>::value < NewSize), tl_size<List>::value, NewSize, FillType
...@@ -893,7 +894,7 @@ struct tl_pad_left_impl<List, Size, Size, FillType> { ...@@ -893,7 +894,7 @@ struct tl_pad_left_impl<List, Size, Size, FillType> {
* @brief Resizes the list to contain @p NewSize elements and uses * @brief Resizes the list to contain @p NewSize elements and uses
* @p FillType to initialize prepended elements with. * @p FillType to initialize prepended elements with.
*/ */
template<class List, size_t NewSize, typename FillType = void_type> template<class List, size_t NewSize, typename FillType = unit_t>
struct tl_pad_left { struct tl_pad_left {
static constexpr size_t list_size = tl_size<List>::value; static constexpr size_t list_size = tl_size<List>::value;
//static_assert(NewSize >= tl_size<List>::value, "List too big"); //static_assert(NewSize >= tl_size<List>::value, "List too big");
...@@ -915,7 +916,7 @@ struct tl_is_zipped { ...@@ -915,7 +916,7 @@ struct tl_is_zipped {
/** /**
* @brief Removes trailing @p What elements from the end. * @brief Removes trailing @p What elements from the end.
*/ */
template<class List, typename What = void_type> template<class List, typename What = unit_t>
struct tl_trim { struct tl_trim {
typedef typename std::conditional< typedef typename std::conditional<
std::is_same<typename tl_back<List>::type, What>::value, std::is_same<typename tl_back<List>::type, What>::value,
......
...@@ -445,12 +445,12 @@ struct map_to_result_type_impl { ...@@ -445,12 +445,12 @@ struct map_to_result_type_impl {
template<typename C> template<typename C>
struct map_to_result_type_impl<false, C> { struct map_to_result_type_impl<false, C> {
typedef void_type type; typedef unit_t type;
}; };
/** /**
* @brief Maps @p T to its result type if it's callable, * @brief Maps @p T to its result type if it's callable,
* {@link void_type} otherwise. * {@link unit_t} otherwise.
*/ */
template<typename T> template<typename T>
struct map_to_result_type { struct map_to_result_type {
......
...@@ -30,19 +30,19 @@ ...@@ -30,19 +30,19 @@
#include <algorithm> #include <algorithm>
#include "cppa/unit.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/object.hpp" #include "cppa/object.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
namespace { namespace {
cppa::util::void_type s_void; cppa::unit_t s_unit;
inline const cppa::uniform_type_info* tvoid() { inline const cppa::uniform_type_info* unit_type() {
return cppa::detail::static_types_array<cppa::util::void_type>::arr[0]; return cppa::detail::static_types_array<cppa::unit_t>::arr[0];
} }
} // namespace <anonymous> } // namespace <anonymous>
...@@ -60,20 +60,20 @@ object::object(void* val, const uniform_type_info* utype) ...@@ -60,20 +60,20 @@ object::object(void* val, const uniform_type_info* utype)
CPPA_REQUIRE(utype != nullptr); CPPA_REQUIRE(utype != nullptr);
} }
object::object() : m_value(&s_void), m_type(tvoid()) { object::object() : m_value(&s_unit), m_type(unit_type()) {
} }
object::~object() { object::~object() {
if (m_value != &s_void) m_type->delete_instance(m_value); if (m_value != &s_unit) m_type->delete_instance(m_value);
} }
object::object(const object& other) { object::object(const object& other) {
m_type = other.m_type; m_type = other.m_type;
m_value = (other.m_value == &s_void) ? other.m_value m_value = (other.m_value == &s_unit) ? other.m_value
: m_type->new_instance(other.m_value); : m_type->new_instance(other.m_value);
} }
object::object(object&& other) : m_value(&s_void), m_type(tvoid()) { object::object(object&& other) : m_value(&s_unit), m_type(unit_type()) {
swap(other); swap(other);
} }
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
namespace cppa { namespace cppa {
bool skip_message() { return false; } match_hint skip_message() {
return match_hint::skip;
}
} // namespace cppa } // namespace cppa
...@@ -45,8 +45,6 @@ ...@@ -45,8 +45,6 @@
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/message_header.hpp" #include "cppa/message_header.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/detail/demangle.hpp" #include "cppa/detail/demangle.hpp"
#include "cppa/detail/to_uniform_name.hpp" #include "cppa/detail/to_uniform_name.hpp"
#include "cppa/detail/singleton_manager.hpp" #include "cppa/detail/singleton_manager.hpp"
......
...@@ -52,7 +52,6 @@ ...@@ -52,7 +52,6 @@
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/detail/demangle.hpp" #include "cppa/detail/demangle.hpp"
#include "cppa/detail/actor_registry.hpp" #include "cppa/detail/actor_registry.hpp"
......
...@@ -68,9 +68,9 @@ namespace cppa { namespace detail { ...@@ -68,9 +68,9 @@ namespace cppa { namespace detail {
{ "cppa::io::connection_handle", "@cn_hdl" }, { "cppa::io::connection_handle", "@cn_hdl" },
{ "cppa::message_header", "@header" }, { "cppa::message_header", "@header" },
{ "cppa::nullptr_t", "@null" }, { "cppa::nullptr_t", "@null" },
{ "cppa::unit_t", "@0" },
{ "cppa::util::buffer", "@buffer" }, { "cppa::util::buffer", "@buffer" },
{ "cppa::util::duration", "@duration" }, { "cppa::util::duration", "@duration" },
{ "cppa::util::void_type", "@0" },
{ "double", "double" }, { "double", "double" },
{ "float", "float" }, { "float", "float" },
{ "long double", "@ldouble" }, { "long double", "@ldouble" },
...@@ -126,7 +126,7 @@ const char* mapped_name_by_decorated_name(const char* cstr) { ...@@ -126,7 +126,7 @@ const char* mapped_name_by_decorated_name(const char* cstr) {
namespace { namespace {
inline bool operator==(const util::void_type&, const util::void_type&) { inline bool operator==(const unit_t&, const unit_t&) {
return true; return true;
} }
...@@ -154,9 +154,9 @@ inline void deserialize_impl(detail::handle<T>& hdl, deserializer* source) { ...@@ -154,9 +154,9 @@ inline void deserialize_impl(detail::handle<T>& hdl, deserializer* source) {
hdl = T::from_int(source->read<int32_t>()); hdl = T::from_int(source->read<int32_t>());
} }
inline void serialize_impl(const util::void_type&, serializer*) { } inline void serialize_impl(const unit_t&, serializer*) { }
inline void deserialize_impl(util::void_type&, deserializer*) { } inline void deserialize_impl(unit_t&, deserializer*) { }
void serialize_impl(const actor_ptr& ptr, serializer* sink) { void serialize_impl(const actor_ptr& ptr, serializer* sink) {
auto impl = sink->addressing(); auto impl = sink->addressing();
...@@ -693,7 +693,7 @@ class utim_impl : public uniform_type_info_map { ...@@ -693,7 +693,7 @@ class utim_impl : public uniform_type_info_map {
intptr_t >(mapping); intptr_t >(mapping);
// fill builtin types *in sorted order* (by uniform name) // fill builtin types *in sorted order* (by uniform name)
size_t i = 0; size_t i = 0;
m_builtin_types[i++] = &m_type_void; // @0 m_builtin_types[i++] = &m_type_unit; // @0
m_builtin_types[i++] = &m_ac_hdl; // @ac_hdl m_builtin_types[i++] = &m_ac_hdl; // @ac_hdl
m_builtin_types[i++] = &m_type_actor; // @actor m_builtin_types[i++] = &m_type_actor; // @actor
m_builtin_types[i++] = &m_type_atom; // @atom m_builtin_types[i++] = &m_type_atom; // @atom
...@@ -824,7 +824,7 @@ class utim_impl : public uniform_type_info_map { ...@@ -824,7 +824,7 @@ class utim_impl : public uniform_type_info_map {
uti_impl<any_tuple> m_type_tuple; uti_impl<any_tuple> m_type_tuple;
uti_impl<util::duration> m_type_duration; uti_impl<util::duration> m_type_duration;
uti_impl<message_header> m_type_header; uti_impl<message_header> m_type_header;
uti_impl<util::void_type> m_type_void; uti_impl<unit_t> m_type_unit;
uti_impl<atom_value> m_type_atom; uti_impl<atom_value> m_type_atom;
uti_impl<std::string> m_type_str; uti_impl<std::string> m_type_str;
uti_impl<std::u16string> m_type_u16str; uti_impl<std::u16string> m_type_u16str;
......
...@@ -442,17 +442,17 @@ int main() { ...@@ -442,17 +442,17 @@ int main() {
CPPA_CHECK(name == "foo" || name == "bar"); CPPA_CHECK(name == "foo" || name == "bar");
return name == "foo" || name == "bar"; return name == "foo" || name == "bar";
}, },
on("-p", arg_match) >> [&](const string& port) -> bool { on("-p", arg_match) >> [&](const string& port) -> match_hint {
auto i = toint(port); auto i = toint(port);
if (i) { if (i) {
CPPA_CHECK_EQUAL(*i, 2); CPPA_CHECK_EQUAL(*i, 2);
return true; return match_hint::handle;
} }
else return false; else return match_hint::skip;
}, },
on_arg_match >> [](const string& arg) -> bool{ on_arg_match >> [](const string& arg) -> match_hint {
CPPA_FAILURE("unexpected string: " << arg); CPPA_FAILURE("unexpected string: " << arg);
return false; return match_hint::skip;
} }
); );
CPPA_CHECK_EQUAL(success, true); CPPA_CHECK_EQUAL(success, true);
...@@ -491,9 +491,9 @@ int main() { ...@@ -491,9 +491,9 @@ int main() {
} }
behavior bhvr1 = ( behavior bhvr1 = (
on<int>() >> [&](int i) -> bool { on<int>() >> [&](int i) -> match_hint {
last_invoked_fun = "<int>@1"; last_invoked_fun = "<int>@1";
return i != 42; return (i == 42) ? match_hint::skip : match_hint::handle;
}, },
on<float>() >> [&] { on<float>() >> [&] {
last_invoked_fun = "<float>@2"; last_invoked_fun = "<float>@2";
......
...@@ -44,7 +44,7 @@ int main() { ...@@ -44,7 +44,7 @@ int main() {
using tri_type = optional_variant<void, int, double, float>; using tri_type = optional_variant<void, int, double, float>;
tri_type t0; tri_type t0;
tri_type t1{util::void_type{}}; tri_type t1{unit};
tri_type t2{0}; tri_type t2{0};
tri_type t3{0.0}; tri_type t3{0.0};
tri_type t4{0.0f}; tri_type t4{0.0f};
......
...@@ -258,7 +258,7 @@ int main() { ...@@ -258,7 +258,7 @@ int main() {
self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB()); self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB());
timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere")) timed_sync_send(c, std::chrono::milliseconds(500), atom("HiThere"))
.then(CPPA_FAILURE_CB("C replied to 'HiThere'!")) .then(CPPA_FAILURE_CB("C replied to 'HiThere'!"))
.continue_with(CPPA_FAILURE_CB("bad continuation")); .continue_with(CPPA_FAILURE_CB("continuation erroneously invoked"));
self->exec_behavior_stack(); self->exec_behavior_stack();
CPPA_CHECK_EQUAL(timeout_occured, true); CPPA_CHECK_EQUAL(timeout_occured, true);
self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB()); self->on_sync_failure(CPPA_UNEXPECTED_MSG_CB());
......
...@@ -76,14 +76,16 @@ optional<int> str2int(const std::string& str) { ...@@ -76,14 +76,16 @@ optional<int> str2int(const std::string& str) {
} }
#define CPPA_CHECK_INVOKED(FunName, Args) \ #define CPPA_CHECK_INVOKED(FunName, Args) \
if ( ( FunName Args ) == false || invoked != #FunName ) { \ invoked.clear(); \
if ( !( FunName Args ) || invoked != #FunName ) { \
CPPA_FAILURE("invocation of " #FunName " failed"); \ CPPA_FAILURE("invocation of " #FunName " failed"); \
} invoked = "" } else CPPA_CHECKPOINT()
#define CPPA_CHECK_NOT_INVOKED(FunName, Args) \ #define CPPA_CHECK_NOT_INVOKED(FunName, Args) \
if ( ( FunName Args ) == true || invoked == #FunName ) { \ invoked.clear(); \
if ( FunName Args || invoked == #FunName ) { \
CPPA_FAILURE(#FunName " erroneously invoked"); \ CPPA_FAILURE(#FunName " erroneously invoked"); \
} invoked = "" } else CPPA_CHECKPOINT()
struct dummy_receiver : event_based_actor { struct dummy_receiver : event_based_actor {
void init() { void init() {
...@@ -164,9 +166,9 @@ void check_guards() { ...@@ -164,9 +166,9 @@ void check_guards() {
CPPA_CHECK_NOT_INVOKED(f02, (2, 1)); CPPA_CHECK_NOT_INVOKED(f02, (2, 1));
CPPA_CHECK_INVOKED(f02, (42, 21)); CPPA_CHECK_INVOKED(f02, (42, 21));
CPPA_CHECK(f02.invoke(make_cow_tuple(42, 21))); CPPA_CHECK(f02(make_cow_tuple(42, 21)));
CPPA_CHECK_EQUAL(invoked, "f02"); CPPA_CHECK_EQUAL(invoked, "f02");
invoked = ""; invoked.clear();
auto f03 = on(42, val<int>) >> [&](const int& a, int&) { invoked = "f03"; CPPA_CHECK_EQUAL(a, 42); }; auto f03 = on(42, val<int>) >> [&](const int& a, int&) { invoked = "f03"; CPPA_CHECK_EQUAL(a, 42); };
CPPA_CHECK_NOT_INVOKED(f03, (0, 0)); CPPA_CHECK_NOT_INVOKED(f03, (0, 0));
...@@ -200,14 +202,14 @@ void check_guards() { ...@@ -200,14 +202,14 @@ void check_guards() {
CPPA_CHECK_NOT_INVOKED(f07, (0)); CPPA_CHECK_NOT_INVOKED(f07, (0));
CPPA_CHECK_NOT_INVOKED(f07, (1)); CPPA_CHECK_NOT_INVOKED(f07, (1));
CPPA_CHECK_INVOKED(f07, (2)); CPPA_CHECK_INVOKED(f07, (2));
CPPA_CHECK(f07.invoke(make_cow_tuple(2))); CPPA_CHECK(f07(make_cow_tuple(2)));
int f08_val = 666; int f08_val = 666;
auto f08 = on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; }; auto f08 = on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; };
CPPA_CHECK_INVOKED(f08, (f08_val)); CPPA_CHECK_INVOKED(f08, (f08_val));
CPPA_CHECK_EQUAL(f08_val, 8); CPPA_CHECK_EQUAL(f08_val, 8);
any_tuple f08_any_val = make_cow_tuple(666); any_tuple f08_any_val = make_cow_tuple(666);
CPPA_CHECK(f08.invoke(f08_any_val)); CPPA_CHECK(f08(f08_any_val));
CPPA_CHECK_EQUAL(f08_any_val.get_as<int>(0), 8); CPPA_CHECK_EQUAL(f08_any_val.get_as<int>(0), 8);
int f09_val = 666; int f09_val = 666;
...@@ -216,13 +218,13 @@ void check_guards() { ...@@ -216,13 +218,13 @@ void check_guards() {
CPPA_CHECK_INVOKED(f09, ("0", f09_val)); CPPA_CHECK_INVOKED(f09, ("0", f09_val));
CPPA_CHECK_EQUAL(f09_val, 9); CPPA_CHECK_EQUAL(f09_val, 9);
any_tuple f09_any_val = make_cow_tuple("0", 666); any_tuple f09_any_val = make_cow_tuple("0", 666);
CPPA_CHECK(f09.invoke(f09_any_val)); CPPA_CHECK(f09(f09_any_val));
CPPA_CHECK_EQUAL(f09_any_val.get_as<int>(1), 9); CPPA_CHECK_EQUAL(f09_any_val.get_as<int>(1), 9);
f09_any_val.get_as_mutable<int>(1) = 666; f09_any_val.get_as_mutable<int>(1) = 666;
any_tuple f09_any_val_copy{f09_any_val}; any_tuple f09_any_val_copy{f09_any_val};
CPPA_CHECK(f09_any_val.at(0) == f09_any_val_copy.at(0)); CPPA_CHECK(f09_any_val.at(0) == f09_any_val_copy.at(0));
// detaches f09_any_val from f09_any_val_copy // detaches f09_any_val from f09_any_val_copy
CPPA_CHECK(f09.invoke(f09_any_val)); CPPA_CHECK(f09(f09_any_val));
CPPA_CHECK_EQUAL(f09_any_val.get_as<int>(1), 9); CPPA_CHECK_EQUAL(f09_any_val.get_as<int>(1), 9);
CPPA_CHECK_EQUAL(f09_any_val_copy.get_as<int>(1), 666); CPPA_CHECK_EQUAL(f09_any_val_copy.get_as<int>(1), 666);
// no longer the same data // no longer the same data
......
...@@ -74,7 +74,7 @@ int main() { ...@@ -74,7 +74,7 @@ int main() {
"@str", "@u16str", "@u32str", // strings "@str", "@u16str", "@u32str", // strings
"@strmap", // string containers "@strmap", // string containers
"float", "double", "@ldouble", // floating points "float", "double", "@ldouble", // floating points
"@0", // cppa::util::void_type "@0", // cppa::util::unit_t
// default announced cppa types // default announced cppa types
"@ac_hdl", // io::accept_handle "@ac_hdl", // io::accept_handle
"@cn_hdl", // io::connection_handle "@cn_hdl", // io::connection_handle
......
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