Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
777fc9bf
Commit
777fc9bf
authored
Jun 28, 2012
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
documentation
parent
4c39c810
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
284 additions
and
256 deletions
+284
-256
cppa/cppa.hpp
cppa/cppa.hpp
+284
-256
No files found.
cppa/cppa.hpp
View file @
777fc9bf
...
@@ -32,24 +32,27 @@
...
@@ -32,24 +32,27 @@
#define CPPA_HPP
#define CPPA_HPP
#include <tuple>
#include <tuple>
#include <chrono>
#include <cstdint>
#include <cstdint>
#include <functional>
#include <type_traits>
#include <type_traits>
#include "cppa/on.hpp"
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/atom.hpp"
#include "cppa/self.hpp"
#include "cppa/self.hpp"
#include "cppa/cow_tuple.hpp"
#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/factory.hpp"
#include "cppa/behavior.hpp"
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp"
#include "cppa/announce.hpp"
#include "cppa/sb_actor.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/fsm_actor.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/local_actor.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"
...
@@ -69,41 +72,45 @@
...
@@ -69,41 +72,45 @@
*
*
* This library provides an implementation of the actor model for C++.
* This library provides an implementation of the actor model for C++.
* It uses a network transparent messaging system to ease development
* 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.
* @p libcppa uses a thread pool to schedule actors by default.
* A scheduled actor should not call blocking functions.
* A scheduled actor should not call blocking functions.
* Individual actors can be spawned (created) with a special flag to run in
* 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.
* an own thread if one needs to make use of blocking APIs.
*
*
* Writing applications in @p libcppa requires a minimum of gluecode.
* Writing applications in @p libcppa requires a minimum of gluecode and
* You don't have to derive a particular class to implement an actor and
* each context <i>is</i> an actor. Even main is implicitly
* each context <i>is</i> an actor. Even main is implicitly
* converted to an actor if needed, as the following example shows:
* converted to an actor if needed.
*
* It's recommended to read at least the
* {@link MessageHandling message handling}
* section of this documentation.
*
*
* @section GettingStarted Getting Started
* @section GettingStarted Getting Started
*
*
* To build @p libcppa, you need <tt>GCC >= 4.
6</tt>, @p Automake
* To build @p libcppa, you need <tt>GCC >= 4.
7</tt> or <tt>Clang >= 3.2</tt>,
* and the <tt>Boost.Thread</tt> library.
*
@p CMake
and the <tt>Boost.Thread</tt> library.
*
*
* The usual build steps on Linux and Mac OS X are:
* The usual build steps on Linux and Mac OS X are:
*
*
* - <tt>autoreconf -i</tt>
*- <tt>mkdir build</tt>
* - <tt>./configure</tt>
*- <tt>cd build</tt>
* - <tt>make</tt>
*- <tt>cmake ..</tt>
* - <tt>make install</tt> (as root, optionally)
*- <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
*- <tt>./bin/unit_tests</tt>
* the correct @p GCC binary or doesn't find your <tt>Boost.Thread</tt>
*
* installation.
* 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
* Windows is not supported yet, because MVSC++ doesn't implement the
* C++11 features needed to compile @p libcppa.
* 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
* @section IntroHelloWorld Hello World Example
*
*
* @include hello_world_example.cpp
* @include hello_world_example.cpp
...
@@ -117,24 +124,32 @@
...
@@ -117,24 +124,32 @@
* features.
* features.
*
*
* @namespace cppa
* @namespace cppa
* @brief This is the root namespace of libcppa.
* @brief Root namespace of libcppa.
*
* Thie @b cppa namespace contains all functions and classes to
* implement Actor based applications.
*
*
* @namespace cppa::util
* @namespace cppa::util
* @brief
This namespace c
ontains utility classes and metaprogramming
* @brief
C
ontains utility classes and metaprogramming
* utilities used by the libcppa implementation.
* utilities used by the libcppa implementation.
*
*
* @namespace cppa::intrusive
* @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.
* @defgroup CopyOnWrite Copy-on-write optimization.
* @p libcppa uses a copy-on-write optimization for its message
* @p libcppa uses a copy-on-write optimization for its message
* passing implementation.
* passing implementation.
*
*
* {@link cppa::tuple Tuples} should @b always be used with by-value semantic,
* {@link cppa::cow_tuple Tuples} should @b always be used with by-value
* since tuples use a copy-on-write smart pointer internally. Let's assume two
* 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:
* tuple @p x and @p y, whereas @p y is a copy of @p x:
*
*
* @code
* @code
...
@@ -239,16 +254,13 @@
...
@@ -239,16 +254,13 @@
* to define patterns:
* to define patterns:
*
*
* @code
* @code
* receive
* receive (
* (
* on(atom("hello"), val<std::string>()) >> [](const std::string& msg) {
* on(atom("hello"), val<std::string>()) >> [](const std::string& msg)
* {
* cout << "received hello message: " << msg << endl;
* 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
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1
+ i2
);
* reply(atom("result"), i0 + i1);
* }
* }
* );
* );
* @endcode
* @endcode
...
@@ -263,16 +275,12 @@
...
@@ -263,16 +275,12 @@
*
*
* Example actor:
* Example actor:
* @code
* @code
* void math_actor()
* void math_actor() {
* {
* receive_loop (
* receive_loop
* on<atom("plus"), int, int>() >> [](int a, int b) {
* (
* on<atom("plus"), int, int>() >> [](int a, int b)
* {
* reply(atom("result"), a + 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);
* reply(atom("result"), a - b);
* }
* }
* );
* );
...
@@ -300,10 +308,8 @@
...
@@ -300,10 +308,8 @@
* @code
* @code
* // receive two integers
* // receive two integers
* vector<int> received_values;
* vector<int> received_values;
* receive_while([&]() { return received_values.size() < 2; })
* receive_while([&]() { return received_values.size() < 2; }) (
* (
* on<int>() >> [](int value) {
* on<int>() >> [](int value)
* {
* received_values.push_back(value);
* received_values.push_back(value);
* }
* }
* );
* );
...
@@ -315,8 +321,7 @@
...
@@ -315,8 +321,7 @@
* @code
* @code
* std::vector<int> vec {1, 2, 3, 4};
* std::vector<int> vec {1, 2, 3, 4};
* auto i = vec.begin();
* auto i = vec.begin();
* receive_for(i, vec.end())
* receive_for(i, vec.end()) (
* (
* on(atom("get")) >> [&]() { reply(atom("result"), *i); }
* on(atom("get")) >> [&]() { reply(atom("result"), *i); }
* );
* );
* @endcode
* @endcode
...
@@ -328,10 +333,8 @@
...
@@ -328,10 +333,8 @@
* @code
* @code
* // receive ints until zero was received
* // receive ints until zero was received
* vector<int> received_values;
* vector<int> received_values;
* do_receive
* do_receive (
* (
* on<int>() >> [](int value) {
* on<int>() >> [](int value)
* {
* received_values.push_back(value);
* received_values.push_back(value);
* }
* }
* )
* )
...
@@ -341,20 +344,18 @@
...
@@ -341,20 +344,18 @@
*
*
* @section FutureSend Send delayed messages
* @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.
* This is particularly useful for recurring events, e.g., periodical polling.
* Usage example:
* Usage example:
*
*
* @code
* @code
* future_send(self, std::chrono::seconds(1), atom("poll"));
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
* receive_loop
* receive_loop (
* (
* // ...
* // ...
* on<atom("poll")>() >> []()
* on<atom("poll")>() >> []() {
* {
* // ... poll something ...
* // ... poll something ...
* // and do it again after 1sec
* // 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
* @endcode
...
@@ -365,7 +366,7 @@
...
@@ -365,7 +366,7 @@
*
*
* The message passing of @p libcppa prohibits pointers in messages because
* The message passing of @p libcppa prohibits pointers in messages because
* it enforces network transparent messaging.
* it enforces network transparent messaging.
* Unfortunately, string literals in @p C++ have the type <tt>c
har const
*</tt>,
* Unfortunately, string literals in @p C++ have the type <tt>c
onst char
*</tt>,
* resp. <tt>const char[]</tt>. Since @p libcppa is a user-friendly library,
* 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 silently converts string literals and C-strings to @p std::string objects.
* It also converts unicode literals to the corresponding STL container.
* It also converts unicode literals to the corresponding STL container.
...
@@ -375,7 +376,7 @@
...
@@ -375,7 +376,7 @@
* // sends an std::string containing "hello actor!" to itself
* // sends an std::string containing "hello actor!" to itself
* send(self, "hello actor!");
* send(self, "hello actor!");
*
*
* c
har const
* cstring = "cstring";
* c
onst char
* cstring = "cstring";
* // sends an std::string containing "cstring" to itself
* // sends an std::string containing "cstring" to itself
* send(self, cstring);
* send(self, cstring);
*
*
...
@@ -385,14 +386,13 @@
...
@@ -385,14 +386,13 @@
* // x has the type cppa::tuple<std::string, std::string>
* // x has the type cppa::tuple<std::string, std::string>
* auto x = make_cow_tuple("hello", "tuple");
* auto x = make_cow_tuple("hello", "tuple");
*
*
* receive
* receive (
* (
* // equal to: on(std::string("hello actor!"))
* // equal to: on(std::string("hello actor!"))
* on("hello actor!") >> []() { }
* on("hello actor!") >> []() { }
* );
* );
* @endcode
* @endcode
*
*
* @defgroup Actor
Management Actor management
.
* @defgroup Actor
Creation Actor creation
.
*
*
*/
*/
...
@@ -410,7 +410,7 @@
...
@@ -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
* @example dancing_kirby.cpp
*/
*/
...
@@ -421,295 +421,323 @@
...
@@ -421,295 +421,323 @@
namespace
cppa
{
namespace
cppa
{
/**
#ifdef CPPA_DOCUMENTATION
* @ingroup ActorManagement
* @brief Links @p lhs and @p rhs;
* @pre <tt>lhs != rhs</tt>
*/
void
link
(
actor_ptr
&
lhs
,
actor_ptr
&
rhs
);
/**
/**
* @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
* @ingroup ActorCreation
* @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.
*/
*/
void
monitor
(
actor_ptr
&
whom
);
void
monitor
(
actor_ptr
&&
whom
);
/**
/**
* @ingroup ActorManagement
* @brief Spawns a new context-switching or thread-mapped {@link actor}
* @brief Removes a monitor from @p whom.
* 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 Spawns a new context-switching {@link actor}
* @brief Spans a new context-switching actor.
* that executes <tt>fun(args...)</tt>.
* @returns A pointer to the spawned {@link actor Actor}.
* @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
)
template
<
typename
Fun
,
typename
...
Args
>
{
actor_ptr
spawn
(
Fun
fun
,
Args
&&
...
args
);
return
get_scheduler
()
->
spawn
(
what
,
scheduled
);
}
/**
/**
* @ingroup ActorManagement
* @brief Spawns a new context-switching or thread-mapped {@link actor}
* @brief Spans a new context-switching actor.
* that executes <tt>fun(args...)</tt> and
* @tparam Hint Hint to the scheduler for the best scheduling strategy.
* joins @p grp immediately.
* @returns A pointer to the spawned {@link actor Actor}.
* @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
>
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
inline
actor_ptr
spawn
(
scheduled_actor
*
what
)
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
{
return
get_scheduler
()
->
spawn
(
what
,
Hint
);
}
/**
/**
* @ingroup ActorManagement
* @brief Spawns a new context-switching {@link actor}
* @brief Spans a new event-based actor.
* that executes <tt>fun(args...)</tt> and
* @returns A pointer to the spawned {@link actor Actor}.
* 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
)
template
<
typename
Fun
,
typename
...
Args
>
{
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
return
get_scheduler
()
->
spawn
(
what
);
}
/**
/**
* @ingroup ActorManagement
* @brief Spawns an actor of type @p ActorImpl.
* @brief Spawns a new actor that executes @p what with given arguments.
* @param args Optional constructor arguments.
* @tparam Hint Hint to the scheduler for the best scheduling strategy.
* @tparam ActorImpl Subtype of {@link event_based_actor} or {@link sb_actor}.
* @param what Function or functor that the spawned Actor should execute.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @param args Arguments needed to invoke @p what.
* @returns A pointer to the spawned {@link actor actor}.
*/
*/
template
<
scheduling_hint
Hint
,
typename
F
,
typename
...
Args
>
template
<
class
ActorImpl
,
typename
...
Args
>
auto
//actor_ptr
actor_ptr
spawn
(
const
group_ptr
&
grp
,
Args
&&
...
args
);
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
);
}
/**
/**
* @ingroup ActorManagement
* @brief Spawns an actor of type @p ActorImpl that joins @p grp immediately.
* @brief Alias for <tt>spawn<scheduled>(what, args...)</tt>.
* @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
>
template
<
class
ActorImpl
,
typename
...
Args
>
a
uto
// actor_ptr
a
ctor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
Args
&&
...
args
);
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
,
#else
actor_ptr
>::
type
{
inline
actor_ptr
spawn
(
void_function
fun
)
{
return
spawn
<
scheduled
>
(
std
::
forward
<
F
>
(
what
),
args
...
);
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
);
}
/**
// forwards self_type as actor_ptr
* @ingroup MessageHandling
template
<
typename
T
>
* @brief Sends <tt>{arg0, args...}</tt> as a message to @p whom.
struct
spawn_fwd_
{
*/
static
inline
T
&&
_
(
T
&&
arg
)
{
return
std
::
move
(
arg
);
}
template
<
typename
Arg0
,
typename
...
Args
>
static
inline
T
&
_
(
T
&
arg
)
{
return
arg
;
}
void
send
(
channel_ptr
&
whom
,
const
Arg0
&
arg0
,
const
Args
&
...
args
);
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
);
}
/**
template
<
typename
Fun
,
typename
Arg0
,
typename
...
Args
>
* @ingroup MessageHandling
inline
actor_ptr
spawn
(
Fun
&&
fun
,
Arg0
&&
arg0
,
Args
&&
...
args
)
{
* @brief Send a message to @p whom.
return
spawn
<
scheduled
>
(
std
::
forward
<
Fun
>
(
fun
),
*
std
::
forward
<
Arg0
>
(
arg0
),
* <b>Usage example:</b>
std
::
forward
<
Args
>
(
args
)...);
* @code
}
* self << make_cow_tuple(1, 2, 3);
* @endcode
* @returns @p whom.
*/
channel_ptr
&
operator
<<
(
channel_ptr
&
whom
,
const
any_tuple
&
what
);
#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
>
template
<
scheduling_hint
Hint
>
void
send
(
intrusive_ptr
<
C
>&
whom
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
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
)
{
static_assert
(
std
::
is_base_of
<
channel
,
C
>::
value
,
"C is not a channel"
);
ptr
->
join
(
grp
);
if
(
whom
)
whom
->
enqueue
(
self
,
make_cow_tuple
(
arg0
,
args
...)
);
}
);
}
}
template
<
class
C
,
typename
Arg0
,
typename
...
Args
>
inline
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
void_function
fun
)
{
void
send
(
intrusive_ptr
<
C
>&&
whom
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
return
spawn_in_group
<
scheduled
>
(
grp
,
std
::
move
(
fun
));
{
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
...));
}
}
// matches "send(this, ...)" in event-based actors
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
Arg0
,
typename
...
Args
>
template
<
typename
Arg0
,
typename
...
Args
>
inline
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
void
send
(
local_actor
*
whom
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
Fun
fun
,
Arg0
&&
arg0
,
Args
&&
...
args
)
{
{
return
spawn_in_group
<
Hint
>
(
whom
->
enqueue
(
whom
,
make_cow_tuple
(
arg0
,
args
...));
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
<
class
ActorImpl
,
typename
...
Args
>
template
<
typename
Arg0
,
typename
...
Args
>
inline
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
Args
&&
...
args
)
{
inline
void
send
(
const
self_type
&
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
return
get_scheduler
()
->
spawn
(
new
ActorImpl
(
std
::
forward
<
Args
>
(
args
)...),
{
[
&
grp
](
local_actor
*
ptr
)
{
ptr
->
join
(
grp
);
});
send
(
static_cast
<
local_actor
*>
(
self
),
arg0
,
args
...);
}
}
template
<
class
C
>
namespace
detail
{
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
inline
void
send_impl
(
channel
*
whom
,
any_tuple
&&
what
)
{
intrusive_ptr
<
C
>&
if
(
whom
)
self
->
send_message
(
whom
,
std
::
move
(
what
));
>::
type
operator
<<
(
intrusive_ptr
<
C
>&
whom
,
const
any_tuple
&
what
)
{
if
(
whom
)
whom
->
enqueue
(
self
,
what
);
return
whom
;
}
}
template
<
class
C
>
template
<
typename
Arg0
,
typename
...
Args
>
typename
std
::
enable_if
<
inline
void
send_tpl_impl
(
channel
*
whom
,
Arg0
&&
arg0
,
Args
&&
...
args
)
{
std
::
is_base_of
<
channel
,
C
>::
value
,
if
(
whom
)
{
intrusive_ptr
<
C
>
self
->
send_message
(
whom
,
make_any_tuple
(
std
::
forward
<
Arg0
>
(
arg0
),
>::
type
std
::
forward
<
Args
>
(
args
)...));
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
);
}
}
}
// namespace detail
template
<
class
C
>
template
<
class
C
>
typename
std
::
enable_if
<
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
std
::
is_base_of
<
channel
,
C
>::
value
,
const
intrusive_ptr
<
C
>&
>::
type
intrusive_ptr
<
C
>&
operator
<<
(
const
intrusive_ptr
<
C
>&
whom
,
any_tuple
what
)
{
>::
type
detail
::
send_impl
(
whom
.
get
(),
std
::
move
(
what
));
operator
<<
(
intrusive_ptr
<
C
>&
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
whom
->
enqueue
(
self
,
std
::
move
(
what
));
return
whom
;
return
whom
;
}
}
template
<
class
C
>
inline
const
self_type
&
operator
<<
(
const
self_type
&
s
,
any_tuple
what
)
{
typename
std
::
enable_if
<
detail
::
send_impl
(
s
.
get
(),
std
::
move
(
what
));
std
::
is_base_of
<
channel
,
C
>::
value
,
return
s
;
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
);
}
}
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
#endif // CPPA_DOCUMENTATION
/**
/**
* @ingroup MessageHandling
* @ingroup MessageHandling
* @brief Sends a message to the sender of the last received message.
* @brief Sends a message to the sender of the last received message.
* @param what Message elements.
*/
*/
template
<
typename
Arg0
,
typename
...
Args
>
template
<
typename
...
Args
>
void
reply
(
const
Arg0
&
arg0
,
const
Args
&
...
args
)
inline
void
reply
(
Args
&&
...
what
)
{
{
send
(
self
->
last_sender
(),
std
::
forward
<
Args
>
(
what
)...);
send
(
self
->
last_sender
(),
arg0
,
args
...);
}
}
/**
/**
* @ingroup MessageHandling
* @ingroup MessageHandling
* @brief Sends a message to @p whom that is delayed by @p rel_time.
* @brief Sends a message to @p whom that is delayed by @p rel_time.
* @param whom Receiver of the message.
* @param whom Receiver of the message.
* @param rel_time Relative time duration to delay the message.
* @param rel_time Relative time duration to delay the message in
* @param data Any number of values for the message content.
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
*/
*/
template
<
typename
Duration
,
typename
...
Data
>
template
<
class
Rep
,
class
Period
,
typename
...
Args
>
void
future_send
(
actor_ptr
whom
,
const
Duration
&
rel_time
,
const
Data
&
...
data
)
inline
void
delayed_send
(
const
actor_ptr
&
whom
,
{
const
std
::
chrono
::
duration
<
Rep
,
Period
>&
rel_time
,
get_scheduler
()
->
future_send
(
whom
,
rel_time
,
data
...);
Args
&&
...
what
)
{
if
(
whom
)
{
get_scheduler
()
->
delayed_send
(
whom
,
rel_time
,
std
::
forward
<
Args
>
(
what
)...);
}
}
}
/**
/**
* @ingroup MessageHandling
* @ingroup MessageHandling
* @brief Sends a reply message that is delayed by @p rel_time.
* @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
>
template
<
class
Rep
,
class
Period
,
typename
...
Args
>
void
delayed_reply
(
const
Duration
&
rel_time
,
Data
const
...
data
)
inline
void
delayed_reply
(
const
std
::
chrono
::
duration
<
Rep
,
Period
>&
rel_time
,
{
Args
&&
...
what
)
{
future_send
(
self
->
last_sender
(),
rel_time
,
data
...);
delayed_send
(
self
->
last_sender
(),
rel_time
,
std
::
forward
<
Args
>
(
what
)
...);
}
}
/**
/**
* @brief Blocks execution of this actor until all
* @brief Blocks execution of this actor until all
* other actors finished execution.
* other actors finished execution.
* @warning This function will cause a deadlock if
* @warning This function will cause a deadlock if
called from multiple actors.
*
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
);
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.
* 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.
* @param port Unused TCP port.
* @throws bind_failure
* @throws bind_failure
*/
*/
void
publish
(
actor_ptr
&
whom
,
std
::
uint16_t
port
);
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
);
/**
/**
* @brief Establish a new connection to the actor at @p host on given @p port.
* @brief Establish a new connection to the actor at @p host on given @p port.
* @param host Valid hostname or IP address.
* @param host Valid hostname or IP address.
* @param port TCP port.
* @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
(
c
har
const
*
host
,
std
::
uint16_t
port
);
actor_ptr
remote_actor
(
c
onst
char
*
host
,
std
::
uint16_t
port
);
}
// namespace cppa
}
// namespace cppa
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment