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
e8f7d3f1
Commit
e8f7d3f1
authored
Jun 29, 2012
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixed wrong commit
parent
777fc9bf
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
256 additions
and
284 deletions
+256
-284
cppa/cppa.hpp
cppa/cppa.hpp
+256
-284
No files found.
cppa/cppa.hpp
View file @
e8f7d3f1
...
...
@@ -32,27 +32,24 @@
#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/cow_tuple.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/fsm_actor.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/scheduled_actor.hpp"
#include "cppa/scheduling_hint.hpp"
#include "cppa/event_based_actor.hpp"
...
...
@@ -72,45 +69,41 @@
*
* 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.
* of both concurrent and distributed software
using C++
.
*
* @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 and
* Writing applications in @p libcppa requires a minimum of gluecode.
* 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
* converted to an actor if needed.
* 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.
*
* @section GettingStarted Getting Started
*
* 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.
* To build @p libcppa, you need <tt>GCC >= 4.
6</tt>, @p Automake
* and the <tt>Boost.Thread</tt> library.
*
* The usual build steps on Linux and Mac OS X are:
*
*- <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.
* - <tt>autoreconf -i</tt>
* - <tt>./configure</tt>
* - <tt>make</tt>
* - <tt>make install</tt> (as root, optionally)
*
*- <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.
* 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.
*
* 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
...
...
@@ -124,32 +117,24 @@
* features.
*
* @namespace cppa
* @brief Root namespace of libcppa.
* @brief This is the root namespace of libcppa.
*
* Thie @b cppa namespace contains all functions and classes to
* implement Actor based applications.
*
* @namespace cppa::util
* @brief
C
ontains utility classes and metaprogramming
* @brief
This namespace c
ontains utility classes and metaprogramming
* utilities used by the libcppa implementation.
*
* @namespace cppa::intrusive
* @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.
* @brief This namespace contains intrusive container implementations.
*
* @defgroup CopyOnWrite Copy-on-write optimization.
* @p libcppa uses a copy-on-write optimization for its message
* passing implementation.
*
* {@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
* {@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
* tuple @p x and @p y, whereas @p y is a copy of @p x:
*
* @code
...
...
@@ -254,13 +239,16 @@
* 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>()>() >> [](int i0, int i1) {
* on(atom("compute"), val<int>(), val<int>(), val<int>()>() >> [](int i0, int i1, int i2)
* {
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1);
* reply(atom("result"), i0 + i1
+ i2
);
* }
* );
* @endcode
...
...
@@ -275,12 +263,16 @@
*
* 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);
* }
* );
...
...
@@ -308,8 +300,10 @@
* @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);
* }
* );
...
...
@@ -321,7 +315,8 @@
* @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
...
...
@@ -333,8 +328,10 @@
* @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);
* }
* )
...
...
@@ -344,18 +341,20 @@
*
* @section FutureSend Send delayed messages
*
* The function @p
delayed
_send provides a simple way to delay a message.
* The function @p
future
_send provides a simple way to delay a message.
* This is particularly useful for recurring events, e.g., periodical polling.
* Usage example:
*
* @code
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
* receive_loop (
* future_send(self, std::chrono::seconds(1), atom("poll"));
* receive_loop
* (
* // ...
* on<atom("poll")>() >> []() {
* on<atom("poll")>() >> []()
* {
* // ... poll something ...
* // and do it again after 1sec
*
delayed
_send(self, std::chrono::seconds(1), atom("poll"));
*
future
_send(self, std::chrono::seconds(1), atom("poll"));
* }
* );
* @endcode
...
...
@@ -366,7 +365,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>c
onst char
*</tt>,
* Unfortunately, string literals in @p C++ have the type <tt>c
har const
*</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.
...
...
@@ -376,7 +375,7 @@
* // sends an std::string containing "hello actor!" to itself
* send(self, "hello actor!");
*
* c
onst char
* cstring = "cstring";
* c
har const
* cstring = "cstring";
* // sends an std::string containing "cstring" to itself
* send(self, cstring);
*
...
...
@@ -386,13 +385,14 @@
* // 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 Actor
Creation Actor creation
.
* @defgroup Actor
Management Actor management
.
*
*/
...
...
@@ -410,7 +410,7 @@
*/
/**
* @brief A simple example for a
delayed
_send based application.
* @brief A simple example for a
future
_send based application.
* @example dancing_kirby.cpp
*/
...
...
@@ -421,323 +421,295 @@
namespace
cppa
{
#ifdef CPPA_DOCUMENTATION
/**
* @ingroup MessageHandling
* @{
* @ingroup ActorManagement
* @brief Links @p lhs and @p rhs;
* @pre <tt>lhs != rhs</tt>
*/
void
link
(
actor_ptr
&
lhs
,
actor_ptr
&
rhs
);
/**
* @brief Sends <tt>{what...}</tt> as a message to @p whom.
* @param whom Receiver of the message.
* @param what Message elements.
* @copydoc link(actor_ptr&,actor_ptr&)
*/
template
<
typename
...
Args
>
void
send
(
const
channel_ptr
&
whom
,
Args
&&
...
what
);
void
link
(
actor_ptr
&&
lhs
,
actor_ptr
&
rhs
);
/**
* @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.
* @copydoc link(actor_ptr&,actor_ptr&)
*/
const
channel_ptr
&
operator
<<
(
const
channel_ptr
&
whom
,
any_tuple
what
);
/** @} */
void
link
(
actor_ptr
&&
lhs
,
actor_ptr
&&
rhs
);
/**
* @ingroup ActorCreation
* @{
* @copydoc link(actor_ptr&,actor_ptr&)
*/
void
link
(
actor_ptr
&
lhs
,
actor_ptr
&&
rhs
);
/**
* @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}.
* @ingroup ActorManagement
* @brief Unlinks @p lhs from @p rhs;
* @pre <tt>lhs != rhs</tt>
*/
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn
(
Fun
fun
,
Args
&&
...
args
);
void
unlink
(
actor_ptr
&
lhs
,
actor_ptr
&
rhs
);
/**
* @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>.
* @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.
*/
template
<
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn
(
Fun
fun
,
Args
&&
...
args
);
void
monitor
(
actor_ptr
&
whom
);
void
monitor
(
actor_ptr
&&
whom
);
/**
* @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.
* @ingroup ActorManagement
* @brief Removes a monitor from @p whom.
*/
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
void
demonitor
(
actor_ptr
&
whom
);
/**
* @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>.
* @ingroup ActorManagement
* @brief Spans a new context-switching actor.
* @returns A pointer to the spawned {@link actor Actor}.
*/
template
<
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
inline
actor_ptr
spawn
(
scheduled_actor
*
what
)
{
return
get_scheduler
()
->
spawn
(
what
,
scheduled
);
}
/**
* @
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 A
n {@link actor_ptr} to the spawned {@link a
ctor}.
* @
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 A
ctor}.
*/
template
<
class
ActorImpl
,
typename
...
Args
>
actor_ptr
spawn
(
const
group_ptr
&
grp
,
Args
&&
...
args
);
template
<
scheduling_hint
Hint
>
inline
actor_ptr
spawn
(
scheduled_actor
*
what
)
{
return
get_scheduler
()
->
spawn
(
what
,
Hint
);
}
/**
* @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.
* @ingroup ActorManagement
* @brief Spans a new event-based actor.
* @returns A pointer to the spawned {@link actor Actor}.
*/
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
);
inline
actor_ptr
spawn
(
abstract_event_based_actor
*
what
)
{
return
get_scheduler
()
->
spawn
(
what
);
}
template
<
scheduling_hint
Hint
>
inline
actor_ptr
spawn
(
void_function
fun
)
{
return
get_scheduler
()
->
spawn
(
std
::
move
(
fun
),
Hint
);
/**
* @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}.
*/
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
);
}
// 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 ActorManagement
* @brief Alias for <tt>spawn<scheduled>(what, args...)</tt>.
*/
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
<
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
)...);
}
#ifdef CPPA_DOCUMENTATION
template
<
class
ActorImpl
,
typename
...
Args
>
inline
actor_ptr
spawn
(
Args
&&
...
args
)
{
return
get_scheduler
()
->
spawn
(
new
ActorImpl
(
std
::
forward
<
Args
>
(
args
)...));
}
/**
* @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
);
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
);
});
}
/**
* @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
);
inline
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
void_function
fun
)
{
return
spawn_in_group
<
scheduled
>
(
grp
,
std
::
move
(
fun
));
}
#else
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
<
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
<
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
)...);
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
...));
}
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
);
});
// 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
...));
}
namespace
detail
{
inline
void
send_impl
(
channel
*
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
self
->
send_message
(
whom
,
std
::
move
(
what
));
}
// matches send(self, ...);
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
)...));
}
inline
void
send
(
const
self_type
&
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
send
(
static_cast
<
local_actor
*>
(
self
),
arg0
,
args
...);
}
}
// namespace detail
template
<
class
C
>
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
));
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
;
}
inline
const
self_type
&
operator
<<
(
const
self_type
&
s
,
any_tuple
what
)
{
detail
::
send_impl
(
s
.
get
(),
std
::
move
(
what
));
return
s
;
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
<
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
)...);
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
));
return
whom
;
}
// 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
)...);
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
);
}
const
self_type
&
operator
<<
(
const
self_type
&
s
,
const
any_tuple
&
what
);
const
self_type
&
operator
<<
(
const
self_type
&
s
,
any_tuple
&&
what
);
#endif // CPPA_DOCUMENTATION
/**
* @ingroup MessageHandling
* @brief Sends a message to the sender of the last received message.
* @param what Message elements.
*/
template
<
typename
...
Args
>
inline
void
reply
(
Args
&&
...
what
)
{
send
(
self
->
last_sender
(),
std
::
forward
<
Args
>
(
what
)...);
template
<
typename
Arg0
,
typename
...
Args
>
void
reply
(
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
send
(
self
->
last_sender
(),
arg0
,
args
...);
}
/**
* @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 in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
* @param rel_time Relative time duration to delay the message.
* @param data Any number of values for the message content.
*/
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
)...);
}
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
...);
}
/**
* @ingroup MessageHandling
* @brief Sends a reply message that is delayed by @p rel_time.
* @param rel_time Relative time duration to delay the message in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
* @see delayed_send()
* @see future_send()
*/
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
)
...);
template
<
typename
Duration
,
typename
...
Data
>
void
delayed_reply
(
const
Duration
&
rel_time
,
Data
const
...
data
)
{
future_send
(
self
->
last_sender
(),
rel_time
,
data
...);
}
/**
* @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 Do not call this function in cooperatively scheduled
actors.
* @warning This function will cause a deadlock if
*
called from multiple
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 @p port.
* @brief Publishes @p whom at
given
@p port.
*
* The connection is automatically closed if the lifetime of @p whom ends.
* @param whom Actor that should be published at @p port.
* @param whom Actor that should be published at
given
@p port.
* @param port Unused TCP port.
* @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.
* @param host Valid hostname or IP address.
* @param port TCP port.
* @returns An {@link actor_ptr} to the proxy instance
* representing a remote actor.
* @returns A pointer to the proxy instance that represents the remote Actor.
*/
actor_ptr
remote_actor
(
c
onst
char
*
host
,
std
::
uint16_t
port
);
actor_ptr
remote_actor
(
c
har
const
*
host
,
std
::
uint16_t
port
);
}
// 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