Commit 777fc9bf authored by neverlord's avatar neverlord

documentation

parent 4c39c810
......@@ -32,24 +32,27 @@
#define CPPA_HPP
#include <tuple>
#include <chrono>
#include <cstdint>
#include <functional>
#include <type_traits>
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/self.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/actor.hpp"
#include "cppa/channel.hpp"
#include "cppa/receive.hpp"
#include "cppa/factory.hpp"
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp"
#include "cppa/sb_actor.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/fsm_actor.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/scheduled_actor.hpp"
#include "cppa/scheduling_hint.hpp"
#include "cppa/event_based_actor.hpp"
......@@ -69,41 +72,45 @@
*
* This library provides an implementation of the actor model for C++.
* It uses a network transparent messaging system to ease development
* of both concurrent and distributed software using C++.
* of both concurrent and distributed software.
*
* @p libcppa uses a thread pool to schedule actors by default.
* A scheduled actor should not call blocking functions.
* Individual actors can be spawned (created) with a special flag to run in
* an own thread if one needs to make use of blocking APIs.
*
* Writing applications in @p libcppa requires a minimum of gluecode.
* You don't have to derive a particular class to implement an actor and
* Writing applications in @p libcppa requires a minimum of gluecode and
* each context <i>is</i> an actor. Even main is implicitly
* converted to an actor if needed, as the following example shows:
*
* It's recommended to read at least the
* {@link MessageHandling message handling}
* section of this documentation.
* converted to an actor if needed.
*
* @section GettingStarted Getting Started
*
* To build @p libcppa, you need <tt>GCC >= 4.6</tt>, @p Automake
* and the <tt>Boost.Thread</tt> library.
* To build @p libcppa, you need <tt>GCC >= 4.7</tt> or <tt>Clang >= 3.2</tt>,
* @p CMake and the <tt>Boost.Thread</tt> library.
*
* The usual build steps on Linux and Mac OS X are:
*
* - <tt>autoreconf -i</tt>
* - <tt>./configure</tt>
* - <tt>make</tt>
* - <tt>make install</tt> (as root, optionally)
*- <tt>mkdir build</tt>
*- <tt>cd build</tt>
*- <tt>cmake ..</tt>
*- <tt>make</tt>
*- <tt>make install</tt> (as root, optionally)
*
* Please run the unit tests as well to verify that @p libcppa works properly.
*
* Use <tt>./configure --help</tt> if the script doesn't auto-select
* the correct @p GCC binary or doesn't find your <tt>Boost.Thread</tt>
* installation.
*- <tt>./bin/unit_tests</tt>
*
* Please submit a bug report that includes (a) your compiler version,
* (b) your OS, and (c) the output of the unit tests if an error occurs.
*
* Windows is not supported yet, because MVSC++ doesn't implement the
* C++11 features needed to compile @p libcppa.
*
* Please read the <b>Manual</b> for an introduction to @p libcppa.
* It is available online at
* http://neverlord.github.com/libcppa/manual/index.html or as PDF version at
* http://neverlord.github.com/libcppa/manual/libcppa_manual.pdf
*
* @section IntroHelloWorld Hello World Example
*
* @include hello_world_example.cpp
......@@ -117,24 +124,32 @@
* features.
*
* @namespace cppa
* @brief This is the root namespace of libcppa.
*
* Thie @b cppa namespace contains all functions and classes to
* implement Actor based applications.
* @brief Root namespace of libcppa.
*
* @namespace cppa::util
* @brief This namespace contains utility classes and metaprogramming
* @brief Contains utility classes and metaprogramming
* utilities used by the libcppa implementation.
*
* @namespace cppa::intrusive
* @brief This namespace contains intrusive container implementations.
* @brief Contains intrusive container implementations.
*
* @namespace cppa::factory
* @brief Contains factory functions to create actors from lambdas or
* other functors.
*
* @namespace cppa::exit_reason
* @brief Contains all predefined exit reasons.
*
* @namespace cppa::placeholders
* @brief Contains the guard placeholders @p _x1 to @p _x9.
*
* @defgroup CopyOnWrite Copy-on-write optimization.
* @p libcppa uses a copy-on-write optimization for its message
* passing implementation.
*
* {@link cppa::tuple Tuples} should @b always be used with by-value semantic,
* since tuples use a copy-on-write smart pointer internally. Let's assume two
* {@link cppa::cow_tuple Tuples} should @b always be used with by-value
* semantic,since tuples use a copy-on-write smart pointer internally.
* Let's assume two
* tuple @p x and @p y, whereas @p y is a copy of @p x:
*
* @code
......@@ -239,16 +254,13 @@
* to define patterns:
*
* @code
* receive
* (
* on(atom("hello"), val<std::string>()) >> [](const std::string& msg)
* {
* receive (
* on(atom("hello"), val<std::string>()) >> [](const std::string& msg) {
* cout << "received hello message: " << msg << endl;
* },
* on(atom("compute"), val<int>(), val<int>(), val<int>()>() >> [](int i0, int i1, int i2)
* {
* on(atom("compute"), val<int>(), val<int>()>() >> [](int i0, int i1) {
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1 + i2);
* reply(atom("result"), i0 + i1);
* }
* );
* @endcode
......@@ -263,16 +275,12 @@
*
* Example actor:
* @code
* void math_actor()
* {
* receive_loop
* (
* on<atom("plus"), int, int>() >> [](int a, int b)
* {
* void math_actor() {
* receive_loop (
* on<atom("plus"), int, int>() >> [](int a, int b) {
* reply(atom("result"), a + b);
* },
* on<atom("minus"), int, int>() >> [](int a, int b)
* {
* on<atom("minus"), int, int>() >> [](int a, int b) {
* reply(atom("result"), a - b);
* }
* );
......@@ -300,10 +308,8 @@
* @code
* // receive two integers
* vector<int> received_values;
* receive_while([&]() { return received_values.size() < 2; })
* (
* on<int>() >> [](int value)
* {
* receive_while([&]() { return received_values.size() < 2; }) (
* on<int>() >> [](int value) {
* received_values.push_back(value);
* }
* );
......@@ -315,8 +321,7 @@
* @code
* std::vector<int> vec {1, 2, 3, 4};
* auto i = vec.begin();
* receive_for(i, vec.end())
* (
* receive_for(i, vec.end()) (
* on(atom("get")) >> [&]() { reply(atom("result"), *i); }
* );
* @endcode
......@@ -328,10 +333,8 @@
* @code
* // receive ints until zero was received
* vector<int> received_values;
* do_receive
* (
* on<int>() >> [](int value)
* {
* do_receive (
* on<int>() >> [](int value) {
* received_values.push_back(value);
* }
* )
......@@ -341,20 +344,18 @@
*
* @section FutureSend Send delayed messages
*
* The function @p future_send provides a simple way to delay a message.
* The function @p delayed_send provides a simple way to delay a message.
* This is particularly useful for recurring events, e.g., periodical polling.
* Usage example:
*
* @code
* future_send(self, std::chrono::seconds(1), atom("poll"));
* receive_loop
* (
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
* receive_loop (
* // ...
* on<atom("poll")>() >> []()
* {
* on<atom("poll")>() >> []() {
* // ... poll something ...
* // and do it again after 1sec
* future_send(self, std::chrono::seconds(1), atom("poll"));
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
* }
* );
* @endcode
......@@ -365,7 +366,7 @@
*
* The message passing of @p libcppa prohibits pointers in messages because
* it enforces network transparent messaging.
* Unfortunately, string literals in @p C++ have the type <tt>char const*</tt>,
* Unfortunately, string literals in @p C++ have the type <tt>const char*</tt>,
* resp. <tt>const char[]</tt>. Since @p libcppa is a user-friendly library,
* it silently converts string literals and C-strings to @p std::string objects.
* It also converts unicode literals to the corresponding STL container.
......@@ -375,7 +376,7 @@
* // sends an std::string containing "hello actor!" to itself
* send(self, "hello actor!");
*
* char const* cstring = "cstring";
* const char* cstring = "cstring";
* // sends an std::string containing "cstring" to itself
* send(self, cstring);
*
......@@ -385,14 +386,13 @@
* // x has the type cppa::tuple<std::string, std::string>
* auto x = make_cow_tuple("hello", "tuple");
*
* receive
* (
* receive (
* // equal to: on(std::string("hello actor!"))
* on("hello actor!") >> []() { }
* );
* @endcode
*
* @defgroup ActorManagement Actor management.
* @defgroup ActorCreation Actor creation.
*
*/
......@@ -410,7 +410,7 @@
*/
/**
* @brief A simple example for a future_send based application.
* @brief A simple example for a delayed_send based application.
* @example dancing_kirby.cpp
*/
......@@ -421,295 +421,323 @@
namespace cppa {
/**
* @ingroup ActorManagement
* @brief Links @p lhs and @p rhs;
* @pre <tt>lhs != rhs</tt>
*/
void link(actor_ptr& lhs, actor_ptr& rhs);
#ifdef CPPA_DOCUMENTATION
/**
* @copydoc link(actor_ptr&,actor_ptr&)
* @ingroup MessageHandling
* @{
*/
void link(actor_ptr&& lhs, actor_ptr& rhs);
/**
* @copydoc link(actor_ptr&,actor_ptr&)
* @brief Sends <tt>{what...}</tt> as a message to @p whom.
* @param whom Receiver of the message.
* @param what Message elements.
*/
void link(actor_ptr&& lhs, actor_ptr&& rhs);
template<typename... Args>
void send(const channel_ptr& whom, Args&&... what);
/**
* @copydoc link(actor_ptr&,actor_ptr&)
* @brief Send a message to @p whom.
*
* <b>Usage example:</b>
* @code
* self << make_any_tuple(1, 2, 3);
* @endcode
* @param whom Receiver of the message.
* @param what Message as instance of {@link any_tuple}.
* @returns @p whom.
*/
void link(actor_ptr& lhs, actor_ptr&& rhs);
const channel_ptr& operator<<(const channel_ptr& whom, any_tuple what);
/**
* @ingroup ActorManagement
* @brief Unlinks @p lhs from @p rhs;
* @pre <tt>lhs != rhs</tt>
*/
void unlink(actor_ptr& lhs, actor_ptr& rhs);
/** @} */
/**
* @ingroup ActorManagement
* @brief Adds a unidirectional @p monitor to @p whom.
* @note Each calls to @p monitor creates a new, independent monitor.
* @pre The calling actor receives a ":Down" message from @p whom when
* it terminates.
* @ingroup ActorCreation
* @{
*/
void monitor(actor_ptr& whom);
void monitor(actor_ptr&& whom);
/**
* @ingroup ActorManagement
* @brief Removes a monitor from @p whom.
* @brief Spawns a new context-switching or thread-mapped {@link actor}
* that executes <tt>fun(args...)</tt>.
* @param fun A function implementing the actor's behavior.
* @param args Optional function parameters for @p fun.
* @tparam Hint A hint to the scheduler for the best scheduling strategy.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
*/
void demonitor(actor_ptr& whom);
template<scheduling_hint Hint, typename Fun, typename... Args>
actor_ptr spawn(Fun fun, Args&&... args);
/**
* @ingroup ActorManagement
* @brief Spans a new context-switching actor.
* @returns A pointer to the spawned {@link actor Actor}.
* @brief Spawns a new context-switching {@link actor}
* that executes <tt>fun(args...)</tt>.
* @param fun A function implementing the actor's behavior.
* @param args Optional function parameters for @p fun.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @note This function is equal to <tt>spawn<scheduled>(fun, args...)</tt>.
*/
inline actor_ptr spawn(scheduled_actor* what)
{
return get_scheduler()->spawn(what, scheduled);
}
template<typename Fun, typename... Args>
actor_ptr spawn(Fun fun, Args&&... args);
/**
* @ingroup ActorManagement
* @brief Spans a new context-switching actor.
* @tparam Hint Hint to the scheduler for the best scheduling strategy.
* @returns A pointer to the spawned {@link actor Actor}.
* @brief Spawns a new context-switching or thread-mapped {@link actor}
* that executes <tt>fun(args...)</tt> and
* joins @p grp immediately.
* @param fun A function implementing the actor's behavior.
* @param args Optional function parameters for @p fun.
* @tparam Hint A hint to the scheduler for the best scheduling strategy.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @note The spawned actor joins @p grp after its
* {@link local_actor::init() init} member function is called but
* before it is executed. Hence, the spawned actor already joined
* the group before this function returns.
*/
template<scheduling_hint Hint>
inline actor_ptr spawn(scheduled_actor* what)
{
return get_scheduler()->spawn(what, Hint);
}
template<scheduling_hint Hint, typename Fun, typename... Args>
actor_ptr spawn_in_group(Fun fun, Args&&... args);
/**
* @ingroup ActorManagement
* @brief Spans a new event-based actor.
* @returns A pointer to the spawned {@link actor Actor}.
* @brief Spawns a new context-switching {@link actor}
* that executes <tt>fun(args...)</tt> and
* joins @p grp immediately.
* @param fun A function implementing the actor's behavior.
* @param args Optional function parameters for @p fun.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @note The spawned actor joins @p grp after its
* {@link local_actor::init() init} member function is called but
* before it is executed. Hence, the spawned actor already joined
* the group before this function returns.
* @note This function is equal to
* <tt>spawn_in_group<scheduled>(fun, args...)</tt>.
*/
inline actor_ptr spawn(abstract_event_based_actor* what)
{
return get_scheduler()->spawn(what);
}
template<typename Fun, typename... Args>
actor_ptr spawn_in_group(Fun fun, Args&&... args);
/**
* @ingroup ActorManagement
* @brief Spawns a new actor that executes @p what with given arguments.
* @tparam Hint Hint to the scheduler for the best scheduling strategy.
* @param what Function or functor that the spawned Actor should execute.
* @param args Arguments needed to invoke @p what.
* @returns A pointer to the spawned {@link actor actor}.
* @brief Spawns an actor of type @p ActorImpl.
* @param args Optional constructor arguments.
* @tparam ActorImpl Subtype of {@link event_based_actor} or {@link sb_actor}.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
*/
template<scheduling_hint Hint, typename F, typename... Args>
auto //actor_ptr
spawn(F&& what, const Args&... args)
-> typename std::enable_if<
!std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value
&& !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value,
actor_ptr
>::type
{
typedef typename util::rm_ref<F>::type ftype;
std::integral_constant<bool, std::is_function<ftype>::value> is_fun;
auto ptr = detail::get_behavior(is_fun, std::forward<F>(what), args...);
return get_scheduler()->spawn(ptr, Hint);
}
template<class ActorImpl, typename... Args>
actor_ptr spawn(const group_ptr& grp, Args&&... args);
/**
* @ingroup ActorManagement
* @brief Alias for <tt>spawn<scheduled>(what, args...)</tt>.
* @brief Spawns an actor of type @p ActorImpl that joins @p grp immediately.
* @param grp The group that the newly created actor shall join.
* @param args Optional constructor arguments.
* @tparam ActorImpl Subtype of {@link event_based_actor} or {@link sb_actor}.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @note The spawned actor joins @p grp after its
* {@link local_actor::init() init} member function is called but
* before it is executed. Hence, the spawned actor already joined
* the group before this function returns.
*/
template<typename F, typename... Args>
auto // actor_ptr
spawn(F&& what, const Args&... args)
-> typename std::enable_if<
!std::is_convertible<typename util::rm_ref<F>::type, scheduled_actor*>::value
&& !std::is_convertible<typename util::rm_ref<F>::type, event_based_actor*>::value,
actor_ptr
>::type
{
return spawn<scheduled>(std::forward<F>(what), args...);
template<class ActorImpl, typename... Args>
actor_ptr spawn_in_group(const group_ptr& grp, Args&&... args);
/** @} */
#else
inline actor_ptr spawn(void_function fun) {
return get_scheduler()->spawn(std::move(fun), scheduled);
}
#ifdef CPPA_DOCUMENTATION
template<scheduling_hint Hint>
inline actor_ptr spawn(void_function fun) {
return get_scheduler()->spawn(std::move(fun), Hint);
}
/**
* @ingroup MessageHandling
* @brief Sends <tt>{arg0, args...}</tt> as a message to @p whom.
*/
template<typename Arg0, typename... Args>
void send(channel_ptr& whom, const Arg0& arg0, const Args&... args);
// forwards self_type as actor_ptr
template<typename T>
struct spawn_fwd_ {
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
static inline const T& _(const T& arg) { return arg; }
};
template<>
struct spawn_fwd_<self_type> {
static inline actor_ptr _(const self_type& s) { return s.get(); }
};
template<scheduling_hint Hint, typename Fun, typename Arg0, typename... Args>
inline actor_ptr spawn(Fun fun, Arg0&& arg0, Args&&... args) {
return get_scheduler()->spawn(
std::bind(
std::move(fun),
spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...),
Hint);
}
/**
* @ingroup MessageHandling
* @brief Send a message to @p whom.
*
* <b>Usage example:</b>
* @code
* self << make_cow_tuple(1, 2, 3);
* @endcode
* @returns @p whom.
*/
channel_ptr& operator<<(channel_ptr& whom, const any_tuple& what);
template<typename Fun, typename Arg0, typename... Args>
inline actor_ptr spawn(Fun&& fun, Arg0&& arg0, Args&&... args) {
return spawn<scheduled>(std::forward<Fun>(fun),
std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
}
#else
template<class ActorImpl, typename... Args>
inline actor_ptr spawn(Args&&... args) {
return get_scheduler()->spawn(new ActorImpl(std::forward<Args>(args)...));
}
template<class C, typename Arg0, typename... Args>
void send(intrusive_ptr<C>& whom, const Arg0& arg0, const Args&... args)
{
static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
if (whom) whom->enqueue(self, make_cow_tuple(arg0, args...));
template<scheduling_hint Hint>
inline actor_ptr spawn_in_group(const group_ptr& grp, void_function fun) {
return get_scheduler()->spawn(std::move(fun), Hint, [grp](local_actor* ptr){
ptr->join(grp);
});
}
template<class C, typename Arg0, typename... Args>
void send(intrusive_ptr<C>&& whom, const Arg0& arg0, const Args&... args)
{
static_assert(std::is_base_of<channel, C>::value, "C is not a channel");
intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, make_cow_tuple(arg0, args...));
inline actor_ptr spawn_in_group(const group_ptr& grp, void_function fun) {
return spawn_in_group<scheduled>(grp, std::move(fun));
}
// matches "send(this, ...)" in event-based actors
template<typename Arg0, typename... Args>
void send(local_actor* whom, const Arg0& arg0, const Args&... args)
{
whom->enqueue(whom, make_cow_tuple(arg0, args...));
template<scheduling_hint Hint, typename Fun, typename Arg0, typename... Args>
inline actor_ptr spawn_in_group(const group_ptr& grp,
Fun fun, Arg0&& arg0, Args&&... args) {
return spawn_in_group<Hint>(
grp,
std::bind(
std::move(fun),
spawn_fwd_<typename util::rm_ref<Arg0>::type>::_(arg0),
spawn_fwd_<typename util::rm_ref<Args>::type>::_(args)...));
}
template<typename Fun, typename Arg0, typename... Args>
inline actor_ptr spawn_in_group(const group_ptr& grp,
Fun&& fun, Arg0&& arg0, Args&&... args) {
return spawn_in_group<scheduled>(grp,
std::forward<Fun>(fun),
std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
}
// matches send(self, ...);
template<typename Arg0, typename... Args>
inline void send(const self_type&, const Arg0& arg0, const Args&... args)
{
send(static_cast<local_actor*>(self), arg0, args...);
template<class ActorImpl, typename... Args>
inline actor_ptr spawn_in_group(const group_ptr& grp, Args&&... args) {
return get_scheduler()->spawn(new ActorImpl(std::forward<Args>(args)...),
[&grp](local_actor* ptr) { ptr->join(grp); });
}
template<class C>
typename std::enable_if<
std::is_base_of<channel, C>::value,
intrusive_ptr<C>&
>::type
operator<<(intrusive_ptr<C>& whom, const any_tuple& what)
{
if (whom) whom->enqueue(self, what);
return whom;
namespace detail {
inline void send_impl(channel* whom, any_tuple&& what) {
if (whom) self->send_message(whom, std::move(what));
}
template<class C>
typename std::enable_if<
std::is_base_of<channel, C>::value,
intrusive_ptr<C>
>::type
operator<<(intrusive_ptr<C>&& whom, const any_tuple& what)
{
intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, what);
return std::move(tmp);
template<typename Arg0, typename... Args>
inline void send_tpl_impl(channel* whom, Arg0&& arg0, Args&&... args) {
if (whom) {
self->send_message(whom, make_any_tuple(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
}
}
} // namespace detail
template<class C>
typename std::enable_if<
std::is_base_of<channel, C>::value,
intrusive_ptr<C>&
>::type
operator<<(intrusive_ptr<C>& whom, any_tuple&& what)
{
if (whom) whom->enqueue(self, std::move(what));
inline typename std::enable_if<std::is_base_of<channel, C>::value,
const intrusive_ptr<C>& >::type
operator<<(const intrusive_ptr<C>& whom, any_tuple what) {
detail::send_impl(whom.get(), std::move(what));
return whom;
}
template<class C>
typename std::enable_if<
std::is_base_of<channel, C>::value,
intrusive_ptr<C>
>::type
operator<<(intrusive_ptr<C>&& whom, any_tuple&& what)
{
intrusive_ptr<C> tmp(std::move(whom));
if (tmp) tmp->enqueue(self, std::move(what));
return std::move(tmp);
inline const self_type& operator<<(const self_type& s, any_tuple what) {
detail::send_impl(s.get(), std::move(what));
return s;
}
const self_type& operator<<(const self_type& s, const any_tuple& what);
template<class C, typename Arg0, typename... Args>
inline typename std::enable_if<std::is_base_of<channel, C>::value>::type
send(const intrusive_ptr<C>& whom, Arg0&& arg0, Args&&... args) {
detail::send_tpl_impl(whom.get(),
std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
}
const self_type& operator<<(const self_type& s, any_tuple&& what);
// matches "send(this, ...)" and "send(self, ...)"
template<typename Arg0, typename... Args>
inline void send(local_actor* whom, Arg0&& arg0, Args&&... args) {
detail::send_tpl_impl(whom,
std::forward<Arg0>(arg0),
std::forward<Args>(args)...);
}
#endif // CPPA_DOCUMENTATION
/**
* @ingroup MessageHandling
* @brief Sends a message to the sender of the last received message.
* @param what Message elements.
*/
template<typename Arg0, typename... Args>
void reply(const Arg0& arg0, const Args&... args)
{
send(self->last_sender(), arg0, args...);
template<typename... Args>
inline void reply(Args&&... what) {
send(self->last_sender(), std::forward<Args>(what)...);
}
/**
* @ingroup MessageHandling
* @brief Sends a message to @p whom that is delayed by @p rel_time.
* @param whom Receiver of the message.
* @param rel_time Relative time duration to delay the message.
* @param data Any number of values for the message content.
* @param rel_time Relative time duration to delay the message in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
*/
template<typename Duration, typename... Data>
void future_send(actor_ptr whom, const Duration& rel_time, const Data&... data)
{
get_scheduler()->future_send(whom, rel_time, data...);
template<class Rep, class Period, typename... Args>
inline void delayed_send(const actor_ptr& whom,
const std::chrono::duration<Rep, Period>& rel_time,
Args&&... what) {
if (whom) {
get_scheduler()->delayed_send(whom, rel_time,
std::forward<Args>(what)...);
}
}
/**
* @ingroup MessageHandling
* @brief Sends a reply message that is delayed by @p rel_time.
* @see future_send()
* @param rel_time Relative time duration to delay the message in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
* @see delayed_send()
*/
template<typename Duration, typename... Data>
void delayed_reply(const Duration& rel_time, Data const... data)
{
future_send(self->last_sender(), rel_time, data...);
template<class Rep, class Period, typename... Args>
inline void delayed_reply(const std::chrono::duration<Rep, Period>& rel_time,
Args&&... what) {
delayed_send(self->last_sender(), rel_time, std::forward<Args>(what)...);
}
/**
* @brief Blocks execution of this actor until all
* other actors finished execution.
* @warning This function will cause a deadlock if
* called from multiple actors.
* @warning This function will cause a deadlock if called from multiple actors.
* @warning Do not call this function in cooperatively scheduled actors.
*/
inline void await_all_others_done()
{
inline void await_all_others_done() {
detail::actor_count_wait_until((self.unchecked() == nullptr) ? 0 : 1);
}
/**
* @brief Publishes @p whom at given @p port.
* @brief Publishes @p whom at @p port.
*
* The connection is automatically closed if the lifetime of @p whom ends.
* @param whom Actor that should be published at given @p port.
* @param whom Actor that should be published at @p port.
* @param port Unused TCP port.
* @throws bind_failure
*/
void publish(actor_ptr& whom, std::uint16_t port);
/**
* @copydoc publish(actor_ptr&,std::uint16_t)
*/
void publish(actor_ptr&& whom, std::uint16_t port);
void publish(actor_ptr whom, std::uint16_t port);
/**
* @brief Establish a new connection to the actor at @p host on given @p port.
* @param host Valid hostname or IP address.
* @param port TCP port.
* @returns A pointer to the proxy instance that represents the remote Actor.
* @returns An {@link actor_ptr} to the proxy instance
* representing a remote actor.
*/
actor_ptr remote_actor(char const* host, std::uint16_t port);
actor_ptr remote_actor(const char* host, std::uint16_t port);
} // namespace cppa
......
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