Commit 2acbbcf9 authored by neverlord's avatar neverlord

minor changes to receive

parent a0616f1b
......@@ -45,6 +45,7 @@ libcppa_la_SOURCES = \
src/post_office_msg.cpp \
src/primitive_variant.cpp \
src/process_information.cpp \
src/receive.cpp \
src/ripemd_160.cpp \
src/abstract_scheduled_actor.cpp \
src/scheduler.cpp \
......
......@@ -243,3 +243,4 @@ cppa/fsm_actor.hpp
cppa/self.hpp
src/self.cpp
cppa/behavior.hpp
src/receive.cpp
......@@ -526,131 +526,6 @@ inline void quit(std::uint32_t 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.
* @returns The last dequeued message from the mailbox.
......
......@@ -33,7 +33,9 @@
#include <new>
#include "cppa/receive.hpp"
#include "cppa/self.hpp"
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/invoke_rules.hpp"
......@@ -43,15 +45,18 @@ template<typename Statement>
struct receive_while_helper
{
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)
{
local_actor* sptr = self;
while (m_stmt())
{
receive(rules);
sptr->dequeue(rules);
}
}
......@@ -63,9 +68,10 @@ struct receive_while_helper
void operator()(timed_invoke_rules& rules)
{
local_actor* sptr = self;
while (m_stmt())
{
receive(rules);
sptr->dequeue(rules);
}
}
......@@ -94,23 +100,18 @@ struct receive_while_helper
class do_receive_helper
{
bool m_timed;
behavior m_bhvr;
union
inline void init(timed_invoke_rules&& bhvr)
{
invoke_rules m_rules;
timed_invoke_rules m_trules;
};
m_bhvr = std::move(bhvr);
}
inline void init(timed_invoke_rules&& ti_rules)
inline void init(invoke_rules& bhvr)
{
m_timed = true;
m_rules.~invoke_rules();
new (&m_trules) timed_invoke_rules(std::move(ti_rules));
m_bhvr = std::move(bhvr);
}
inline void init(invoke_rules&) { }
template<typename Arg0, typename... Args>
inline void init(invoke_rules& rules, Arg0&& arg0, Args&&... args)
{
......@@ -120,34 +121,24 @@ class do_receive_helper
public:
template<typename... Args>
do_receive_helper(invoke_rules&& rules, Args&&... args) : m_timed(false)
do_receive_helper(invoke_rules&& rules) : m_bhvr(std::move(rules))
{
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)
{
new (&m_trules) timed_invoke_rules(std::move(other.m_trules));
}
else
{
new (&m_rules) invoke_rules(std::move(other.m_rules));
}
invoke_rules tmp(std::move(rules));
init(tmp.splice(std::forward<Arg0>(arg0)), std::forward<Args>(args)...);
}
~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>
......@@ -155,11 +146,12 @@ class do_receive_helper
{
static_assert(std::is_same<bool, decltype(stmt())>::value,
"functor or function does not return a boolean");
if (m_timed)
local_actor* sptr = self;
if (m_bhvr.is_left())
{
do
{
receive(m_trules);
sptr->dequeue(m_bhvr.left());
}
while (stmt() == false);
}
......@@ -167,7 +159,7 @@ class do_receive_helper
{
do
{
receive(m_rules);
sptr->dequeue(m_bhvr.right());
}
while (stmt() == false);
}
......
......@@ -87,7 +87,6 @@ class invoke_rule_builder
typedef typename pattern_type_from_type_list<converted_type_list>::type
pattern_type;
//typedef pattern<TypeList...> pattern_type;
typedef std::unique_ptr<pattern_type> pattern_ptr_type;
pattern_ptr_type m_pattern;
......@@ -194,7 +193,7 @@ detail::invoke_rule_builder<atom_value, atom_value, atom_value,
}
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)
{
return { util::duration(d) };
......
......@@ -32,51 +32,184 @@
#define RECEIVE_HPP
#include "cppa/self.hpp"
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/detail/receive_loop_helper.hpp"
namespace cppa {
/**
* @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);
}
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);
}
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)),
std::forward<Tail>(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)...);
}
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
#endif // RECEIVE_HPP
......@@ -135,22 +135,4 @@ void demonitor(actor_ptr& whom)
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
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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()
CPPA_CHECK_EQUAL(atom(" "), atom("@!?"));
CPPA_CHECK_NOT_EQUAL(atom("abc"), atom(" abc"));
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))
<< make_tuple(atom(":Attach"), atom(":Baz"), "cstring")
<< 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