Commit 8a14da68 authored by Dominik Charousset's avatar Dominik Charousset

added partial_function::or_else

this feature allows users to define the behavior of an actor by
concatenating partial functions
parent 85f7e0ff
...@@ -95,6 +95,7 @@ set(LIBCPPA_SRC ...@@ -95,6 +95,7 @@ set(LIBCPPA_SRC
src/any_tuple.cpp src/any_tuple.cpp
src/atom.cpp src/atom.cpp
src/attachable.cpp src/attachable.cpp
src/behavior.cpp
src/behavior_stack.cpp src/behavior_stack.cpp
src/binary_deserializer.cpp src/binary_deserializer.cpp
src/binary_serializer.cpp src/binary_serializer.cpp
......
...@@ -209,6 +209,7 @@ src/actor_registry.cpp ...@@ -209,6 +209,7 @@ src/actor_registry.cpp
src/any_tuple.cpp src/any_tuple.cpp
src/atom.cpp src/atom.cpp
src/attachable.cpp src/attachable.cpp
src/behavior.cpp
src/behavior_stack.cpp src/behavior_stack.cpp
src/binary_deserializer.cpp src/binary_deserializer.cpp
src/binary_serializer.cpp src/binary_serializer.cpp
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <type_traits> #include <type_traits>
#include "cppa/match_expr.hpp" #include "cppa/match_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/timeout_definition.hpp" #include "cppa/timeout_definition.hpp"
#include "cppa/util/tbind.hpp" #include "cppa/util/tbind.hpp"
...@@ -47,12 +46,14 @@ ...@@ -47,12 +46,14 @@
namespace cppa { namespace cppa {
class partial_function;
/** /**
* @brief Describes the behavior of an actor. * @brief Describes the behavior of an actor.
*/ */
class behavior { class behavior {
typedef partial_function super; friend class partial_function;
public: public:
...@@ -64,9 +65,9 @@ class behavior { ...@@ -64,9 +65,9 @@ class behavior {
behavior& operator=(behavior&&) = default; behavior& operator=(behavior&&) = default;
behavior& operator=(const behavior&) = default; behavior& operator=(const behavior&) = default;
inline behavior(partial_function fun) : m_impl(std::move(fun.m_impl)) { } behavior(const partial_function& fun);
inline behavior(partial_function::impl_ptr ptr) : m_impl(std::move(ptr)) { } inline behavior(impl_ptr ptr) : m_impl(std::move(ptr)) { }
template<typename F> template<typename F>
behavior(const timeout_definition<F>& arg) behavior(const timeout_definition<F>& arg)
...@@ -109,17 +110,6 @@ class behavior { ...@@ -109,17 +110,6 @@ class behavior {
}; };
template<typename Arg0, typename... Args>
typename util::if_else<
util::disjunction<
is_timeout_definition<Arg0>,
is_timeout_definition<Args>...>,
behavior,
util::wrapped<partial_function> >::type
match_expr_convert(const Arg0& arg0, const Args&... args) {
return {match_expr_concat(arg0, args...)};
}
template<typename... Lhs, typename F> template<typename... Lhs, typename F>
inline behavior operator,(const match_expr<Lhs...>& lhs, inline behavior operator,(const match_expr<Lhs...>& lhs,
const timeout_definition<F>& rhs) { const timeout_definition<F>& rhs) {
......
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
#define BEHAVIOR_IMPL_HPP #define BEHAVIOR_IMPL_HPP
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -56,6 +59,38 @@ class behavior_impl : public ref_counted { ...@@ -56,6 +59,38 @@ class behavior_impl : public ref_counted {
return m_timeout; return m_timeout;
} }
typedef intrusive_ptr<behavior_impl> pointer;
virtual pointer copy(const generic_timeout_definition& tdef) const = 0;
inline pointer or_else(const pointer& other) {
CPPA_REQUIRE(other != nullptr);
struct combinator : behavior_impl {
pointer first;
pointer second;
bool invoke(any_tuple& arg) {
return first->invoke(arg) || second->invoke(arg);
}
bool invoke(const any_tuple& arg) {
return first->invoke(arg) || second->invoke(arg);
}
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
return second->handle_timeout();
}
pointer copy(const generic_timeout_definition& tdef) const {
return new combinator(first, second->copy(tdef));
}
combinator(const pointer& p0, const pointer& p1)
: behavior_impl(p1->timeout()), first(p0), second(p1) { }
};
return new combinator(this, other);
}
private: private:
util::duration m_timeout; util::duration m_timeout;
...@@ -94,6 +129,11 @@ class default_behavior_impl : public behavior_impl { ...@@ -94,6 +129,11 @@ class default_behavior_impl : public behavior_impl {
return m_expr.can_invoke(tup); return m_expr.can_invoke(tup);
} }
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(); } void handle_timeout() { m_fun(); }
private: private:
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include "cppa/option.hpp" #include "cppa/option.hpp"
#include "cppa/guard_expr.hpp" #include "cppa/guard_expr.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/tpartial_function.hpp" #include "cppa/tpartial_function.hpp"
#include "cppa/util/rm_ref.hpp" #include "cppa/util/rm_ref.hpp"
...@@ -49,6 +48,7 @@ ...@@ -49,6 +48,7 @@
#include "cppa/detail/projection.hpp" #include "cppa/detail/projection.hpp"
#include "cppa/detail/value_guard.hpp" #include "cppa/detail/value_guard.hpp"
#include "cppa/detail/pseudo_tuple.hpp" #include "cppa/detail/pseudo_tuple.hpp"
#include "cppa/detail/behavior_impl.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -733,14 +733,14 @@ class match_expr { ...@@ -733,14 +733,14 @@ class match_expr {
bool defined_at(const any_tuple& tup) { bool defined_at(const any_tuple& tup) {
return pfun.can_invoke(tup); return pfun.can_invoke(tup);
} }
}; typedef typename detail::behavior_impl::pointer pointer;
pointer copy(const generic_timeout_definition& tdef) const {
inline partial_function as_partial_function() const { return new_default_behavior_impl(pfun, tdef.timeout, tdef.handler);
return {partial_function::impl_ptr{new pfun_impl(*this)}};
} }
};
inline operator partial_function() const { intrusive_ptr<detail::behavior_impl> as_behavior_impl() const {
return as_partial_function(); return new pfun_impl(*this);
} }
private: private:
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
...@@ -67,6 +68,10 @@ class partial_function { ...@@ -67,6 +68,10 @@ class partial_function {
partial_function& operator=(partial_function&&) = default; partial_function& operator=(partial_function&&) = default;
partial_function& operator=(const partial_function&) = default; partial_function& operator=(const partial_function&) = default;
template<typename... Cases>
partial_function(const match_expr<Cases...>& mexpr)
: m_impl(mexpr.as_behavior_impl()) { }
partial_function(impl_ptr ptr); partial_function(impl_ptr ptr);
inline bool undefined() const { inline bool undefined() const {
...@@ -82,12 +87,54 @@ class partial_function { ...@@ -82,12 +87,54 @@ class partial_function {
return (m_impl) && m_impl->invoke(std::forward<T>(arg)); return (m_impl) && m_impl->invoke(std::forward<T>(arg));
} }
inline partial_function or_else(const partial_function& other) const {
return m_impl->or_else(other.m_impl);
}
inline behavior or_else(const behavior& other) const {
return behavior{m_impl->or_else(other.m_impl)};
}
template<typename F>
inline behavior or_else(const timeout_definition<F>& tdef) const {
generic_timeout_definition gtd{tdef.timeout, tdef.handler};
return behavior{m_impl->copy(gtd)};
}
template<typename... Cases>
inline partial_function or_else(const match_expr<Cases...>& mexpr) const {
return m_impl->or_else(mexpr.as_behavior_impl());
}
template<typename Arg0, typename Arg1, typename... Args>
typename util::if_else<
util::disjunction<
is_timeout_definition<Arg0>,
is_timeout_definition<Arg1>,
is_timeout_definition<Args>...>,
behavior,
util::wrapped<partial_function> >::type
or_else(const Arg0& arg0, const Arg1& arg1, const Args&... args) const {
return m_impl->or_else(match_expr_concat(arg0, arg1, args...));
}
private: private:
impl_ptr m_impl; impl_ptr m_impl;
}; };
template<typename Arg0, typename... Args>
typename util::if_else<
util::disjunction<
is_timeout_definition<Arg0>,
is_timeout_definition<Args>...>,
behavior,
util::wrapped<partial_function> >::type
match_expr_convert(const Arg0& arg0, const Args&... args) {
return {match_expr_concat(arg0, args...)};
}
} // namespace cppa } // namespace cppa
#endif // CPPA_PARTIAL_FUNCTION_HPP #endif // CPPA_PARTIAL_FUNCTION_HPP
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef TIMEOUT_DEFINITION_HPP #ifndef TIMEOUT_DEFINITION_HPP
#define TIMEOUT_DEFINITION_HPP #define TIMEOUT_DEFINITION_HPP
#include <functional>
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
namespace cppa { namespace cppa {
...@@ -47,6 +49,8 @@ struct is_timeout_definition : std::false_type { }; ...@@ -47,6 +49,8 @@ struct is_timeout_definition : std::false_type { };
template<typename F> template<typename F>
struct is_timeout_definition<timeout_definition<F> > : std::true_type { }; struct is_timeout_definition<timeout_definition<F> > : std::true_type { };
typedef timeout_definition<std::function<void()> > generic_timeout_definition;
} // namespace cppa } // namespace cppa
#endif // TIMEOUT_DEFINITION_HPP #endif // TIMEOUT_DEFINITION_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include "cppa/behavior.hpp"
#include "cppa/partial_function.hpp"
namespace cppa {
behavior::behavior(const partial_function& fun) : m_impl(fun.m_impl) { }
} // namespace cppa
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/behavior.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
namespace cppa { namespace cppa {
......
...@@ -391,5 +391,30 @@ int main() { ...@@ -391,5 +391,30 @@ int main() {
cout << "success: " << success << endl; cout << "success: " << success << endl;
cout << "check combined partial function matching" << endl;
std::string last_invoked_fun;
auto check = [&](partial_function& pf, const any_tuple& tup, const string& str) {
last_invoked_fun = "";
pf(tup);
CPPA_CHECK_EQUAL(str, last_invoked_fun);
};
partial_function pf0 = (
on<int,int>() >> [&] { last_invoked_fun = "<int,int>@1"; },
on<float>() >> [&] { last_invoked_fun = "<float>@2"; }
);
auto pf1 = pf0.or_else(
on<int,int>() >> [&] { last_invoked_fun = "<int,int>@3"; },
on<string>() >> [&] { last_invoked_fun = "<string>@4"; }
);
check(pf0, make_any_tuple(1, 2), "<int,int>@1");
check(pf1, make_any_tuple(1, 2), "<int,int>@1");
check(pf0, make_any_tuple("hi"), "");
check(pf1, make_any_tuple("hi"), "<string>@4");
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
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