Commit a9300af4 authored by neverlord's avatar neverlord

RIP invoke_rules, long live partial_function

parent 550a4200
...@@ -4,12 +4,12 @@ lib_LTLIBRARIES = libcppa.la ...@@ -4,12 +4,12 @@ lib_LTLIBRARIES = libcppa.la
libcppa_la_SOURCES = \ libcppa_la_SOURCES = \
src/abstract_event_based_actor.cpp \ src/abstract_event_based_actor.cpp \
src/abstract_scheduled_actor.cpp \
src/abstract_tuple.cpp \ src/abstract_tuple.cpp \
src/scheduled_actor.cpp \
src/actor_count.cpp \
src/actor.cpp \ src/actor.cpp \
src/actor_proxy_cache.cpp \ src/actor_count.cpp \
src/actor_proxy.cpp \ src/actor_proxy.cpp \
src/actor_proxy_cache.cpp \
src/actor_registry.cpp \ src/actor_registry.cpp \
src/addressed_message.cpp \ src/addressed_message.cpp \
src/any_tuple.cpp \ src/any_tuple.cpp \
...@@ -18,35 +18,35 @@ libcppa_la_SOURCES = \ ...@@ -18,35 +18,35 @@ libcppa_la_SOURCES = \
src/binary_deserializer.cpp \ src/binary_deserializer.cpp \
src/binary_serializer.cpp \ src/binary_serializer.cpp \
src/channel.cpp \ src/channel.cpp \
src/local_actor.cpp \
src/converted_thread_context.cpp \ src/converted_thread_context.cpp \
src/cppa.cpp \ src/cppa.cpp \
src/event_based_actor.cpp \
src/delegate.cpp \ src/delegate.cpp \
src/demangle.cpp \ src/demangle.cpp \
src/deserializer.cpp \ src/deserializer.cpp \
src/duration.cpp \ src/duration.cpp \
src/empty_tuple.cpp \ src/empty_tuple.cpp \
src/event_based_actor.cpp \
src/exception.cpp \ src/exception.cpp \
src/fiber.cpp \ src/fiber.cpp \
src/group.cpp \ src/group.cpp \
src/group_manager.cpp \ src/group_manager.cpp \
src/intermediate.cpp \ src/intermediate.cpp \
src/invokable.cpp \ src/invokable.cpp \
src/invoke_rules.cpp \ src/local_actor.cpp \
src/mailman.cpp \ src/mailman.cpp \
src/mock_scheduler.cpp \ src/mock_scheduler.cpp \
src/native_socket.cpp \ src/native_socket.cpp \
src/network_manager.cpp \ src/network_manager.cpp \
src/object_array.cpp \
src/object.cpp \ src/object.cpp \
src/object_array.cpp \
src/partial_function.cpp \
src/post_office.cpp \ src/post_office.cpp \
src/post_office_msg.cpp \ src/post_office_msg.cpp \
src/primitive_variant.cpp \ src/primitive_variant.cpp \
src/process_information.cpp \ src/process_information.cpp \
src/receive.cpp \ src/receive.cpp \
src/ripemd_160.cpp \ src/ripemd_160.cpp \
src/abstract_scheduled_actor.cpp \ src/scheduled_actor.cpp \
src/scheduler.cpp \ src/scheduler.cpp \
src/self.cpp \ src/self.cpp \
src/serializer.cpp \ src/serializer.cpp \
...@@ -70,11 +70,12 @@ endif ...@@ -70,11 +70,12 @@ endif
nobase_library_include_HEADERS = \ nobase_library_include_HEADERS = \
cppa/abstract_actor.hpp \ cppa/abstract_actor.hpp \
cppa/scheduled_actor.hpp \ cppa/abstract_event_based_actor.hpp \
cppa/actor.hpp \ cppa/actor.hpp \
cppa/actor_proxy.hpp \ cppa/actor_proxy.hpp \
cppa/announce.hpp \ cppa/announce.hpp \
cppa/any_tuple.hpp \ cppa/any_tuple.hpp \
cppa/any_tuple_view.hpp \
cppa/anything.hpp \ cppa/anything.hpp \
cppa/atom.hpp \ cppa/atom.hpp \
cppa/attachable.hpp \ cppa/attachable.hpp \
...@@ -83,15 +84,10 @@ nobase_library_include_HEADERS = \ ...@@ -83,15 +84,10 @@ nobase_library_include_HEADERS = \
cppa/binary_serializer.hpp \ cppa/binary_serializer.hpp \
cppa/channel.hpp \ cppa/channel.hpp \
cppa/config.hpp \ cppa/config.hpp \
cppa/local_actor.hpp \
cppa/match.hpp \
cppa/cow_ptr.hpp \ cppa/cow_ptr.hpp \
cppa/cppa.hpp \ cppa/cppa.hpp \
cppa/deserializer.hpp \ cppa/deserializer.hpp \
cppa/either.hpp \ cppa/detail/abstract_scheduled_actor.hpp \
cppa/event_based_actor.hpp \
cppa/event_based_actor_base.hpp \
cppa/abstract_event_based_actor.hpp \
cppa/detail/abstract_tuple.hpp \ cppa/detail/abstract_tuple.hpp \
cppa/detail/actor_count.hpp \ cppa/detail/actor_count.hpp \
cppa/detail/actor_proxy_cache.hpp \ cppa/detail/actor_proxy_cache.hpp \
...@@ -128,7 +124,6 @@ nobase_library_include_HEADERS = \ ...@@ -128,7 +124,6 @@ nobase_library_include_HEADERS = \
cppa/detail/ptype_to_type.hpp \ cppa/detail/ptype_to_type.hpp \
cppa/detail/receive_loop_helper.hpp \ cppa/detail/receive_loop_helper.hpp \
cppa/detail/ref_counted_impl.hpp \ cppa/detail/ref_counted_impl.hpp \
cppa/detail/abstract_scheduled_actor.hpp \
cppa/detail/serialize_tuple.hpp \ cppa/detail/serialize_tuple.hpp \
cppa/detail/singleton_manager.hpp \ cppa/detail/singleton_manager.hpp \
cppa/detail/swap_bytes.hpp \ cppa/detail/swap_bytes.hpp \
...@@ -145,6 +140,9 @@ nobase_library_include_HEADERS = \ ...@@ -145,6 +140,9 @@ nobase_library_include_HEADERS = \
cppa/detail/uniform_type_info_map.hpp \ cppa/detail/uniform_type_info_map.hpp \
cppa/detail/yield_interface.hpp \ cppa/detail/yield_interface.hpp \
cppa/detail/yielding_actor.hpp \ cppa/detail/yielding_actor.hpp \
cppa/either.hpp \
cppa/event_based_actor.hpp \
cppa/event_based_actor_base.hpp \
cppa/exception.hpp \ cppa/exception.hpp \
cppa/exit_reason.hpp \ cppa/exit_reason.hpp \
cppa/from_string.hpp \ cppa/from_string.hpp \
...@@ -152,16 +150,19 @@ nobase_library_include_HEADERS = \ ...@@ -152,16 +150,19 @@ nobase_library_include_HEADERS = \
cppa/get.hpp \ cppa/get.hpp \
cppa/group.hpp \ cppa/group.hpp \
cppa/intrusive_ptr.hpp \ cppa/intrusive_ptr.hpp \
cppa/invoke_rules.hpp \ cppa/local_actor.hpp \
cppa/match.hpp \
cppa/object.hpp \ cppa/object.hpp \
cppa/on.hpp \ cppa/on.hpp \
cppa/option.hpp \ cppa/option.hpp \
cppa/partial_function.hpp \
cppa/pattern.hpp \ cppa/pattern.hpp \
cppa/primitive_type.hpp \ cppa/primitive_type.hpp \
cppa/primitive_variant.hpp \ cppa/primitive_variant.hpp \
cppa/process_information.hpp \ cppa/process_information.hpp \
cppa/receive.hpp \ cppa/receive.hpp \
cppa/ref_counted.hpp \ cppa/ref_counted.hpp \
cppa/scheduled_actor.hpp \
cppa/scheduler.hpp \ cppa/scheduler.hpp \
cppa/scheduling_hint.hpp \ cppa/scheduling_hint.hpp \
cppa/self.hpp \ cppa/self.hpp \
...@@ -190,14 +191,14 @@ nobase_library_include_HEADERS = \ ...@@ -190,14 +191,14 @@ nobase_library_include_HEADERS = \
cppa/util/fiber.hpp \ cppa/util/fiber.hpp \
cppa/util/fixed_vector.hpp \ cppa/util/fixed_vector.hpp \
cppa/util/has_copy_member_fun.hpp \ cppa/util/has_copy_member_fun.hpp \
cppa/util.hpp \ cppa/util/if_else.hpp \
cppa/util/is_array_of.hpp \ cppa/util/is_array_of.hpp \
cppa/util/is_builtin.hpp \ cppa/util/is_builtin.hpp \
cppa/util/if_else.hpp \
cppa/util/is_comparable.hpp \ cppa/util/is_comparable.hpp \
cppa/util/is_copyable.hpp \ cppa/util/is_copyable.hpp \
cppa/util/is_forward_iterator.hpp \ cppa/util/is_forward_iterator.hpp \
cppa/util/is_iterable.hpp \ cppa/util/is_iterable.hpp \
cppa/util/is_iterable.hpp \
cppa/util/is_legal_tuple_type.hpp \ cppa/util/is_legal_tuple_type.hpp \
cppa/util/is_manipulator.hpp \ cppa/util/is_manipulator.hpp \
cppa/util/is_mutable_ref.hpp \ cppa/util/is_mutable_ref.hpp \
...@@ -210,11 +211,12 @@ nobase_library_include_HEADERS = \ ...@@ -210,11 +211,12 @@ nobase_library_include_HEADERS = \
cppa/util/replace_type.hpp \ cppa/util/replace_type.hpp \
cppa/util/ripemd_160.hpp \ cppa/util/ripemd_160.hpp \
cppa/util/rm_ref.hpp \ cppa/util/rm_ref.hpp \
cppa/util/static_foreach.hpp \
cppa/util/shared_lock_guard.hpp \ cppa/util/shared_lock_guard.hpp \
cppa/util/shared_spinlock.hpp \ cppa/util/shared_spinlock.hpp \
cppa/util/single_reader_queue.hpp \ cppa/util/single_reader_queue.hpp \
cppa/util/singly_linked_list.hpp \ cppa/util/singly_linked_list.hpp \
cppa/util/static_foreach.hpp \
cppa/util/tbind.hpp \
cppa/util/type_list.hpp \ cppa/util/type_list.hpp \
cppa/util/type_pair.hpp \ cppa/util/type_pair.hpp \
cppa/util/upgrade_lock_guard.hpp \ cppa/util/upgrade_lock_guard.hpp \
......
...@@ -3,7 +3,6 @@ cppa/tuple.hpp ...@@ -3,7 +3,6 @@ cppa/tuple.hpp
unit_testing/main.cpp unit_testing/main.cpp
cppa/util/void_type.hpp cppa/util/void_type.hpp
cppa/util/type_list.hpp cppa/util/type_list.hpp
cppa/util.hpp
cppa/util/is_one_of.hpp cppa/util/is_one_of.hpp
cppa/util/conjunction.hpp cppa/util/conjunction.hpp
cppa/util/disjunction.hpp cppa/util/disjunction.hpp
...@@ -34,7 +33,6 @@ cppa/util/is_copyable.hpp ...@@ -34,7 +33,6 @@ cppa/util/is_copyable.hpp
cppa/util/has_copy_member_fun.hpp cppa/util/has_copy_member_fun.hpp
cppa/detail/intermediate.hpp cppa/detail/intermediate.hpp
cppa/detail/invokable.hpp cppa/detail/invokable.hpp
cppa/invoke_rules.hpp
cppa/on.hpp cppa/on.hpp
unit_testing/test__serialization.cpp unit_testing/test__serialization.cpp
cppa/serializer.hpp cppa/serializer.hpp
...@@ -176,7 +174,6 @@ cppa/detail/receive_loop_helper.hpp ...@@ -176,7 +174,6 @@ cppa/detail/receive_loop_helper.hpp
cppa/util/wrapped.hpp cppa/util/wrapped.hpp
cppa/detail/boxed.hpp cppa/detail/boxed.hpp
cppa/detail/unboxed.hpp cppa/detail/unboxed.hpp
src/invoke_rules.cpp
src/abstract_tuple.cpp src/abstract_tuple.cpp
cppa/util/duration.hpp cppa/util/duration.hpp
src/duration.cpp src/duration.cpp
...@@ -262,3 +259,5 @@ cppa/detail/disablable_delete.hpp ...@@ -262,3 +259,5 @@ cppa/detail/disablable_delete.hpp
unit_testing/test__fixed_vector.cpp unit_testing/test__fixed_vector.cpp
cppa/detail/tuple_cast_impl.hpp cppa/detail/tuple_cast_impl.hpp
cppa/match.hpp cppa/match.hpp
cppa/partial_function.hpp
src/partial_function.cpp
...@@ -52,60 +52,125 @@ namespace cppa { ...@@ -52,60 +52,125 @@ namespace cppa {
template<class Base> template<class Base>
class abstract_actor : public Base class abstract_actor : public Base
{ {
typedef detail::lock_guard<detail::mutex> guard_type;
//typedef std::lock_guard<std::mutex> guard_type;
typedef std::unique_ptr<attachable> attachable_ptr;
// true if the associated thread has finished execution
std::atomic<std::uint32_t> m_exit_reason;
// guards access to m_exited, m_subscriptions and m_links
detail::mutex m_mtx;
// links to other actors
std::vector<actor_ptr> m_links;
// code that is executed on cleanup typedef std::unique_ptr<attachable> attachable_ptr;
std::vector<attachable_ptr> m_attachables; typedef detail::lock_guard<detail::mutex> guard_type;
public: public:
struct queue_node struct queue_node
{ {
friend class abstract_actor;
friend class queue_node_ptr;
queue_node* next; queue_node* next;
actor_ptr sender; actor_ptr sender;
any_tuple msg; any_tuple msg;
queue_node() : next(nullptr) { } queue_node() : next(nullptr) { }
queue_node(actor* from, any_tuple&& content) queue_node(actor* from, any_tuple&& content)
: next(nullptr), sender(from), msg(std::move(content)) : next(nullptr), sender(from), msg(std::move(content)) { }
queue_node(actor* from, any_tuple const& content)
: next(nullptr), sender(from), msg(content) { }
};
typedef std::unique_ptr<queue_node> queue_node_ptr;
bool attach(attachable* ptr) /*override*/
{
if (ptr == nullptr)
{ {
guard_type guard(m_mtx);
return m_exit_reason.load() == exit_reason::not_exited;
} }
queue_node(actor* from, any_tuple const& content) else
: next(nullptr), sender(from), msg(content) {
attachable_ptr uptr(ptr);
std::uint32_t reason;
// lifetime scope of guard
{
guard_type guard(m_mtx);
reason = m_exit_reason.load();
if (reason == exit_reason::not_exited)
{ {
m_attachables.push_back(std::move(uptr));
return true;
}
}
uptr->actor_exited(reason);
return false;
}
} }
};
typedef std::unique_ptr<queue_node> queue_node_ptr; void detach(attachable::token const& what) /*override*/
{
attachable_ptr uptr;
// lifetime scope of guard
{
guard_type guard(m_mtx);
auto end = m_attachables.end();
auto i = std::find_if(
m_attachables.begin(), end,
[&](attachable_ptr& p) { return p->matches(what); });
if (i != end)
{
uptr = std::move(*i);
m_attachables.erase(i);
}
}
// uptr will be destroyed here, without locked mutex
}
protected: void link_to(intrusive_ptr<actor>& other) /*override*/
{
(void) link_to_impl(other);
}
util::single_reader_queue<queue_node> m_mailbox; void unlink_from(intrusive_ptr<actor>& other) /*override*/
{
(void) unlink_from_impl(other);
}
private: bool remove_backlink(intrusive_ptr<actor>& other) /*override*/
{
if (other && other != this)
{
guard_type guard(m_mtx);
auto i = std::find(m_links.begin(), m_links.end(), other);
if (i != m_links.end())
{
m_links.erase(i);
return true;
}
}
return false;
}
// @pre m_mtx.locked() bool establish_backlink(intrusive_ptr<actor>& other) /*override*/
bool exited() const
{ {
return m_exit_reason.load() != exit_reason::not_exited; std::uint32_t reason = exit_reason::not_exited;
if (other && other != this)
{
guard_type guard(m_mtx);
reason = m_exit_reason.load();
if (reason == exit_reason::not_exited)
{
auto i = std::find(m_links.begin(), m_links.end(), other);
if (i == m_links.end())
{
m_links.push_back(other);
return true;
}
}
}
// send exit message without lock
if (reason != exit_reason::not_exited)
{
other->enqueue(this, make_tuple(atom(":Exit"), reason));
}
return false;
} }
protected: protected:
util::single_reader_queue<queue_node> m_mailbox;
template<typename T> template<typename T>
inline queue_node* fetch_node(actor* sender, T&& msg) inline queue_node* fetch_node(actor* sender, T&& msg)
{ {
...@@ -185,105 +250,22 @@ class abstract_actor : public Base ...@@ -185,105 +250,22 @@ class abstract_actor : public Base
return false; return false;
} }
public: private:
bool attach(attachable* ptr) /*override*/
{
if (ptr == nullptr)
{
guard_type guard(m_mtx);
return m_exit_reason.load() == exit_reason::not_exited;
}
else
{
attachable_ptr uptr(ptr);
std::uint32_t reason;
// lifetime scope of guard
{
guard_type guard(m_mtx);
reason = m_exit_reason.load();
if (reason == exit_reason::not_exited)
{
m_attachables.push_back(std::move(uptr));
return true;
}
}
uptr->actor_exited(reason);
return false;
}
}
void detach(attachable::token const& what) /*override*/
{
attachable_ptr uptr;
// lifetime scope of guard
{
guard_type guard(m_mtx);
auto end = m_attachables.end();
auto i = std::find_if(m_attachables.begin(),
end,
[&](attachable_ptr& ptr)
{
return ptr->matches(what);
});
if (i != end)
{
uptr = std::move(*i);
m_attachables.erase(i);
}
}
// uptr will be destroyed here, without locked mutex
}
void link_to(intrusive_ptr<actor>& other) /*override*/
{
(void) link_to_impl(other);
}
void unlink_from(intrusive_ptr<actor>& other) /*override*/
{
(void) unlink_from_impl(other);
}
bool remove_backlink(intrusive_ptr<actor>& other) /*override*/ // @pre m_mtx.locked()
{ bool exited() const
if (other && other != this)
{
guard_type guard(m_mtx);
auto i = std::find(m_links.begin(), m_links.end(), other);
if (i != m_links.end())
{ {
m_links.erase(i); return m_exit_reason.load() != exit_reason::not_exited;
return true;
}
}
return false;
} }
bool establish_backlink(intrusive_ptr<actor>& other) /*override*/ // true if the associated thread has finished execution
{ std::atomic<std::uint32_t> m_exit_reason;
std::uint32_t reason = exit_reason::not_exited; // guards access to m_exited, m_subscriptions and m_links
if (other && other != this) detail::mutex m_mtx;
{ // links to other actors
guard_type guard(m_mtx); std::vector<actor_ptr> m_links;
reason = m_exit_reason.load(); // code that is executed on cleanup
if (reason == exit_reason::not_exited) std::vector<attachable_ptr> m_attachables;
{
auto i = std::find(m_links.begin(), m_links.end(), other);
if (i == m_links.end())
{
m_links.push_back(other);
return true;
}
}
}
// send exit message without lock
if (reason != exit_reason::not_exited)
{
other->enqueue(this, make_tuple(atom(":Exit"), reason));
}
return false;
}
}; };
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/either.hpp" #include "cppa/either.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/behavior.hpp"
#include "cppa/detail/disablable_delete.hpp" #include "cppa/detail/disablable_delete.hpp"
#include "cppa/detail/abstract_scheduled_actor.hpp" #include "cppa/detail/abstract_scheduled_actor.hpp"
...@@ -56,9 +56,9 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -56,9 +56,9 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
public: public:
void dequeue(invoke_rules&) /*override*/; void dequeue(behavior&) /*override*/;
void dequeue(timed_invoke_rules&) /*override*/; void dequeue(partial_function&) /*override*/;
void resume(util::fiber*, resume_callback* callback) /*override*/; void resume(util::fiber*, resume_callback* callback) /*override*/;
...@@ -74,31 +74,20 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -74,31 +74,20 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
template<typename Scheduler> template<typename Scheduler>
abstract_event_based_actor* abstract_event_based_actor*
attach_to_scheduler(void (*enqueue_fun)(Scheduler*, abstract_scheduled_actor*), attach_to_scheduler(void (*enq_fun)(Scheduler*, abstract_scheduled_actor*),
Scheduler* sched) Scheduler* sched)
{ {
m_enqueue_to_scheduler.reset(enqueue_fun, sched, this); m_enqueue_to_scheduler.reset(enq_fun, sched, this);
this->init(); this->init();
return this; return this;
} }
private:
void handle_message(queue_node_ptr& node,
invoke_rules& behavior);
void handle_message(queue_node_ptr& node,
timed_invoke_rules& behavior);
void handle_message(queue_node_ptr& node);
protected: protected:
abstract_event_based_actor(); abstract_event_based_actor();
// ownership flag + pointer // ownership flag + pointer
typedef either<std::unique_ptr<invoke_rules, detail::disablable_delete<invoke_rules>>, typedef std::unique_ptr<behavior, detail::disablable_delete<behavior>>
std::unique_ptr<timed_invoke_rules, detail::disablable_delete<timed_invoke_rules>>>
stack_element; stack_element;
queue_node_buffer m_buffer; queue_node_buffer m_buffer;
...@@ -132,6 +121,10 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor ...@@ -132,6 +121,10 @@ class abstract_event_based_actor : public detail::abstract_scheduled_actor
receive(std::forward<Args>(args)...); receive(std::forward<Args>(args)...);
} }
private:
void handle_message(queue_node_ptr& node);
}; };
} // namespace cppa } // namespace cppa
......
...@@ -56,17 +56,6 @@ typedef std::uint32_t actor_id; ...@@ -56,17 +56,6 @@ typedef std::uint32_t actor_id;
class actor : public channel class actor : public channel
{ {
bool m_is_proxy;
actor_id m_id;
process_information_ptr m_parent_process;
protected:
actor(process_information_ptr const& parent = process_information::get());
actor(std::uint32_t aid,
process_information_ptr const& parent = process_information::get());
public: public:
~actor(); ~actor();
...@@ -202,6 +191,20 @@ class actor : public channel ...@@ -202,6 +191,20 @@ class actor : public channel
*/ */
inline bool is_proxy() const; inline bool is_proxy() const;
protected:
actor(process_information_ptr const& parent = process_information::get());
actor(std::uint32_t aid,
process_information_ptr const& parent = process_information::get());
private:
actor_id m_id;
bool m_is_proxy;
process_information_ptr m_parent_process;
}; };
/** /**
......
...@@ -50,9 +50,6 @@ class actor_proxy : public abstract_actor<actor> ...@@ -50,9 +50,6 @@ class actor_proxy : public abstract_actor<actor>
typedef abstract_actor<actor> super; typedef abstract_actor<actor> super;
void forward_message(process_information_ptr const&,
actor*, any_tuple const&);
public: public:
actor_proxy(std::uint32_t mid, process_information_ptr const& parent); actor_proxy(std::uint32_t mid, process_information_ptr const& parent);
...@@ -77,6 +74,11 @@ class actor_proxy : public abstract_actor<actor> ...@@ -77,6 +74,11 @@ class actor_proxy : public abstract_actor<actor>
bool establish_backlink(intrusive_ptr<actor>& to); bool establish_backlink(intrusive_ptr<actor>& to);
public:
void forward_message(process_information_ptr const&,
actor*, any_tuple const&);
}; };
#endif // CPPA_DOCUMENTATION #endif // CPPA_DOCUMENTATION
......
...@@ -45,10 +45,6 @@ namespace cppa { ...@@ -45,10 +45,6 @@ namespace cppa {
class any_tuple class any_tuple
{ {
cow_ptr<detail::abstract_tuple> m_vals;
explicit any_tuple(cow_ptr<detail::abstract_tuple> const& vals);
public: public:
/** /**
...@@ -143,11 +139,22 @@ class any_tuple ...@@ -143,11 +139,22 @@ class any_tuple
cow_ptr<detail::abstract_tuple> const& vals() const; cow_ptr<detail::abstract_tuple> const& vals() const;
inline std::type_info const* values_type_list() const inline void const* type_token() const
{
return m_vals->type_token();
}
inline std::type_info const* impl_type() const
{ {
return m_vals->values_type_list(); return m_vals->impl_type();
} }
private:
cow_ptr<detail::abstract_tuple> m_vals;
explicit any_tuple(cow_ptr<detail::abstract_tuple> const& vals);
}; };
inline bool operator==(any_tuple const& lhs, any_tuple const& rhs) inline bool operator==(any_tuple const& lhs, any_tuple const& rhs)
......
...@@ -31,15 +31,111 @@ ...@@ -31,15 +31,111 @@
#ifndef BEHAVIOR_HPP #ifndef BEHAVIOR_HPP
#define BEHAVIOR_HPP #define BEHAVIOR_HPP
#include "cppa/either.hpp" #include <functional>
#include "cppa/invoke_rules.hpp" #include <type_traits>
#include "cppa/util/tbind.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/partial_function.hpp"
namespace cppa { namespace cppa {
/** /**
* @brief * @brief
*/ */
typedef either<invoke_rules, timed_invoke_rules> behavior; class behavior
{
behavior(behavior const&) = delete;
behavior& operator=(behavior const&) = delete;
public:
behavior() = default;
behavior(behavior&&) = default;
behavior& operator=(behavior&&) = default;
inline behavior(partial_function&& fun) : m_fun(std::move(fun))
{
}
inline behavior(util::duration tout, std::function<void()>&& handler)
: m_timeout(tout), m_timeout_handler(std::move(handler))
{
}
inline void handle_timeout() const
{
m_timeout_handler();
}
inline util::duration const& timeout() const
{
return m_timeout;
}
inline void operator()(any_tuple const& value)
{
m_fun(value);
}
inline detail::intermediate* get_intermediate(any_tuple const& value)
{
return m_fun.get_intermediate(value);
}
inline partial_function& get_partial_function()
{
return m_fun;
}
inline behavior& splice(behavior&& what)
{
m_fun.splice(std::move(what.get_partial_function()));
m_timeout = what.m_timeout;
m_timeout_handler = std::move(what.m_timeout_handler);
return *this;
}
template<class... Args>
inline behavior& splice(partial_function&& arg0, Args&&... args)
{
m_fun.splice(std::move(arg0));
return splice(std::forward<Args>(args)...);
}
private:
// terminates recursion
inline behavior& splice() { return *this; }
partial_function m_fun;
util::duration m_timeout;
std::function<void()> m_timeout_handler;
};
namespace detail {
template<typename... Ts>
struct select_bhvr
{
static constexpr bool timed =
util::tl_exists<
util::type_list<Ts...>,
util::tbind<std::is_same, behavior>::type
>::value;
typedef typename util::if_else_c<timed,
behavior,
util::wrapped<partial_function> >::type
type;
};
} // namespace detail
} // namespace cppa } // namespace cppa
......
...@@ -53,10 +53,6 @@ class channel : public ref_counted ...@@ -53,10 +53,6 @@ class channel : public ref_counted
friend class actor; friend class actor;
friend class group; friend class group;
// channel is a sealed class and the only
// allowed subclasses are actor and group.
channel() = default;
public: public:
virtual ~channel(); virtual ~channel();
...@@ -68,6 +64,12 @@ class channel : public ref_counted ...@@ -68,6 +64,12 @@ class channel : public ref_counted
virtual void enqueue(actor* sender, any_tuple&& msg) = 0; virtual void enqueue(actor* sender, any_tuple&& msg) = 0;
private:
// channel is a sealed class and the only
// allowed subclasses are actor and group.
channel() = default;
}; };
/** /**
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
#include "cppa/receive.hpp" #include "cppa/receive.hpp"
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
...@@ -49,7 +50,6 @@ ...@@ -49,7 +50,6 @@
#include "cppa/fsm_actor.hpp" #include "cppa/fsm_actor.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp" #include "cppa/exit_reason.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/scheduled_actor.hpp"
#include "cppa/scheduling_hint.hpp" #include "cppa/scheduling_hint.hpp"
#include "cppa/event_based_actor.hpp" #include "cppa/event_based_actor.hpp"
......
...@@ -84,7 +84,7 @@ class abstract_scheduled_actor : public abstract_actor<local_actor> ...@@ -84,7 +84,7 @@ class abstract_scheduled_actor : public abstract_actor<local_actor>
filter_result filter_msg(any_tuple const& msg); filter_result filter_msg(any_tuple const& msg);
dq_result dq(queue_node_ptr& node, dq_result dq(queue_node_ptr& node,
invoke_rules_base& rules, partial_function& rules,
queue_node_buffer& buffer); queue_node_buffer& buffer);
bool has_pending_timeout() bool has_pending_timeout()
...@@ -157,8 +157,8 @@ struct scheduled_actor_dummy : abstract_scheduled_actor ...@@ -157,8 +157,8 @@ struct scheduled_actor_dummy : abstract_scheduled_actor
{ {
void resume(util::fiber*, resume_callback*); void resume(util::fiber*, resume_callback*);
void quit(std::uint32_t); void quit(std::uint32_t);
void dequeue(invoke_rules&); void dequeue(behavior&);
void dequeue(timed_invoke_rules&); void dequeue(partial_function&);
void link_to(intrusive_ptr<actor>&); void link_to(intrusive_ptr<actor>&);
void unlink_from(intrusive_ptr<actor>&); void unlink_from(intrusive_ptr<actor>&);
bool establish_backlink(intrusive_ptr<actor>&); bool establish_backlink(intrusive_ptr<actor>&);
......
...@@ -56,14 +56,19 @@ struct abstract_tuple : ref_counted ...@@ -56,14 +56,19 @@ struct abstract_tuple : ref_counted
virtual abstract_tuple* copy() const = 0; virtual abstract_tuple* copy() const = 0;
virtual void const* at(size_t pos) const = 0; virtual void const* at(size_t pos) const = 0;
virtual uniform_type_info const* type_at(size_t pos) const = 0; virtual uniform_type_info const* type_at(size_t pos) const = 0;
// type_list of values or nullptr
virtual std::type_info const* values_type_list() const = 0; // identifies the type of the implementation, this is NOT the
// typeid of the implementation class
virtual std::type_info const* impl_type() const = 0;
// uniquely identifies this category (element types) of messages
virtual void const* type_token() const = 0;
bool equals(abstract_tuple const& other) const; bool equals(abstract_tuple const& other) const;
// iterator support // iterator support
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, class const_iterator //: public std::iterator<std::bidirectional_iterator_tag,
type_value_pair> // type_value_pair>
{ {
size_t m_pos; size_t m_pos;
...@@ -142,7 +147,7 @@ struct abstract_tuple : ref_counted ...@@ -142,7 +147,7 @@ struct abstract_tuple : ref_counted
inline const_iterator& operator*() { return *this; } inline const_iterator& operator*() { return *this; }
inline operator type_value_pair() const { return {type(), value()}; } //inline operator type_value_pair() const { return {type(), value()}; }
}; };
...@@ -160,6 +165,20 @@ inline bool full_eq(abstract_tuple::const_iterator const& lhs, ...@@ -160,6 +165,20 @@ inline bool full_eq(abstract_tuple::const_iterator const& lhs,
|| lhs.type()->equals(lhs.value(), rhs.second)); || lhs.type()->equals(lhs.value(), rhs.second));
} }
inline bool full_eq_v2(type_value_pair const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return full_eq(rhs, lhs);
}
inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return lhs.type() == rhs.type()
&& lhs.type()->equals(lhs.value(), rhs.value());
}
inline bool values_only_eq(abstract_tuple::const_iterator const& lhs, inline bool values_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs) type_value_pair const& rhs)
{ {
...@@ -167,12 +186,24 @@ inline bool values_only_eq(abstract_tuple::const_iterator const& lhs, ...@@ -167,12 +186,24 @@ inline bool values_only_eq(abstract_tuple::const_iterator const& lhs,
|| lhs.type()->equals(lhs.value(), rhs.second); || lhs.type()->equals(lhs.value(), rhs.second);
} }
inline bool values_only_eq_v2(type_value_pair const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return values_only_eq(rhs, lhs);
}
inline bool types_only_eq(abstract_tuple::const_iterator const& lhs, inline bool types_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs) type_value_pair const& rhs)
{ {
return lhs.type() == rhs.first; return lhs.type() == rhs.first;
} }
inline bool types_only_eq_v2(type_value_pair const& lhs,
abstract_tuple::const_iterator const& rhs)
{
return lhs.first == rhs.type();
}
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // ABSTRACT_TUPLE_HPP #endif // ABSTRACT_TUPLE_HPP
...@@ -75,9 +75,9 @@ class converted_thread_context : public abstract_actor<local_actor> ...@@ -75,9 +75,9 @@ class converted_thread_context : public abstract_actor<local_actor>
void enqueue(actor* sender, any_tuple const& msg) /*override*/; void enqueue(actor* sender, any_tuple const& msg) /*override*/;
void dequeue(invoke_rules& rules) /*override*/; void dequeue(behavior& rules) /*override*/;
void dequeue(timed_invoke_rules& rules) /*override*/; void dequeue(partial_function& rules) /*override*/;
inline decltype(m_mailbox)& mailbox() inline decltype(m_mailbox)& mailbox()
{ {
...@@ -97,7 +97,7 @@ class converted_thread_context : public abstract_actor<local_actor> ...@@ -97,7 +97,7 @@ class converted_thread_context : public abstract_actor<local_actor>
// returns true if node->msg was accepted by rules // returns true if node->msg was accepted by rules
bool dq(queue_node_ptr& node, bool dq(queue_node_ptr& node,
invoke_rules_base& rules, partial_function& rules,
queue_node_buffer& buffer); queue_node_buffer& buffer);
throw_on_exit_result throw_on_exit(any_tuple const& msg); throw_on_exit_result throw_on_exit(any_tuple const& msg);
......
...@@ -102,7 +102,12 @@ class decorated_tuple : public abstract_tuple ...@@ -102,7 +102,12 @@ class decorated_tuple : public abstract_tuple
return m_decorated->type_at(m_mapping[pos]); return m_decorated->type_at(m_mapping[pos]);
} }
std::type_info const* values_type_list() const void const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
std::type_info const* impl_type() const
{ {
return detail::static_type_list<ElementTypes...>::list; return detail::static_type_list<ElementTypes...>::list;
} }
......
...@@ -46,8 +46,8 @@ struct empty_tuple : abstract_tuple ...@@ -46,8 +46,8 @@ struct empty_tuple : abstract_tuple
void const* at(size_t) const; void const* at(size_t) const;
bool equals(abstract_tuple const& other) const; bool equals(abstract_tuple const& other) const;
uniform_type_info const* type_at(size_t) const; uniform_type_info const* type_at(size_t) const;
std::type_info const& impl_type() const; std::type_info const* impl_type() const;
std::type_info const* values_type_list() const; void const* type_token() const;
}; };
......
This diff is collapsed.
...@@ -68,7 +68,9 @@ class object_array : public abstract_tuple ...@@ -68,7 +68,9 @@ class object_array : public abstract_tuple
uniform_type_info const* type_at(size_t pos) const; uniform_type_info const* type_at(size_t pos) const;
std::type_info const* values_type_list() const; void const* type_token() const;
std::type_info const* impl_type() const;
}; };
......
...@@ -36,7 +36,12 @@ ...@@ -36,7 +36,12 @@
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/invokable.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
...@@ -47,54 +52,33 @@ struct receive_while_helper ...@@ -47,54 +52,33 @@ struct receive_while_helper
Statement m_stmt; Statement m_stmt;
template<typename S> template<typename S>
receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt)) receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt)) { }
{
}
void operator()(invoke_rules& rules) void operator()(behavior& bhvr)
{ {
local_actor* sptr = self; local_actor* sptr = self;
while (m_stmt()) while (m_stmt()) sptr->dequeue(bhvr);
{
sptr->dequeue(rules);
}
}
void operator()(invoke_rules&& rules)
{
invoke_rules tmp(std::move(rules));
(*this)(tmp);
} }
void operator()(timed_invoke_rules& rules) void operator()(partial_function& fun)
{ {
local_actor* sptr = self; local_actor* sptr = self;
while (m_stmt()) while (m_stmt()) sptr->dequeue(fun);
{
sptr->dequeue(rules);
}
} }
void operator()(timed_invoke_rules&& rules) void operator()(behavior&& bhvr)
{ {
timed_invoke_rules tmp(std::move(rules)); behavior tmp{std::move(bhvr)};
(*this)(tmp); (*this)(tmp);
} }
template<typename Arg0, typename... Args> template<typename... Args>
void operator()(invoke_rules& rules, Arg0&& arg0, Args&&... args) void operator()(partial_function&& arg0, Args&&... args)
{ {
(*this)(rules.splice(std::forward<Arg0>(arg0)), typename select_bhvr<Args...>::type tmp;
std::forward<Args>(args)...); (*this)(tmp.splice(std::move(arg0), std::forward<Args>(args)...));
} }
template<typename Arg0, typename... Args>
void operator()(invoke_rules&& rules, Arg0&& arg0, Args&&... args)
{
invoke_rules tmp(std::move(rules));
(*this)(tmp.splice(std::forward<Arg0>(arg0)),
std::forward<Args>(args)...);
}
}; };
class do_receive_helper class do_receive_helper
...@@ -102,44 +86,19 @@ class do_receive_helper ...@@ -102,44 +86,19 @@ class do_receive_helper
behavior m_bhvr; behavior m_bhvr;
inline void init(timed_invoke_rules&& bhvr)
{
m_bhvr = std::move(bhvr);
}
inline void init(invoke_rules& bhvr)
{
m_bhvr = std::move(bhvr);
}
template<typename Arg0, typename... Args>
inline void init(invoke_rules& rules, Arg0&& arg0, Args&&... args)
{
init(rules.splice(std::forward<Arg0>(arg0)),
std::forward<Args>(args)...);
}
public: public:
do_receive_helper(invoke_rules&& rules) : m_bhvr(std::move(rules)) do_receive_helper(behavior&& bhvr) : m_bhvr(std::move(bhvr))
{
}
do_receive_helper(timed_invoke_rules&& rules) : m_bhvr(std::move(rules))
{ {
} }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
do_receive_helper(invoke_rules&& rules, Arg0&& arg0, Args&&... args) do_receive_helper(Arg0&& arg0, Args&&... args)
{ {
invoke_rules tmp(std::move(rules)); m_bhvr.splice(std::forward<Arg0>(arg0), std::forward<Args>(args)...);
init(tmp.splice(std::forward<Arg0>(arg0)), std::forward<Args>(args)...);
} }
do_receive_helper(do_receive_helper&& other) do_receive_helper(do_receive_helper&&) = default;
: m_bhvr(std::move(other.m_bhvr))
{
}
template<typename Statement> template<typename Statement>
void until(Statement&& stmt) void until(Statement&& stmt)
...@@ -147,11 +106,11 @@ class do_receive_helper ...@@ -147,11 +106,11 @@ class do_receive_helper
static_assert(std::is_same<bool, decltype(stmt())>::value, static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean"); "functor or function does not return a boolean");
local_actor* sptr = self; local_actor* sptr = self;
if (m_bhvr.is_left()) if (m_bhvr.timeout().valid())
{ {
do do
{ {
sptr->dequeue(m_bhvr.left()); sptr->dequeue(m_bhvr);
} }
while (stmt() == false); while (stmt() == false);
} }
...@@ -159,7 +118,7 @@ class do_receive_helper ...@@ -159,7 +118,7 @@ class do_receive_helper
{ {
do do
{ {
sptr->dequeue(m_bhvr.right()); sptr->dequeue(m_bhvr.get_partial_function());
} }
while (stmt() == false); while (stmt() == false);
} }
......
...@@ -112,7 +112,12 @@ class tuple_vals : public abstract_tuple ...@@ -112,7 +112,12 @@ class tuple_vals : public abstract_tuple
return abstract_tuple::equals(other); return abstract_tuple::equals(other);
} }
std::type_info const* values_type_list() const void const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
std::type_info const* impl_type() const
{ {
return detail::static_type_list<ElementTypes...>::list; return detail::static_type_list<ElementTypes...>::list;
} }
......
...@@ -79,9 +79,9 @@ class yielding_actor : public abstract_scheduled_actor ...@@ -79,9 +79,9 @@ class yielding_actor : public abstract_scheduled_actor
~yielding_actor() /*override*/; ~yielding_actor() /*override*/;
void dequeue(invoke_rules& rules) /*override*/; void dequeue(behavior& rules) /*override*/;
void dequeue(timed_invoke_rules& rules) /*override*/; void dequeue(partial_function& rules) /*override*/;
void resume(util::fiber* from, resume_callback* callback) /*override*/; void resume(util::fiber* from, resume_callback* callback) /*override*/;
......
...@@ -44,9 +44,7 @@ class event_based_actor : public event_based_actor_base<event_based_actor> ...@@ -44,9 +44,7 @@ class event_based_actor : public event_based_actor_base<event_based_actor>
typedef abstract_event_based_actor::stack_element stack_element; typedef abstract_event_based_actor::stack_element stack_element;
// has_ownership == false // has_ownership == false
void do_become(behavior* bhvr); void do_become(behavior* bhvr, bool has_ownership);
void do_become(invoke_rules* bhvr, bool has_ownership);
void do_become(timed_invoke_rules* bhvr, bool has_ownership);
public: public:
......
...@@ -42,64 +42,26 @@ class event_based_actor_base : public abstract_event_based_actor ...@@ -42,64 +42,26 @@ class event_based_actor_base : public abstract_event_based_actor
typedef abstract_event_based_actor super; typedef abstract_event_based_actor super;
inline void become_impl(invoke_rules& rules)
{
become(std::move(rules));
}
inline void become_impl(timed_invoke_rules&& rules)
{
become(std::move(rules));
}
template<typename Head, typename... Tail>
void become_impl(invoke_rules& rules, Head&& head, Tail&&... tail)
{
become_impl(rules.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
inline Derived* d_this() { return static_cast<Derived*>(this); } inline Derived* d_this() { return static_cast<Derived*>(this); }
protected: protected:
inline void become(behavior* bhvr) inline void become(behavior* bhvr)
{
d_this()->do_become(bhvr);
}
inline void become(invoke_rules* bhvr)
{
d_this()->do_become(bhvr, false);
}
inline void become(timed_invoke_rules* bhvr)
{ {
d_this()->do_become(bhvr, false); d_this()->do_become(bhvr, false);
} }
inline void become(invoke_rules&& bhvr) template<typename... Args>
{ void become(partial_function&& arg0, Args&&... args)
d_this()->do_become(new invoke_rules(std::move(bhvr)), true);
}
inline void become(timed_invoke_rules&& bhvr)
{
d_this()->do_become(new timed_invoke_rules(std::move(bhvr)), true);
}
inline void become(behavior&& bhvr)
{ {
if (bhvr.is_left()) become(std::move(bhvr.left())); auto ptr = new behavior;
else become(std::move(bhvr.right())); ptr->splice(std::move(arg0), std::forward<Args>(args)...);
d_this()->do_become(ptr, true);
} }
template<typename Head, typename... Tail> inline void become(behavior&& arg0)
void become(invoke_rules&& rules, Head&& head, Tail&&... tail)
{ {
invoke_rules tmp(std::move(rules)); d_this()->do_become(new behavior(std::move(arg0)), true);
become_impl(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
} }
}; };
......
...@@ -32,8 +32,9 @@ ...@@ -32,8 +32,9 @@
#define CONTEXT_HPP #define CONTEXT_HPP
#include "cppa/actor.hpp" #include "cppa/actor.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/single_reader_queue.hpp" #include "cppa/util/single_reader_queue.hpp"
namespace cppa { namespace cppa {
...@@ -70,19 +71,19 @@ class local_actor : public actor ...@@ -70,19 +71,19 @@ class local_actor : public actor
virtual void quit(std::uint32_t reason) = 0; virtual void quit(std::uint32_t reason) = 0;
/** /**
* @brief Removes the first element from the queue that is matched * @brief
* by @p rules and invokes the corresponding callback.
* @param rules * @param rules
* @warning Call only from the owner of the queue. * @warning Call only from the owner of the queue.
*/ */
virtual void dequeue(invoke_rules& rules) = 0; virtual void dequeue(behavior& rules) = 0;
/** /**
* @brief * @brief Removes the first element from the queue that is matched
* by @p rules and invokes the corresponding callback.
* @param rules * @param rules
* @warning Call only from the owner of the queue. * @warning Call only from the owner of the queue.
*/ */
virtual void dequeue(timed_invoke_rules& rules) = 0; virtual void dequeue(partial_function& rules) = 0;
inline bool trap_exit() const; inline bool trap_exit() const;
......
...@@ -210,14 +210,16 @@ struct matcher<wildcard_position::nil, T...> ...@@ -210,14 +210,16 @@ struct matcher<wildcard_position::nil, T...>
static inline bool tmatch(any_tuple const& tup) static inline bool tmatch(any_tuple const& tup)
{ {
// match implementation type if possible // match implementation type if possible
auto vals = tup.values_type_list(); auto impl = tup.impl_type();
auto prns = detail::static_type_list<T...>::list; // the impl_type of both decorated_tuple and tuple_vals
if (vals == prns || *vals == *prns) // is &typeid(type_list<T...>)
auto tinf = detail::static_type_list<T...>::list;
if (impl == tinf || *impl == *tinf)
{ {
return true; return true;
} }
// always use a full dynamic match for object arrays // always use a full dynamic match for object arrays
else if (*vals == typeid(detail::object_array) else if (*impl == typeid(detail::object_array)
&& tup.size() == sizeof...(T)) && tup.size() == sizeof...(T))
{ {
auto& tarr = detail::static_types_array<T...>::arr; auto& tarr = detail::static_types_array<T...>::arr;
...@@ -241,8 +243,9 @@ struct matcher<wildcard_position::nil, T...> ...@@ -241,8 +243,9 @@ struct matcher<wildcard_position::nil, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
return std::equal(tup.begin(), tup.end(), ptrn.begin(), CPPA_REQUIRE(tup.size() == sizeof...(T));
detail::values_only_eq); return std::equal(ptrn.begin(), ptrn.vend(), tup.begin(),
detail::values_only_eq_v2);
} }
}; };
...@@ -277,9 +280,8 @@ struct matcher<wildcard_position::trailing, T...> ...@@ -277,9 +280,8 @@ struct matcher<wildcard_position::trailing, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
auto begin = tup.begin(); return std::equal(ptrn.begin(), ptrn.vend(), tup.begin(),
return std::equal(begin, begin + size, ptrn.begin(), detail::values_only_eq_v2);
detail::values_only_eq);
} }
}; };
...@@ -334,11 +336,12 @@ struct matcher<wildcard_position::leading, T...> ...@@ -334,11 +336,12 @@ struct matcher<wildcard_position::leading, T...>
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn) static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{ {
auto begin = tup.begin(); auto tbegin = tup.begin();
begin += (tup.size() - size); // skip unmatched elements
return std::equal(begin, tup.end(), tbegin += (tup.size() - size);
ptrn.begin() + 1, // skip 'anything' // skip leading wildcard ++(ptr.begin())
detail::values_only_eq); return std::equal(++(ptrn.begin()), ptrn.vend(), tbegin,
detail::values_only_eq_v2);
} }
}; };
......
...@@ -37,8 +37,9 @@ ...@@ -37,8 +37,9 @@
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/behavior.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
...@@ -54,28 +55,27 @@ ...@@ -54,28 +55,27 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
class timed_invoke_rule_builder class behavior_rvalue_builder
{ {
util::duration m_timeout; util::duration m_timeout;
public: public:
constexpr timed_invoke_rule_builder(util::duration const& d) : m_timeout(d) constexpr behavior_rvalue_builder(util::duration const& d) : m_timeout(d)
{ {
} }
template<typename F> template<typename F>
timed_invoke_rules operator>>(F&& f) behavior operator>>(F&& f)
{ {
typedef timed_invokable_impl<F> impl; return {m_timeout, std::function<void()>{std::forward<F>(f)}};
return timed_invokable_ptr(new impl(m_timeout, std::forward<F>(f)));
} }
}; };
template<typename... TypeList> template<typename... TypeList>
class invoke_rule_builder class rvalue_builder
{ {
typedef util::arg_match_t arg_match_t; typedef util::arg_match_t arg_match_t;
...@@ -85,7 +85,8 @@ class invoke_rule_builder ...@@ -85,7 +85,8 @@ class invoke_rule_builder
static constexpr bool is_complete = static constexpr bool is_complete =
!std::is_same<arg_match_t, typename raw_types::back>::value; !std::is_same<arg_match_t, typename raw_types::back>::value;
typedef typename util::if_else_c<is_complete == false, typedef typename util::if_else_c<
is_complete == false,
typename util::tl_pop_back<raw_types>::type, typename util::tl_pop_back<raw_types>::type,
util::wrapped<raw_types> >::type util::wrapped<raw_types> >::type
types; types;
...@@ -103,13 +104,13 @@ class invoke_rule_builder ...@@ -103,13 +104,13 @@ class invoke_rule_builder
std::unique_ptr<pattern_type> m_ptr; std::unique_ptr<pattern_type> m_ptr;
template<typename F> template<typename F>
invoke_rules cr_rules(F&& f, std::integral_constant<bool, true>) partial_function cr_rvalue(F&& f, std::integral_constant<bool, true>)
{ {
return get_invokable_impl(std::forward<F>(f), std::move(m_ptr)); return get_invokable_impl(std::forward<F>(f), std::move(m_ptr));
} }
template<typename F> template<typename F>
invoke_rules cr_rules(F&& f, std::integral_constant<bool, false>) partial_function cr_rvalue(F&& f, std::integral_constant<bool, false>)
{ {
using namespace ::cppa::util; using namespace ::cppa::util;
typedef typename get_callable_trait<F>::type ctrait; typedef typename get_callable_trait<F>::type ctrait;
...@@ -125,32 +126,31 @@ class invoke_rule_builder ...@@ -125,32 +126,31 @@ class invoke_rule_builder
public: public:
template<typename... Args> template<typename... Args>
invoke_rule_builder(Args const&... args) rvalue_builder(Args const&... args) : m_ptr(new pattern_type(args...))
: m_ptr(new pattern_type(args...))
{ {
} }
template<typename F> template<typename F>
invoke_rules operator>>(F&& f) partial_function operator>>(F&& f)
{ {
std::integral_constant<bool,is_complete> token; std::integral_constant<bool, is_complete> token;
return cr_rules(std::forward<F>(f), token); return cr_rvalue(std::forward<F>(f), token);
} }
}; };
class on_the_fly_invoke_rule_builder class on_the_fly_rvalue_builder
{ {
public: public:
constexpr on_the_fly_invoke_rule_builder() constexpr on_the_fly_rvalue_builder()
{ {
} }
template<typename F> template<typename F>
invoke_rules operator>>(F&& f) const partial_function operator>>(F&& f) const
{ {
using namespace ::cppa::util; using namespace ::cppa::util;
typedef typename get_callable_trait<F>::type ctrait; typedef typename get_callable_trait<F>::type ctrait;
...@@ -180,10 +180,10 @@ typedef typename detail::boxed<util::arg_match_t>::type boxed_arg_match_t; ...@@ -180,10 +180,10 @@ typedef typename detail::boxed<util::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();
constexpr detail::on_the_fly_invoke_rule_builder on_arg_match; constexpr detail::on_the_fly_rvalue_builder on_arg_match;
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
detail::invoke_rule_builder<typename detail::unboxed<Arg0>::type, detail::rvalue_builder<typename detail::unboxed<Arg0>::type,
typename detail::unboxed<Args>::type...> typename detail::unboxed<Args>::type...>
on(Arg0 const& arg0, Args const&... args) on(Arg0 const& arg0, Args const&... args)
{ {
...@@ -191,25 +191,25 @@ on(Arg0 const& arg0, Args const&... args) ...@@ -191,25 +191,25 @@ on(Arg0 const& arg0, Args const&... args)
} }
template<typename... TypeList> template<typename... TypeList>
detail::invoke_rule_builder<TypeList...> on() detail::rvalue_builder<TypeList...> on()
{ {
return { }; return { };
} }
template<atom_value A0, typename... TypeList> template<atom_value A0, typename... TypeList>
detail::invoke_rule_builder<atom_value, TypeList...> on() detail::rvalue_builder<atom_value, TypeList...> on()
{ {
return { A0 }; return { A0 };
} }
template<atom_value A0, atom_value A1, typename... TypeList> template<atom_value A0, atom_value A1, typename... TypeList>
detail::invoke_rule_builder<atom_value, atom_value, TypeList...> on() detail::rvalue_builder<atom_value, atom_value, TypeList...> on()
{ {
return { A0, A1 }; return { A0, A1 };
} }
template<atom_value A0, atom_value A1, atom_value A2, typename... TypeList> template<atom_value A0, atom_value A1, atom_value A2, typename... TypeList>
detail::invoke_rule_builder<atom_value, atom_value, detail::rvalue_builder<atom_value, atom_value,
atom_value, TypeList...> on() atom_value, TypeList...> on()
{ {
return { A0, A1, A2 }; return { A0, A1, A2 };
...@@ -218,20 +218,20 @@ detail::invoke_rule_builder<atom_value, atom_value, ...@@ -218,20 +218,20 @@ detail::invoke_rule_builder<atom_value, atom_value,
template<atom_value A0, atom_value A1, template<atom_value A0, atom_value A1,
atom_value A2, atom_value A3, atom_value A2, atom_value A3,
typename... TypeList> typename... TypeList>
detail::invoke_rule_builder<atom_value, atom_value, atom_value, detail::rvalue_builder<atom_value, atom_value, atom_value,
atom_value, TypeList...> on() atom_value, TypeList...> on()
{ {
return { A0, A1, A2, A3 }; return { A0, A1, A2, A3 };
} }
template<class Rep, class Period> template<class Rep, class Period>
constexpr detail::timed_invoke_rule_builder constexpr detail::behavior_rvalue_builder
after(const std::chrono::duration<Rep, Period>& d) after(std::chrono::duration<Rep, Period> const& d)
{ {
return { util::duration(d) }; return { util::duration(d) };
} }
inline detail::invoke_rule_builder<anything> others() inline detail::rvalue_builder<anything> others()
{ {
return { }; return { };
} }
......
...@@ -28,24 +28,75 @@ ...@@ -28,24 +28,75 @@
\******************************************************************************/ \******************************************************************************/
#ifndef UTIL_HPP #ifndef PARTIAL_FUNCTION_HPP
#define UTIL_HPP #define PARTIAL_FUNCTION_HPP
#include "cppa/util/callable_trait.hpp" #include <vector>
#include "cppa/util/compare_tuples.hpp" #include <memory>
#include "cppa/util/conjunction.hpp" #include <utility>
#include "cppa/util/disjunction.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/detail/invokable.hpp"
#include "cppa/util/has_copy_member_fun.hpp"
#include "cppa/util/is_comparable.hpp" namespace cppa {
#include "cppa/util/is_copyable.hpp"
#include "cppa/util/is_legal_tuple_type.hpp" class behavior;
#include "cppa/util/is_one_of.hpp"
#include "cppa/util/remove_const_reference.hpp" class partial_function
#include "cppa/util/replace_type.hpp" {
#include "cppa/util/single_reader_queue.hpp"
#include "cppa/util/singly_linked_list.hpp" public:
#include "cppa/util/type_list.hpp"
#include "cppa/util/void_type.hpp" typedef std::unique_ptr<detail::invokable> invokable_ptr;
#endif // UTIL_HPP partial_function() = default;
partial_function(partial_function&& other);
partial_function(invokable_ptr&& ptr);
bool defined_at(any_tuple const& value);
void operator()(any_tuple const& value);
detail::invokable const* definition_at(any_tuple const& value);
detail::intermediate* get_intermediate(any_tuple const& value);
template<class... Args>
partial_function& splice(partial_function&& arg0, Args&&... args)
{
auto& vec = arg0.m_funs;
std::move(vec.begin(), vec.end(), std::back_inserter(m_funs));
return splice(std::forward<Args>(args)...);
}
inline partial_function operator,(partial_function&& arg)
{
return std::move(splice(std::move(arg)));
}
behavior operator,(behavior&& arg);
private:
// terminates recursion
inline partial_function& splice()
{
m_cache.clear();
return *this;
}
typedef std::vector<detail::invokable*> cache_entry;
typedef std::pair<void const*, cache_entry> cache_element;
std::vector<invokable_ptr> m_funs;
std::vector<cache_element> m_cache;
cache_element m_dummy; // binary search dummy
cache_entry& get_cache_entry(any_tuple const& value);
};
} // namespace cppa
#endif // PARTIAL_FUNCTION_HPP
...@@ -111,10 +111,25 @@ class pattern ...@@ -111,10 +111,25 @@ class pattern
typedef type_value_pair_const_iterator const_iterator; typedef type_value_pair_const_iterator const_iterator;
typedef std::reverse_iterator<const_iterator> reverse_const_iterator;
const_iterator begin() const { return m_ptrs; } inline const_iterator begin() const { return m_ptrs; }
const_iterator end() const { return m_ptrs + size; } inline const_iterator end() const { return m_ptrs + size; }
inline reverse_const_iterator rbegin() const
{
return reverse_const_iterator{end()};
}
inline reverse_const_iterator rend() const
{
return reverse_const_iterator{begin()};
}
inline const_iterator vbegin() const { return m_vbegin; }
inline const_iterator vend() const { return m_vend; }
pattern() : m_has_values(false) pattern() : m_has_values(false)
{ {
...@@ -124,6 +139,7 @@ class pattern ...@@ -124,6 +139,7 @@ class pattern
m_ptrs[i].first = arr[i]; m_ptrs[i].first = arr[i];
m_ptrs[i].second = nullptr; m_ptrs[i].second = nullptr;
} }
m_vbegin = m_vend = begin();
} }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
...@@ -152,6 +168,7 @@ class pattern ...@@ -152,6 +168,7 @@ class pattern
m_ptrs[i].first = arr[i]; m_ptrs[i].first = arr[i];
m_ptrs[i].second = nullptr; m_ptrs[i].second = nullptr;
} }
init_value_iterators();
} }
inline bool has_values() const { return m_has_values; } inline bool has_values() const { return m_has_values; }
...@@ -174,10 +191,28 @@ class pattern ...@@ -174,10 +191,28 @@ class pattern
} }
}; };
void init_value_iterators()
{
auto pred = [](type_value_pair const& tvp) { return tvp.second != 0; };
auto last = end();
m_vbegin = std::find_if(begin(), last, pred);
if (m_vbegin == last)
{
m_vbegin = m_vend = begin();
}
else
{
m_vend = std::find_if(rbegin(), rend(), pred).base();
}
}
detail::tdata<option<Types>...> m_data; detail::tdata<option<Types>...> m_data;
bool m_has_values; bool m_has_values;
type_value_pair m_ptrs[size]; type_value_pair m_ptrs[size];
const_iterator m_vbegin;
const_iterator m_vend;
}; };
template<class ExtendedType, class BasicType> template<class ExtendedType, class BasicType>
...@@ -189,10 +224,13 @@ ExtendedType* extend_pattern(BasicType const* p) ...@@ -189,10 +224,13 @@ ExtendedType* extend_pattern(BasicType const* p)
detail::tdata_set(et->m_data, p->m_data); detail::tdata_set(et->m_data, p->m_data);
et->m_has_values = true; et->m_has_values = true;
typedef typename ExtendedType::types extended_types; typedef typename ExtendedType::types extended_types;
typedef typename detail::static_types_array_from_type_list<extended_types>::type tarr; typedef typename
detail::static_types_array_from_type_list<extended_types>::type
tarr;
auto& arr = tarr::arr; auto& arr = tarr::arr;
typename ExtendedType::init_helper f(et->m_ptrs, arr); typename ExtendedType::init_helper f(et->m_ptrs, arr);
util::static_foreach<0, BasicType::size>::_(et->m_data, f); util::static_foreach<0, BasicType::size>::_(et->m_data, f);
et->init_value_iterators();
} }
return et; return et;
} }
......
...@@ -97,84 +97,42 @@ auto do_receive(behavior& bhvr); ...@@ -97,84 +97,42 @@ auto do_receive(behavior& bhvr);
#else // CPPA_DOCUMENTATION #else // CPPA_DOCUMENTATION
inline void receive(invoke_rules& bhvr) { self->dequeue(bhvr); } inline void receive(behavior& bhvr) { self->dequeue(bhvr); }
inline void receive(timed_invoke_rules& bhvr) { self->dequeue(bhvr); } inline void receive(partial_function& fun) { self->dequeue(fun); }
inline void receive(behavior& bhvr) inline void receive(behavior&& arg0)
{ {
if (bhvr.is_left()) self->dequeue(bhvr.left()); behavior tmp{std::move(arg0)};
else self->dequeue(bhvr.right()); receive(tmp);
} }
inline void receive(timed_invoke_rules&& bhvr) template<typename... Args>
{ void receive(partial_function&& arg0, Args&&... args)
timed_invoke_rules tmp(std::move(bhvr));
self->dequeue(tmp);
}
inline void receive(invoke_rules&& bhvr)
{
invoke_rules tmp(std::move(bhvr));
self->dequeue(tmp);
}
template<typename Head, typename... Tail>
void receive(invoke_rules&& bhvr, Head&& head, Tail&&... tail)
{
invoke_rules tmp(std::move(bhvr));
receive(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
template<typename Head, typename... Tail>
void receive(invoke_rules& bhvr, Head&& head, Tail&&... tail)
{ {
receive(bhvr.splice(std::forward<Head>(head)), typename detail::select_bhvr<Args...>::type tmp;
std::forward<Tail>(tail)...); receive(tmp.splice(std::move(arg0), std::forward<Args>(args)...));
} }
void receive_loop(behavior& rules);
void receive_loop(invoke_rules& rules); void receive_loop(partial_function& rules);
void receive_loop(timed_invoke_rules& rules);
inline void receive_loop(behavior& bhvr) inline void receive_loop(behavior&& arg0)
{ {
if (bhvr.is_left()) receive_loop(bhvr.left()); behavior tmp{std::move(arg0)};
else receive_loop(bhvr.right());
}
inline void receive_loop(invoke_rules&& rules)
{
invoke_rules tmp(std::move(rules));
receive_loop(tmp); receive_loop(tmp);
} }
inline void receive_loop(timed_invoke_rules&& rules) template<typename... Args>
{ void receive_loop(partial_function&& arg0, Args&&... args)
timed_invoke_rules tmp(std::move(rules));
receive_loop(tmp);
}
template<typename Head, typename... Tail>
void receive_loop(invoke_rules& rules, Head&& head, Tail&&... tail)
{
receive_loop(rules.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
template<typename Head, typename... Tail>
void receive_loop(invoke_rules&& rules, Head&& head, Tail&&... tail)
{ {
invoke_rules tmp(std::move(rules)); typename detail::select_bhvr<Args...>::type tmp;
receive_loop(tmp.splice(std::forward<Head>(head)), receive_loop(tmp.splice(std::move(arg0), std::forward<Args>(args)...));
std::forward<Tail>(tail)...);
} }
template<typename Statement> template<typename Statement>
detail::receive_while_helper<Statement> detail::receive_while_helper<Statement> receive_while(Statement&& stmt)
receive_while(Statement&& stmt)
{ {
static_assert(std::is_same<bool, decltype(stmt())>::value, static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean"); "functor or function does not return a boolean");
......
...@@ -42,8 +42,7 @@ class stacked_event_based_actor : public event_based_actor_base<stacked_event_ba ...@@ -42,8 +42,7 @@ class stacked_event_based_actor : public event_based_actor_base<stacked_event_ba
typedef abstract_event_based_actor::stack_element stack_element; typedef abstract_event_based_actor::stack_element stack_element;
void do_become(invoke_rules* behavior, bool has_ownership); void do_become(behavior* behavior, bool has_ownership);
void do_become(timed_invoke_rules* behavior, bool has_ownership);
protected: protected:
......
...@@ -71,7 +71,7 @@ class duration ...@@ -71,7 +71,7 @@ class duration
{ {
} }
template <class Rep, class Period> template<class Rep, class Period>
constexpr duration(std::chrono::duration<Rep, Period> d) constexpr duration(std::chrono::duration<Rep, Period> d)
: unit(get_time_unit_from_period<Period>()), count(d.count()) : unit(get_time_unit_from_period<Period>()), count(d.count())
{ {
...@@ -79,6 +79,8 @@ class duration ...@@ -79,6 +79,8 @@ class duration
"only seconds, milliseconds or microseconds allowed"); "only seconds, milliseconds or microseconds allowed");
} }
inline bool valid() const { return unit != time_unit::none; }
time_unit unit; time_unit unit;
std::uint32_t count; std::uint32_t count;
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
namespace cppa { namespace util { namespace cppa { namespace util {
template<template <typename, typename> class Tpl, typename Arg1> template<template<typename, typename> class Tpl, typename Arg1>
struct tbind struct tbind
{ {
template<typename Arg2> template<typename Arg2>
......
...@@ -185,7 +185,7 @@ struct tl_first_n ...@@ -185,7 +185,7 @@ struct tl_first_n
/** /**
* @brief Tests whether a predicate holds for all elements of a list. * @brief Tests whether a predicate holds for all elements of a list.
*/ */
template<class List, template <typename> class Predicate> template<class List, template<typename> class Predicate>
struct tl_forall struct tl_forall
{ {
static constexpr bool value = static constexpr bool value =
...@@ -193,7 +193,7 @@ struct tl_forall ...@@ -193,7 +193,7 @@ struct tl_forall
&& tl_forall<typename List::tail, Predicate>::value; && tl_forall<typename List::tail, Predicate>::value;
}; };
template<template <typename> class Predicate> template<template<typename> class Predicate>
struct tl_forall<type_list<>, Predicate> struct tl_forall<type_list<>, Predicate>
{ {
static constexpr bool value = true; static constexpr bool value = true;
...@@ -202,7 +202,7 @@ struct tl_forall<type_list<>, Predicate> ...@@ -202,7 +202,7 @@ struct tl_forall<type_list<>, Predicate>
/** /**
* @brief Tests whether a predicate holds for some of the elements of a list. * @brief Tests whether a predicate holds for some of the elements of a list.
*/ */
template<class List, template <typename> class Predicate> template<class List, template<typename> class Predicate>
struct tl_exists struct tl_exists
{ {
static constexpr bool value = static constexpr bool value =
...@@ -210,7 +210,7 @@ struct tl_exists ...@@ -210,7 +210,7 @@ struct tl_exists
|| tl_exists<typename List::tail, Predicate>::value; || tl_exists<typename List::tail, Predicate>::value;
}; };
template<template <typename> class Predicate> template<template<typename> class Predicate>
struct tl_exists<type_list<>, Predicate> struct tl_exists<type_list<>, Predicate>
{ {
static constexpr bool value = false; static constexpr bool value = false;
...@@ -222,7 +222,7 @@ struct tl_exists<type_list<>, Predicate> ...@@ -222,7 +222,7 @@ struct tl_exists<type_list<>, Predicate>
/** /**
* @brief Counts the number of elements in the list which satisfy a predicate. * @brief Counts the number of elements in the list which satisfy a predicate.
*/ */
template<class List, template <typename> class Predicate> template<class List, template<typename> class Predicate>
struct tl_count struct tl_count
{ {
static constexpr size_t value = static constexpr size_t value =
...@@ -230,7 +230,7 @@ struct tl_count ...@@ -230,7 +230,7 @@ struct tl_count
+ tl_count<typename List::tail, Predicate>::value; + tl_count<typename List::tail, Predicate>::value;
}; };
template<template <typename> class Predicate> template<template<typename> class Predicate>
struct tl_count<type_list<>, Predicate> struct tl_count<type_list<>, Predicate>
{ {
static constexpr size_t value = 0; static constexpr size_t value = 0;
...@@ -241,7 +241,7 @@ struct tl_count<type_list<>, Predicate> ...@@ -241,7 +241,7 @@ struct tl_count<type_list<>, Predicate>
/** /**
* @brief Counts the number of elements in the list which satisfy a predicate. * @brief Counts the number of elements in the list which satisfy a predicate.
*/ */
template<class List, template <typename> class Predicate> template<class List, template<typename> class Predicate>
struct tl_count_not struct tl_count_not
{ {
static constexpr size_t value = static constexpr size_t value =
...@@ -249,7 +249,7 @@ struct tl_count_not ...@@ -249,7 +249,7 @@ struct tl_count_not
+ tl_count_not<typename List::tail, Predicate>::value; + tl_count_not<typename List::tail, Predicate>::value;
}; };
template<template <typename> class Predicate> template<template<typename> class Predicate>
struct tl_count_not<type_list<>, Predicate> struct tl_count_not<type_list<>, Predicate>
{ {
static constexpr size_t value = 0; static constexpr size_t value = 0;
...@@ -260,7 +260,7 @@ struct tl_count_not<type_list<>, Predicate> ...@@ -260,7 +260,7 @@ struct tl_count_not<type_list<>, Predicate>
/** /**
* @brief Tests whether a predicate holds for all elements of a zipped list. * @brief Tests whether a predicate holds for all elements of a zipped list.
*/ */
template<class ZippedList, template <typename, typename> class Predicate> template<class ZippedList, template<typename, typename> class Predicate>
struct tl_zipped_forall struct tl_zipped_forall
{ {
typedef typename ZippedList::head head; typedef typename ZippedList::head head;
...@@ -269,7 +269,7 @@ struct tl_zipped_forall ...@@ -269,7 +269,7 @@ struct tl_zipped_forall
&& tl_zipped_forall<typename ZippedList::tail, Predicate>::value; && tl_zipped_forall<typename ZippedList::tail, Predicate>::value;
}; };
template<template <typename, typename> class Predicate> template<template<typename, typename> class Predicate>
struct tl_zipped_forall<type_list<>, Predicate> struct tl_zipped_forall<type_list<>, Predicate>
{ {
static constexpr bool value = true; static constexpr bool value = true;
...@@ -294,10 +294,10 @@ struct tl_concat<type_list<ListATypes...>, type_list<ListBTypes...> > ...@@ -294,10 +294,10 @@ struct tl_concat<type_list<ListATypes...>, type_list<ListBTypes...> >
/** /**
* @brief Applies a "template function" to each element in the list. * @brief Applies a "template function" to each element in the list.
*/ */
template<typename List, template <typename> class Trait> template<typename List, template<typename> class Trait>
struct tl_apply; struct tl_apply;
template<template <typename> class Trait, typename... Elements> template<template<typename> class Trait, typename... Elements>
struct tl_apply<type_list<Elements...>, Trait> struct tl_apply<type_list<Elements...>, Trait>
{ {
typedef type_list<typename Trait<Elements>::type...> type; typedef type_list<typename Trait<Elements>::type...> type;
......
...@@ -44,7 +44,7 @@ class upgrade_lock_guard ...@@ -44,7 +44,7 @@ class upgrade_lock_guard
public: public:
template<template <typename> class LockType> template<template<typename> class LockType>
upgrade_lock_guard(LockType<UpgradeLockable>& other) upgrade_lock_guard(LockType<UpgradeLockable>& other)
{ {
m_lockable = other.release(); m_lockable = other.release();
......
...@@ -39,31 +39,26 @@ abstract_event_based_actor::abstract_event_based_actor() ...@@ -39,31 +39,26 @@ abstract_event_based_actor::abstract_event_based_actor()
{ {
} }
void abstract_event_based_actor::dequeue(invoke_rules&) void abstract_event_based_actor::dequeue(behavior&)
{ {
quit(exit_reason::unallowed_function_call); quit(exit_reason::unallowed_function_call);
} }
void abstract_event_based_actor::dequeue(timed_invoke_rules&) void abstract_event_based_actor::dequeue(partial_function&)
{ {
quit(exit_reason::unallowed_function_call); quit(exit_reason::unallowed_function_call);
} }
void abstract_event_based_actor::handle_message(queue_node_ptr& node, void abstract_event_based_actor::handle_message(queue_node_ptr& node)
invoke_rules& behavior)
{
// no need to handle result
(void) dq(node, behavior, m_buffer);
}
void abstract_event_based_actor::handle_message(queue_node_ptr& node,
timed_invoke_rules& behavior)
{ {
switch (dq(node, behavior, m_buffer)) auto& bhvr = *(m_loop_stack.back());
if (bhvr.timeout().valid())
{
switch (dq(node, bhvr.get_partial_function(), m_buffer))
{ {
case dq_timeout_occured: case dq_timeout_occured:
{ {
behavior.handle_timeout(); bhvr.handle_timeout();
// fall through // fall through
} }
case dq_done: case dq_done:
...@@ -72,28 +67,18 @@ void abstract_event_based_actor::handle_message(queue_node_ptr& node, ...@@ -72,28 +67,18 @@ void abstract_event_based_actor::handle_message(queue_node_ptr& node,
// request next timeout if needed // request next timeout if needed
if (!m_loop_stack.empty()) if (!m_loop_stack.empty())
{ {
auto& back = m_loop_stack.back(); auto& next_bhvr = *(m_loop_stack.back());
if (back.is_right()) request_timeout(next_bhvr.timeout());
{
request_timeout(back.right()->timeout());
}
} }
break; break;
} }
default: break; default: break;
} }
}
void abstract_event_based_actor::handle_message(queue_node_ptr& node)
{
auto& bhvr = m_loop_stack.back();
if (bhvr.is_left())
{
handle_message(node, *(bhvr.left()));
} }
else else
{ {
handle_message(node, *(bhvr.right())); // no need to handle result
(void) dq(node, bhvr.get_partial_function(), m_buffer);
} }
} }
......
...@@ -129,8 +129,11 @@ int abstract_scheduled_actor::compare_exchange_state(int expected, ...@@ -129,8 +129,11 @@ int abstract_scheduled_actor::compare_exchange_state(int expected,
void abstract_scheduled_actor::request_timeout(util::duration const& d) void abstract_scheduled_actor::request_timeout(util::duration const& d)
{ {
if (d.valid())
{
future_send(this, d, atom(":Timeout"), ++m_active_timeout_id); future_send(this, d, atom(":Timeout"), ++m_active_timeout_id);
m_has_pending_timeout_request = true; m_has_pending_timeout_request = true;
}
} }
auto abstract_scheduled_actor::filter_msg(const any_tuple& msg) -> filter_result auto abstract_scheduled_actor::filter_msg(const any_tuple& msg) -> filter_result
...@@ -162,7 +165,7 @@ auto abstract_scheduled_actor::filter_msg(const any_tuple& msg) -> filter_result ...@@ -162,7 +165,7 @@ auto abstract_scheduled_actor::filter_msg(const any_tuple& msg) -> filter_result
} }
auto abstract_scheduled_actor::dq(queue_node_ptr& node, auto abstract_scheduled_actor::dq(queue_node_ptr& node,
invoke_rules_base& rules, partial_function& rules,
queue_node_buffer& buffer) -> dq_result queue_node_buffer& buffer) -> dq_result
{ {
switch (filter_msg(node->msg)) switch (filter_msg(node->msg))
...@@ -232,11 +235,11 @@ void scheduled_actor_dummy::quit(std::uint32_t) ...@@ -232,11 +235,11 @@ void scheduled_actor_dummy::quit(std::uint32_t)
{ {
} }
void scheduled_actor_dummy::dequeue(invoke_rules&) void scheduled_actor_dummy::dequeue(behavior&)
{ {
} }
void scheduled_actor_dummy::dequeue(timed_invoke_rules&) void scheduled_actor_dummy::dequeue(partial_function&)
{ {
} }
......
...@@ -36,7 +36,7 @@ bool abstract_tuple::equals(const abstract_tuple &other) const ...@@ -36,7 +36,7 @@ bool abstract_tuple::equals(const abstract_tuple &other) const
{ {
return this == &other return this == &other
|| ( size() == other.size() || ( size() == other.size()
&& std::equal(begin(), end(), other.begin(), detail::full_eq)); && std::equal(begin(), end(), other.begin(), detail::full_eq_v3));
} }
abstract_tuple::abstract_tuple(abstract_tuple const&) : ref_counted() { } abstract_tuple::abstract_tuple(abstract_tuple const&) : ref_counted() { }
......
...@@ -55,7 +55,7 @@ inline cppa::detail::actor_registry& registry() ...@@ -55,7 +55,7 @@ inline cppa::detail::actor_registry& registry()
namespace cppa { namespace cppa {
actor::actor(std::uint32_t aid, const process_information_ptr& pptr) actor::actor(std::uint32_t aid, const process_information_ptr& pptr)
: m_is_proxy(true), m_id(aid), m_parent_process(pptr) : m_id(aid), m_is_proxy(true), m_parent_process(pptr)
{ {
if (!pptr) if (!pptr)
{ {
...@@ -64,7 +64,7 @@ actor::actor(std::uint32_t aid, const process_information_ptr& pptr) ...@@ -64,7 +64,7 @@ actor::actor(std::uint32_t aid, const process_information_ptr& pptr)
} }
actor::actor(const process_information_ptr& pptr) actor::actor(const process_information_ptr& pptr)
: m_is_proxy(false), m_id(registry().next_id()), m_parent_process(pptr) : m_id(registry().next_id()), m_is_proxy(false), m_parent_process(pptr)
{ {
if (!pptr) if (!pptr)
{ {
......
...@@ -69,7 +69,7 @@ void converted_thread_context::enqueue(actor* sender, const any_tuple& msg) ...@@ -69,7 +69,7 @@ void converted_thread_context::enqueue(actor* sender, const any_tuple& msg)
m_mailbox.push_back(fetch_node(sender, msg)); m_mailbox.push_back(fetch_node(sender, msg));
} }
void converted_thread_context::dequeue(invoke_rules& rules) /*override*/ void converted_thread_context::dequeue(partial_function& rules) /*override*/
{ {
queue_node_buffer buffer; queue_node_buffer buffer;
queue_node_ptr node(m_mailbox.pop()); queue_node_ptr node(m_mailbox.pop());
...@@ -79,8 +79,10 @@ void converted_thread_context::dequeue(invoke_rules& rules) /*override*/ ...@@ -79,8 +79,10 @@ void converted_thread_context::dequeue(invoke_rules& rules) /*override*/
} }
} }
void converted_thread_context::dequeue(timed_invoke_rules& rules) /*override*/ void converted_thread_context::dequeue(behavior& rules) /*override*/
{ {
if (rules.timeout().valid())
{
auto timeout = now(); auto timeout = now();
timeout += rules.timeout(); timeout += rules.timeout();
queue_node_buffer buffer; queue_node_buffer buffer;
...@@ -98,7 +100,12 @@ void converted_thread_context::dequeue(timed_invoke_rules& rules) /*override*/ ...@@ -98,7 +100,12 @@ void converted_thread_context::dequeue(timed_invoke_rules& rules) /*override*/
} }
} }
} }
while (dq(node, rules, buffer) == false); while (dq(node, rules.get_partial_function(), buffer) == false);
}
else
{
converted_thread_context::dequeue(rules.get_partial_function());
}
} }
converted_thread_context::throw_on_exit_result converted_thread_context::throw_on_exit_result
...@@ -121,7 +128,7 @@ converted_thread_context::throw_on_exit(any_tuple const& msg) ...@@ -121,7 +128,7 @@ converted_thread_context::throw_on_exit(any_tuple const& msg)
} }
bool converted_thread_context::dq(queue_node_ptr& node, bool converted_thread_context::dq(queue_node_ptr& node,
invoke_rules_base& rules, partial_function& rules,
queue_node_buffer& buffer) queue_node_buffer& buffer)
{ {
if (m_trap_exit == false && throw_on_exit(node->msg) == normal_exit_signal) if (m_trap_exit == false && throw_on_exit(node->msg) == normal_exit_signal)
......
...@@ -63,7 +63,12 @@ bool empty_tuple::equals(const abstract_tuple& other) const ...@@ -63,7 +63,12 @@ bool empty_tuple::equals(const abstract_tuple& other) const
return other.size() == 0; return other.size() == 0;
} }
std::type_info const* empty_tuple::values_type_list() const void const* empty_tuple::type_token() const
{
return &typeid(empty_tuple);
}
std::type_info const* empty_tuple::impl_type() const
{ {
return &typeid(empty_tuple); return &typeid(empty_tuple);
} }
......
...@@ -30,27 +30,6 @@ ...@@ -30,27 +30,6 @@
#include "cppa/event_based_actor.hpp" #include "cppa/event_based_actor.hpp"
namespace {
template<class StackElement, class Vec, class What>
void push_to(Vec& vec, What&& bhvr)
{
// keep always the latest element in the stack to prevent subtle errors,
// e.g., the addresses of all variables in a lambda expression calling
// become() suddenly are invalid if we would pop the behavior!
if (vec.size() < 2)
{
vec.push_back(std::move(bhvr));
}
else
{
vec[0] = std::move(vec[1]);
vec[1] = std::move(bhvr);
}
}
} // namespace <anonymous>
namespace cppa { namespace cppa {
void event_based_actor::become_void() void event_based_actor::become_void()
...@@ -58,32 +37,24 @@ void event_based_actor::become_void() ...@@ -58,32 +37,24 @@ void event_based_actor::become_void()
m_loop_stack.clear(); m_loop_stack.clear();
} }
void event_based_actor::do_become(behavior* bhvr) void event_based_actor::do_become(behavior* bhvr, bool has_ownership)
{ {
if (bhvr->is_left()) reset_timeout();
request_timeout(bhvr->timeout());
stack_element se{bhvr};
if (!has_ownership) se.get_deleter().disable();
// keep always the latest element in the stack to prevent subtle errors,
// e.g., the addresses of all variables in a lambda expression calling
// become() suddenly are invalid if we would pop the behavior!
if (m_loop_stack.size() < 2)
{ {
do_become(&(bhvr->left()), false); m_loop_stack.push_back(std::move(se));
} }
else else
{ {
do_become(&(bhvr->right()), false); m_loop_stack[0] = std::move(m_loop_stack[1]);
m_loop_stack[1] = std::move(se);
} }
} }
void event_based_actor::do_become(invoke_rules* bhvr, bool has_ownership)
{
reset_timeout();
stack_element::left_type ptr(bhvr);
if (!has_ownership) ptr.get_deleter().disable();
push_to<stack_element>(m_loop_stack, std::move(ptr));
}
void event_based_actor::do_become(timed_invoke_rules* bhvr, bool has_ownership)
{
request_timeout(bhvr->timeout());
stack_element::right_type ptr(bhvr);
if (!has_ownership) ptr.get_deleter().disable();
push_to<stack_element>(m_loop_stack, std::move(ptr));
}
} // namespace cppa } // namespace cppa
...@@ -32,11 +32,7 @@ ...@@ -32,11 +32,7 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
invokable_base::~invokable_base() invokable::~invokable()
{
}
timed_invokable::timed_invokable(const util::duration& d) : m_timeout(d)
{ {
} }
......
...@@ -35,10 +35,9 @@ ...@@ -35,10 +35,9 @@
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/scheduler.hpp" #include "cppa/scheduler.hpp"
#include "cppa/attachable.hpp" #include "cppa/attachable.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/local_actor.hpp"
#include "cppa/scheduled_actor.hpp" #include "cppa/scheduled_actor.hpp"
#include "cppa/detail/thread.hpp" #include "cppa/detail/thread.hpp"
......
...@@ -67,7 +67,12 @@ uniform_type_info const* object_array::type_at(size_t pos) const ...@@ -67,7 +67,12 @@ uniform_type_info const* object_array::type_at(size_t pos) const
return m_elements[pos].type(); return m_elements[pos].type();
} }
std::type_info const* object_array::values_type_list() const void const* object_array::type_token() const
{
return &typeid(object_array);
}
std::type_info const* object_array::impl_type() const
{ {
return &typeid(object_array); return &typeid(object_array);
} }
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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/config.hpp"
#include "cppa/behavior.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/detail/invokable.hpp"
namespace cppa {
partial_function::partial_function(partial_function&& other)
: m_funs(std::move(other.m_funs))
{
}
partial_function::partial_function(invokable_ptr&& ptr)
{
m_funs.push_back(std::move(ptr));
}
auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry&
{
m_dummy.first = value.type_token();
auto end = m_cache.end();
// note: uses >= for comparison (not a "real" upper bound)
auto i = std::upper_bound(m_cache.begin(), end, m_dummy,
[](cache_element const& lhs,
cache_element const& rhs)
{
return lhs.first >= rhs.first;
});
// if we didn't found a cache entry ...
if (i == end || i->first != m_dummy.first)
{
// ... create one (store all invokables with matching types)
cache_entry tmp;
for (auto& fun : m_funs)
{
if (fun->types_match(value))
{
tmp.push_back(fun.get());
}
}
// m_cache is always sorted,
// due to emplace(upper_bound, ...) insertions
i = m_cache.emplace(i, std::move(m_dummy.first), std::move(tmp));
}
return i->second;
}
void partial_function::operator()(any_tuple const& value)
{
auto& v = get_cache_entry(value);
(void) std::any_of(
v.begin(), v.end(),
[&](detail::invokable* i) { return i->unsafe_invoke(value); });
}
detail::invokable const* partial_function::definition_at(any_tuple const& value)
{
auto& v = get_cache_entry(value);
auto i = std::find_if(
v.begin(), v.end(),
[&](detail::invokable* i) { return i->could_invoke(value); });
return (i != v.end()) ? *i : nullptr;
}
bool partial_function::defined_at(any_tuple const& value)
{
return definition_at(value) != nullptr;
}
detail::intermediate* partial_function::get_intermediate(any_tuple const& value)
{
detail::intermediate* result = nullptr;
for (auto& i : get_cache_entry(value))
{
if ((result = i->get_unsafe_intermediate(value)) != nullptr)
{
return result;
}
}
return nullptr;
}
behavior partial_function::operator,(behavior&& arg)
{
behavior bhvr{std::move(arg)};
bhvr.get_partial_function().m_funs = std::move(m_funs);
return bhvr;
}
} // namespace cppa
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
namespace cppa { namespace cppa {
void receive_loop(invoke_rules& rules) void receive_loop(behavior& rules)
{ {
local_actor* sptr = self; local_actor* sptr = self;
for (;;) for (;;)
...@@ -41,7 +41,7 @@ void receive_loop(invoke_rules& rules) ...@@ -41,7 +41,7 @@ void receive_loop(invoke_rules& rules)
} }
} }
void receive_loop(timed_invoke_rules& rules) void receive_loop(partial_function& rules)
{ {
local_actor* sptr = self; local_actor* sptr = self;
for (;;) for (;;)
......
...@@ -45,22 +45,14 @@ void stacked_event_based_actor::unbecome() ...@@ -45,22 +45,14 @@ void stacked_event_based_actor::unbecome()
} }
} }
void stacked_event_based_actor::do_become(invoke_rules* behavior, void stacked_event_based_actor::do_become(behavior* bhvr,
bool has_ownership) bool has_ownership)
{ {
reset_timeout(); reset_timeout();
stack_element::left_type ptr(behavior); request_timeout(bhvr->timeout());
if (!has_ownership) ptr.get_deleter().disable(); stack_element se{bhvr};
m_loop_stack.push_back(std::move(ptr)); if (!has_ownership) se.get_deleter().disable();
} m_loop_stack.push_back(std::move(se));
void stacked_event_based_actor::do_become(timed_invoke_rules* behavior,
bool has_ownership)
{
request_timeout(behavior->timeout());
stack_element::right_type ptr(behavior);
if (!has_ownership) ptr.get_deleter().disable();
m_loop_stack.push_back(std::move(ptr));
} }
} // namespace cppa } // namespace cppa
...@@ -93,7 +93,7 @@ void yielding_actor::yield_until_not_empty() ...@@ -93,7 +93,7 @@ void yielding_actor::yield_until_not_empty()
} }
} }
void yielding_actor::dequeue(invoke_rules& rules) void yielding_actor::dequeue(partial_function& rules)
{ {
queue_node_buffer buffer; queue_node_buffer buffer;
yield_until_not_empty(); yield_until_not_empty();
...@@ -105,8 +105,10 @@ void yielding_actor::dequeue(invoke_rules& rules) ...@@ -105,8 +105,10 @@ void yielding_actor::dequeue(invoke_rules& rules)
} }
} }
void yielding_actor::dequeue(timed_invoke_rules& rules) void yielding_actor::dequeue(behavior& rules)
{ {
if (rules.timeout().valid())
{
queue_node_buffer buffer; queue_node_buffer buffer;
// try until a message was successfully dequeued // try until a message was successfully dequeued
request_timeout(rules.timeout()); request_timeout(rules.timeout());
...@@ -118,7 +120,7 @@ void yielding_actor::dequeue(timed_invoke_rules& rules) ...@@ -118,7 +120,7 @@ void yielding_actor::dequeue(timed_invoke_rules& rules)
//} //}
yield_until_not_empty(); yield_until_not_empty();
queue_node_ptr node(m_mailbox.pop()); queue_node_ptr node(m_mailbox.pop());
switch (dq(node, rules, buffer)) switch (dq(node, rules.get_partial_function(), buffer))
{ {
case dq_done: case dq_done:
{ {
...@@ -132,6 +134,12 @@ void yielding_actor::dequeue(timed_invoke_rules& rules) ...@@ -132,6 +134,12 @@ void yielding_actor::dequeue(timed_invoke_rules& rules)
default: break; default: break;
} }
} }
}
else
{
// suppress virtual function call
yielding_actor::dequeue(rules.get_partial_function());
}
} }
void yielding_actor::resume(util::fiber* from, resume_callback* callback) void yielding_actor::resume(util::fiber* from, resume_callback* callback)
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <iostream> #include <iostream>
#include "test.hpp" #include "test.hpp"
#include "cppa/util.hpp"
#include "cppa/cppa.hpp" #include "cppa/cppa.hpp"
......
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <functional>
#include "test.hpp" #include "test.hpp"
...@@ -11,6 +12,7 @@ ...@@ -11,6 +12,7 @@
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp" #include "cppa/util/disable_if.hpp"
...@@ -19,9 +21,12 @@ ...@@ -19,9 +21,12 @@
#include "cppa/util/is_primitive.hpp" #include "cppa/util/is_primitive.hpp"
#include "cppa/util/is_mutable_ref.hpp" #include "cppa/util/is_mutable_ref.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp" #include "cppa/detail/decorated_tuple.hpp"
#include <boost/progress.hpp>
using namespace cppa; using namespace cppa;
template<typename Arr> template<typename Arr>
...@@ -59,6 +64,35 @@ void match_test(T const& value) ...@@ -59,6 +64,35 @@ void match_test(T const& value)
); );
} }
template<class Testee>
void invoke_test(std::vector<any_tuple>& test_tuples, Testee& x)
{
boost::progress_timer t;
for (int i = 0; i < 1000000; ++i)
{
for (auto& t : test_tuples) x(t);
}
}
inline detail::intermediate* get_i(partial_function& pf, any_tuple const& value)
{
return pf.get_intermediate(value);
}
template<class Testee>
void intermediate_test(std::vector<any_tuple>& test_tuples, Testee& x)
{
boost::progress_timer t;
for (int i = 0; i < 1000000; ++i)
{
for (auto& t : test_tuples)
{
auto i = get_i(x, t);
if (i) i->invoke();
}
}
}
size_t test__pattern() size_t test__pattern()
{ {
CPPA_TEST(test__pattern); CPPA_TEST(test__pattern);
......
...@@ -9,13 +9,11 @@ ...@@ -9,13 +9,11 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/util.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/util.hpp"
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/element_at.hpp" #include "cppa/util/element_at.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
......
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