Commit 2acbbcf9 authored by neverlord's avatar neverlord

minor changes to receive

parent a0616f1b
...@@ -45,6 +45,7 @@ libcppa_la_SOURCES = \ ...@@ -45,6 +45,7 @@ libcppa_la_SOURCES = \
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/ripemd_160.cpp \ src/ripemd_160.cpp \
src/abstract_scheduled_actor.cpp \ src/abstract_scheduled_actor.cpp \
src/scheduler.cpp \ src/scheduler.cpp \
......
...@@ -243,3 +243,4 @@ cppa/fsm_actor.hpp ...@@ -243,3 +243,4 @@ cppa/fsm_actor.hpp
cppa/self.hpp cppa/self.hpp
src/self.cpp src/self.cpp
cppa/behavior.hpp cppa/behavior.hpp
src/receive.cpp
...@@ -526,131 +526,6 @@ inline void quit(std::uint32_t reason) ...@@ -526,131 +526,6 @@ inline void quit(std::uint32_t reason)
self->quit(reason); self->quit(reason);
} }
/**
* @brief Receives messages in an endless loop.
*
* Semantically equal to: <tt>for (;;) { receive(rules); }</tt>
* @param rules Invoke rules to receive and handle messages.
*/
void receive_loop(invoke_rules& rules);
/**
* @copydoc receive_loop(invoke_rules&)
* Support for invoke rules with timeout.
*/
void receive_loop(timed_invoke_rules& rules);
/**
* @copydoc receive_loop(invoke_rules&)
* Support for rvalue references.
*/
inline void receive_loop(invoke_rules&& rules)
{
invoke_rules tmp(std::move(rules));
receive_loop(tmp);
}
/**
* @copydoc receive_loop(invoke_rules&)
* Support for rvalue references and timeout.
*/
inline void receive_loop(timed_invoke_rules&& rules)
{
timed_invoke_rules tmp(std::move(rules));
receive_loop(tmp);
}
/**
* @brief Receives messages in an endless loop.
*
* This function overload provides a simple way to define a receive loop
* with on-the-fly {@link invoke_rules}.
*
* @b Example:
* @code
* receive_loop(on<int>() >> int_fun, on<float>() >> float_fun);
* @endcode
* @see receive_loop(invoke_rules&)
*/
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)...);
}
/**
* @brief Receives messages in an endless loop.
*
* This function overload provides a simple way to define a receive loop
* with on-the-fly {@link invoke_rules}.
*
* @b Example:
* @code
* receive_loop(on<int>() >> int_fun, on<float>() >> float_fun);
* @endcode
* @see receive_loop(invoke_rules&)
*
* Support for rvalue references.
*/
template<typename Head, typename... Tail>
void receive_loop(invoke_rules&& rules, Head&& head, Tail&&... tail)
{
invoke_rules tmp(std::move(rules));
receive_loop(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
/**
* @brief Receives messages as long as @p stmt returns true.
*
* Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_while([&]() { return (++i <= 10); })
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* );
* @endcode
* @param stmt Lambda expression, functor or function returning a @c bool.
* @returns A functor implementing the loop.
*/
template<typename Statement>
detail::receive_while_helper<Statement>
receive_while(Statement&& stmt)
{
static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean");
return std::move(stmt);
}
/**
* @brief Receives messages until @p stmt returns true.
*
* Semantically equal to: <tt>do { receive(...); } while (stmt() == false);</tt>
*
* <b>Usage example:</b>
* @code
* int i = 0;
* do_receive
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* )
* .until([&]() { return (++i >= 10); };
* @endcode
* @param args Invoke rules to handle received messages.
* @returns A functor providing the @c until member function.
*/
template<typename... Args>
detail::do_receive_helper do_receive(Args&&... args)
{
return detail::do_receive_helper(std::forward<Args>(args)...);
}
/** /**
* @brief Gets the last dequeued message from the mailbox. * @brief Gets the last dequeued message from the mailbox.
* @returns The last dequeued message from the mailbox. * @returns The last dequeued message from the mailbox.
......
...@@ -33,7 +33,9 @@ ...@@ -33,7 +33,9 @@
#include <new> #include <new>
#include "cppa/receive.hpp" #include "cppa/self.hpp"
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
...@@ -43,15 +45,18 @@ template<typename Statement> ...@@ -43,15 +45,18 @@ template<typename Statement>
struct receive_while_helper struct receive_while_helper
{ {
Statement m_stmt; Statement m_stmt;
receive_while_helper(Statement&& stmt) : m_stmt(std::move(stmt))
template<typename S>
receive_while_helper(S&& stmt) : m_stmt(std::forward<S>(stmt))
{ {
} }
void operator()(invoke_rules& rules) void operator()(invoke_rules& rules)
{ {
local_actor* sptr = self;
while (m_stmt()) while (m_stmt())
{ {
receive(rules); sptr->dequeue(rules);
} }
} }
...@@ -63,9 +68,10 @@ struct receive_while_helper ...@@ -63,9 +68,10 @@ struct receive_while_helper
void operator()(timed_invoke_rules& rules) void operator()(timed_invoke_rules& rules)
{ {
local_actor* sptr = self;
while (m_stmt()) while (m_stmt())
{ {
receive(rules); sptr->dequeue(rules);
} }
} }
...@@ -94,23 +100,18 @@ struct receive_while_helper ...@@ -94,23 +100,18 @@ struct receive_while_helper
class do_receive_helper class do_receive_helper
{ {
bool m_timed; behavior m_bhvr;
union inline void init(timed_invoke_rules&& bhvr)
{ {
invoke_rules m_rules; m_bhvr = std::move(bhvr);
timed_invoke_rules m_trules; }
};
inline void init(timed_invoke_rules&& ti_rules) inline void init(invoke_rules& bhvr)
{ {
m_timed = true; m_bhvr = std::move(bhvr);
m_rules.~invoke_rules();
new (&m_trules) timed_invoke_rules(std::move(ti_rules));
} }
inline void init(invoke_rules&) { }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
inline void init(invoke_rules& rules, Arg0&& arg0, Args&&... args) inline void init(invoke_rules& rules, Arg0&& arg0, Args&&... args)
{ {
...@@ -120,34 +121,24 @@ class do_receive_helper ...@@ -120,34 +121,24 @@ class do_receive_helper
public: public:
template<typename... Args> do_receive_helper(invoke_rules&& rules) : m_bhvr(std::move(rules))
do_receive_helper(invoke_rules&& rules, Args&&... args) : m_timed(false)
{ {
new (&m_rules) invoke_rules(std::move(rules));
init(m_rules, std::forward<Args>(args)...);
} }
do_receive_helper(timed_invoke_rules&& rules) : m_timed(true) do_receive_helper(timed_invoke_rules&& rules) : m_bhvr(std::move(rules))
{ {
new (&m_trules) timed_invoke_rules(std::move(rules));
} }
do_receive_helper(do_receive_helper&& other) : m_timed(other.m_timed) template<typename Arg0, typename... Args>
do_receive_helper(invoke_rules&& rules, Arg0&& arg0, Args&&... args)
{ {
if (other.m_timed) invoke_rules tmp(std::move(rules));
{ init(tmp.splice(std::forward<Arg0>(arg0)), std::forward<Args>(args)...);
new (&m_trules) timed_invoke_rules(std::move(other.m_trules));
}
else
{
new (&m_rules) invoke_rules(std::move(other.m_rules));
}
} }
~do_receive_helper() do_receive_helper(do_receive_helper&& other)
: m_bhvr(std::move(other.m_bhvr))
{ {
if (m_timed) m_trules.~timed_invoke_rules();
else m_rules.~invoke_rules();
} }
template<typename Statement> template<typename Statement>
...@@ -155,11 +146,12 @@ class do_receive_helper ...@@ -155,11 +146,12 @@ 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");
if (m_timed) local_actor* sptr = self;
if (m_bhvr.is_left())
{ {
do do
{ {
receive(m_trules); sptr->dequeue(m_bhvr.left());
} }
while (stmt() == false); while (stmt() == false);
} }
...@@ -167,7 +159,7 @@ class do_receive_helper ...@@ -167,7 +159,7 @@ class do_receive_helper
{ {
do do
{ {
receive(m_rules); sptr->dequeue(m_bhvr.right());
} }
while (stmt() == false); while (stmt() == false);
} }
......
...@@ -87,7 +87,6 @@ class invoke_rule_builder ...@@ -87,7 +87,6 @@ class invoke_rule_builder
typedef typename pattern_type_from_type_list<converted_type_list>::type typedef typename pattern_type_from_type_list<converted_type_list>::type
pattern_type; pattern_type;
//typedef pattern<TypeList...> pattern_type;
typedef std::unique_ptr<pattern_type> pattern_ptr_type; typedef std::unique_ptr<pattern_type> pattern_ptr_type;
pattern_ptr_type m_pattern; pattern_ptr_type m_pattern;
...@@ -194,7 +193,7 @@ detail::invoke_rule_builder<atom_value, atom_value, atom_value, ...@@ -194,7 +193,7 @@ detail::invoke_rule_builder<atom_value, atom_value, atom_value,
} }
template<class Rep, class Period> template<class Rep, class Period>
inline constexpr detail::timed_invoke_rule_builder constexpr detail::timed_invoke_rule_builder
after(const std::chrono::duration<Rep, Period>& d) after(const std::chrono::duration<Rep, Period>& d)
{ {
return { util::duration(d) }; return { util::duration(d) };
......
...@@ -32,51 +32,184 @@ ...@@ -32,51 +32,184 @@
#define RECEIVE_HPP #define RECEIVE_HPP
#include "cppa/self.hpp" #include "cppa/self.hpp"
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp" #include "cppa/local_actor.hpp"
#include "cppa/detail/receive_loop_helper.hpp"
namespace cppa { namespace cppa {
/** /**
* @brief Dequeues the next message from the mailbox that's matched * @brief Dequeues the next message from the mailbox that's matched
* by @p rules and executes the corresponding callback. * by @p bhvr and executes the corresponding callback.
*/ */
inline void receive(invoke_rules& rules) inline void receive(invoke_rules& bhvr)
{ {
self->dequeue(rules); self->dequeue(bhvr);
} }
inline void receive(timed_invoke_rules& rules) inline void receive(timed_invoke_rules& bhvr)
{ {
self->dequeue(rules); self->dequeue(bhvr);
} }
inline void receive(timed_invoke_rules&& rules) inline void receive(timed_invoke_rules&& bhvr)
{ {
timed_invoke_rules tmp(std::move(rules)); timed_invoke_rules tmp(std::move(bhvr));
self->dequeue(tmp); self->dequeue(tmp);
} }
inline void receive(invoke_rules&& rules) inline void receive(invoke_rules&& bhvr)
{ {
invoke_rules tmp(std::move(rules)); invoke_rules tmp(std::move(bhvr));
self->dequeue(tmp); self->dequeue(tmp);
} }
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
void receive(invoke_rules&& rules, Head&& head, Tail&&... tail) void receive(invoke_rules&& bhvr, Head&& head, Tail&&... tail)
{ {
invoke_rules tmp(std::move(rules)); invoke_rules tmp(std::move(bhvr));
receive(tmp.splice(std::forward<Head>(head)), receive(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...); std::forward<Tail>(tail)...);
} }
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
void receive(invoke_rules& rules, Head&& head, Tail&&... tail) void receive(invoke_rules& bhvr, Head&& head, Tail&&... tail)
{ {
receive(rules.splice(std::forward<Head>(head)), receive(bhvr.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...); std::forward<Tail>(tail)...);
} }
inline void receive(behavior& bhvr)
{
if (bhvr.is_left()) receive(bhvr.left());
else receive(bhvr.right());
}
/**
* @brief Receives messages in an endless loop.
*
* Semantically equal to: <tt>for (;;) { receive(rules); }</tt>
* @param rules Invoke rules to receive and handle messages.
*/
void receive_loop(invoke_rules& rules);
/**
* @copydoc receive_loop(invoke_rules&)
* Support for invoke rules with timeout.
*/
void receive_loop(timed_invoke_rules& rules);
/**
* @copydoc receive_loop(invoke_rules&)
* Support for rvalue references.
*/
inline void receive_loop(invoke_rules&& rules)
{
invoke_rules tmp(std::move(rules));
receive_loop(tmp);
}
/**
* @copydoc receive_loop(invoke_rules&)
* Support for rvalue references and timeout.
*/
inline void receive_loop(timed_invoke_rules&& rules)
{
timed_invoke_rules tmp(std::move(rules));
receive_loop(tmp);
}
/**
* @brief Receives messages in an endless loop.
*
* This function overload provides a simple way to define a receive loop
* with on-the-fly {@link invoke_rules}.
*
* @b Example:
* @code
* receive_loop(on<int>() >> int_fun, on<float>() >> float_fun);
* @endcode
* @see receive_loop(invoke_rules&)
*/
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)...);
}
/**
* @brief Receives messages in an endless loop.
*
* This function overload provides a simple way to define a receive loop
* with on-the-fly {@link invoke_rules}.
*
* @b Example:
* @code
* receive_loop(on<int>() >> int_fun, on<float>() >> float_fun);
* @endcode
* @see receive_loop(invoke_rules&)
*
* Support for rvalue references.
*/
template<typename Head, typename... Tail>
void receive_loop(invoke_rules&& rules, Head&& head, Tail&&... tail)
{
invoke_rules tmp(std::move(rules));
receive_loop(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
/**
* @brief Receives messages as long as @p stmt returns true.
*
* Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_while([&]() { return (++i <= 10); })
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* );
* @endcode
* @param stmt Lambda expression, functor or function returning a @c bool.
* @returns A functor implementing the loop.
*/
template<typename Statement>
detail::receive_while_helper<Statement>
receive_while(Statement&& stmt)
{
static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean");
return std::move(stmt);
}
/**
* @brief Receives messages until @p stmt returns true.
*
* Semantically equal to: <tt>do { receive(...); } while (stmt() == false);</tt>
*
* <b>Usage example:</b>
* @code
* int i = 0;
* do_receive
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* )
* .until([&]() { return (++i >= 10); };
* @endcode
* @param args Invoke rules to handle received messages.
* @returns A functor providing the @c until member function.
*/
template<typename... Args>
detail::do_receive_helper do_receive(Args&&... args)
{
return detail::do_receive_helper(std::forward<Args>(args)...);
}
} // namespace cppa } // namespace cppa
#endif // RECEIVE_HPP #endif // RECEIVE_HPP
...@@ -135,22 +135,4 @@ void demonitor(actor_ptr& whom) ...@@ -135,22 +135,4 @@ void demonitor(actor_ptr& whom)
if (whom) whom->detach(mtoken); if (whom) whom->detach(mtoken);
} }
void receive_loop(invoke_rules& rules)
{
local_actor* sptr = self;
for (;;)
{
sptr->dequeue(rules);
}
}
void receive_loop(timed_invoke_rules& rules)
{
local_actor* sptr = self;
for (;;)
{
sptr->dequeue(rules);
}
}
} // namespace cppa } // namespace cppa
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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/receive.hpp"
namespace cppa {
void receive_loop(invoke_rules& rules)
{
local_actor* sptr = self;
for (;;)
{
sptr->dequeue(rules);
}
}
void receive_loop(timed_invoke_rules& rules)
{
local_actor* sptr = self;
for (;;)
{
sptr->dequeue(rules);
}
}
} // namespace cppa
...@@ -35,7 +35,6 @@ size_t test__atom() ...@@ -35,7 +35,6 @@ size_t test__atom()
CPPA_CHECK_EQUAL(atom(" "), atom("@!?")); CPPA_CHECK_EQUAL(atom(" "), atom("@!?"));
CPPA_CHECK_NOT_EQUAL(atom("abc"), atom(" abc")); CPPA_CHECK_NOT_EQUAL(atom("abc"), atom(" abc"));
CPPA_CHECK_EQUAL(to_string(s_foo), "FooBar"); CPPA_CHECK_EQUAL(to_string(s_foo), "FooBar");
cout << to_string(s_foo) << endl;
self << make_tuple(atom("foo"), static_cast<std::uint32_t>(42)) self << make_tuple(atom("foo"), static_cast<std::uint32_t>(42))
<< make_tuple(atom(":Attach"), atom(":Baz"), "cstring") << make_tuple(atom(":Attach"), atom(":Baz"), "cstring")
<< make_tuple(atom("b"), atom("a"), atom("c"), 23.f) << make_tuple(atom("b"), atom("a"), atom("c"), 23.f)
......
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