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
0f8c067e
Commit
0f8c067e
authored
Jun 29, 2012
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
maintenance & documentation
parent
b0fb47b1
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
217 additions
and
254 deletions
+217
-254
cppa/cppa.hpp
cppa/cppa.hpp
+132
-223
cppa/scheduler.hpp
cppa/scheduler.hpp
+75
-21
cppa/self.hpp
cppa/self.hpp
+2
-1
src/local_actor.cpp
src/local_actor.cpp
+6
-7
src/scheduler.cpp
src/scheduler.cpp
+2
-2
No files found.
cppa/cppa.hpp
View file @
0f8c067e
...
@@ -193,8 +193,8 @@
...
@@ -193,8 +193,8 @@
* The first argument is the receiver of the message followed by any number
* The first argument is the receiver of the message followed by any number
* of values. @p send creates a tuple from the given values and enqueues the
* of values. @p send creates a tuple from the given values and enqueues the
* tuple to the receivers mailbox. Thus, send should @b not be used to send
* tuple to the receivers mailbox. Thus, send should @b not be used to send
* a message to multiple receivers. You should use
the @p enqueue
* a message to multiple receivers. You should use
@p operator<<
*
member function of the receivers
instead as in the following example:
* instead as in the following example:
*
*
* @code
* @code
* // spawn some actors
* // spawn some actors
...
@@ -207,20 +207,20 @@
...
@@ -207,20 +207,20 @@
*
*
* // send a message to a1, a2 and a3
* // send a message to a1, a2 and a3
* auto msg = make_cow_tuple(atom("compute"), 1, 2, 3);
* auto msg = make_cow_tuple(atom("compute"), 1, 2, 3);
*
auto s = self; // cache self pointer
*
* // note: this is more efficient then using send() three times because
* // note: this is more efficient then using send() three times because
* // send() would create a new tuple each time;
* // send() would create a new tuple each time;
* // this safes both time and memory thanks to libcppa's copy-on-write
* // this safes both time and memory thanks to libcppa's copy-on-write
* a1
->enqueue(s, msg)
;
* a1
<< msg
;
* a2
->enqueue(s, msg)
;
* a2
<< msg
;
* a3
->enqueue(s, msg)
;
* a3
<< msg
;
*
*
* // modify msg and send it again
* // modify msg and send it again
* // (msg becomes detached due to copy-on-write optimization)
* // (msg becomes detached due to copy-on-write optimization)
* get_ref<1>(msg) = 10; // msg is now { atom("compute"), 10, 2, 3 }
* get_ref<1>(msg) = 10; // msg is now { atom("compute"), 10, 2, 3 }
* a1
->enqueue(s, msg)
;
* a1
<< msg
;
* a2
->enqueue(s, msg)
;
* a2
<< msg
;
* a3
->enqueue(s, msg)
;
* a3
<< msg
;
* @endcode
* @endcode
*
*
* @section Receive Receive messages
* @section Receive Receive messages
...
@@ -231,11 +231,11 @@
...
@@ -231,11 +231,11 @@
* @code
* @code
* receive
* receive
* (
* (
* on
<atom("hello"), std::string>(
) >> [](const std::string& msg)
* on
(atom("hello"), arg_match
) >> [](const std::string& msg)
* {
* {
* cout << "received hello message: " << msg << endl;
* cout << "received hello message: " << msg << endl;
* },
* },
* on
<atom("compute"), int, int, int>(
) >> [](int i0, int i1, int i2)
* on
(atom("compute"), arg_match
) >> [](int i0, int i1, int i2)
* {
* {
* // 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 + i2);
...
@@ -243,27 +243,7 @@
...
@@ -243,27 +243,7 @@
* );
* );
* @endcode
* @endcode
*
*
* The function @p on creates a pattern.
* Please read the manual for further details about pattern matching.
* It provides two ways of defining patterns:
* either by template parameters (prefixed by up to four atoms) or by arguments.
* The first way matches for types only (exept for the prefixing atoms).
* The second way compares values.
* Use the template function @p val to match for the type only.
*
* This example is equivalent to the previous one but uses the second way
* to define patterns:
*
* @code
* 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) {
* // send our result back to the sender of this messages
* reply(atom("result"), i0 + i1);
* }
* );
* @endcode
*
*
* @section Atoms Atoms
* @section Atoms Atoms
*
*
...
@@ -277,10 +257,10 @@
...
@@ -277,10 +257,10 @@
* @code
* @code
* void math_actor() {
* void math_actor() {
* receive_loop (
* receive_loop (
* on
<atom("plus"), int, int>(
) >> [](int a, int b) {
* on
(atom("plus"), arg_match
) >> [](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"), arg_match
) >> [](int a, int b) {
* reply(atom("result"), a - b);
* reply(atom("result"), a - b);
* }
* }
* );
* );
...
@@ -352,7 +332,7 @@
...
@@ -352,7 +332,7 @@
* delayed_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
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
* delayed_send(self, std::chrono::seconds(1), atom("poll"));
...
@@ -421,7 +401,20 @@
...
@@ -421,7 +401,20 @@
namespace
cppa
{
namespace
cppa
{
#ifdef CPPA_DOCUMENTATION
namespace
detail
{
template
<
typename
T
>
inline
void
send_impl
(
T
*
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
self
->
send_message
(
whom
,
std
::
move
(
what
));
}
template
<
typename
T
,
typename
...
Args
>
inline
void
send_tpl_impl
(
T
*
whom
,
Args
&&
...
what
)
{
if
(
whom
)
self
->
send_message
(
whom
,
make_any_tuple
(
std
::
forward
<
Args
>
(
what
)...));
}
}
// namespace detail
/**
/**
* @ingroup MessageHandling
* @ingroup MessageHandling
...
@@ -429,15 +422,7 @@ namespace cppa {
...
@@ -429,15 +422,7 @@ namespace cppa {
*/
*/
/**
/**
* @brief Sends <tt>{what...}</tt> as a message to @p whom.
* @brief Sends a message to @p whom.
* @param whom Receiver of the message.
* @param what Message elements.
*/
template
<
typename
...
Args
>
void
send
(
const
channel_ptr
&
whom
,
Args
&&
...
what
);
/**
* @brief Send a message to @p whom.
*
*
* <b>Usage example:</b>
* <b>Usage example:</b>
* @code
* @code
...
@@ -447,10 +432,85 @@ void send(const channel_ptr& whom, Args&&... what);
...
@@ -447,10 +432,85 @@ void send(const channel_ptr& whom, Args&&... what);
* @param what Message as instance of {@link any_tuple}.
* @param what Message as instance of {@link any_tuple}.
* @returns @p whom.
* @returns @p whom.
*/
*/
const
channel_ptr
&
operator
<<
(
const
channel_ptr
&
whom
,
any_tuple
what
);
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
));
return
whom
;
}
/**
* @brief Sends <tt>{what...}</tt> as a message to @p whom.
* @param whom Receiver of the message.
* @param what Message elements.
* @pre <tt>sizeof...(Args) > 0</tt>
*/
template
<
class
C
,
typename
...
Args
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
>::
type
send
(
const
intrusive_ptr
<
C
>&
whom
,
Args
&&
...
what
)
{
static_assert
(
sizeof
...(
Args
)
>
0
,
"no message to send"
);
detail
::
send_tpl_impl
(
whom
.
get
(),
std
::
forward
<
Args
>
(
what
)...);
}
/**
* @brief Sends a message to the sender of the last received message.
* @param what Message elements.
* @note Equal to <tt>send(self->last_received(), what...)</tt>.
*/
template
<
typename
...
Args
>
inline
void
reply
(
Args
&&
...
what
)
{
send
(
self
->
last_sender
(),
std
::
forward
<
Args
>
(
what
)...);
}
/**
* @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.
*/
template
<
class
Rep
,
class
Period
,
typename
...
Args
>
inline
void
delayed_send
(
const
channel_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
)...);
}
}
/**
* @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.
* @note Equal to <tt>delayed_send(self->last_sender(), rel_time, what...)</tt>.
* @see delayed_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
)...);
}
/** @} */
/** @} */
#ifndef CPPA_DOCUMENTATION
// 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
)...);
}
inline
const
self_type
&
operator
<<
(
const
self_type
&
s
,
any_tuple
what
)
{
detail
::
send_impl
(
s
.
get
(),
std
::
move
(
what
));
return
s
;
}
#endif // CPPA_DOCUMENTATION
/**
/**
* @ingroup ActorCreation
* @ingroup ActorCreation
* @{
* @{
...
@@ -466,7 +526,11 @@ const channel_ptr& operator<<(const channel_ptr& whom, any_tuple what);
...
@@ -466,7 +526,11 @@ const channel_ptr& operator<<(const channel_ptr& whom, any_tuple what);
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
*/
*/
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn
(
Fun
fun
,
Args
&&
...
args
);
actor_ptr
spawn
(
Fun
&&
fun
,
Args
&&
...
args
)
{
return
get_scheduler
()
->
spawn_impl
(
Hint
,
std
::
forward
<
Fun
>
(
fun
),
std
::
forward
<
Args
>
(
args
)...);
}
/**
/**
* @brief Spawns a new context-switching {@link actor}
* @brief Spawns a new context-switching {@link actor}
...
@@ -477,7 +541,10 @@ actor_ptr spawn(Fun fun, Args&&... args);
...
@@ -477,7 +541,10 @@ actor_ptr spawn(Fun fun, Args&&... args);
* @note This function is equal to <tt>spawn<scheduled>(fun, args...)</tt>.
* @note This function is equal to <tt>spawn<scheduled>(fun, args...)</tt>.
*/
*/
template
<
typename
Fun
,
typename
...
Args
>
template
<
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn
(
Fun
fun
,
Args
&&
...
args
);
actor_ptr
spawn
(
Fun
&&
fun
,
Args
&&
...
args
)
{
return
spawn
<
scheduled
>
(
std
::
forward
<
Fun
>
(
fun
),
std
::
forward
<
Args
>
(
args
)...);
}
/**
/**
* @brief Spawns a new context-switching or thread-mapped {@link actor}
* @brief Spawns a new context-switching or thread-mapped {@link actor}
...
@@ -493,7 +560,14 @@ actor_ptr spawn(Fun fun, Args&&... args);
...
@@ -493,7 +560,14 @@ actor_ptr spawn(Fun fun, Args&&... args);
* the group before this function returns.
* the group before this function returns.
*/
*/
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
template
<
scheduling_hint
Hint
,
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
Fun
&&
fun
,
Args
&&
...
args
)
{
return
get_scheduler
()
->
spawn_cb_impl
(
Hint
,
[
grp
](
local_actor
*
ptr
)
{
ptr
->
join
(
grp
);
},
std
::
forward
<
Fun
>
(
fun
),
std
::
forward
<
Args
>
(
args
)...);
}
/**
/**
* @brief Spawns a new context-switching {@link actor}
* @brief Spawns a new context-switching {@link actor}
...
@@ -510,7 +584,10 @@ actor_ptr spawn_in_group(Fun fun, Args&&... args);
...
@@ -510,7 +584,10 @@ actor_ptr spawn_in_group(Fun fun, Args&&... args);
* <tt>spawn_in_group<scheduled>(fun, args...)</tt>.
* <tt>spawn_in_group<scheduled>(fun, args...)</tt>.
*/
*/
template
<
typename
Fun
,
typename
...
Args
>
template
<
typename
Fun
,
typename
...
Args
>
actor_ptr
spawn_in_group
(
Fun
fun
,
Args
&&
...
args
);
actor_ptr
spawn_in_group
(
Fun
&&
fun
,
Args
&&
...
args
)
{
return
spawn_in_group
<
scheduled
>
(
std
::
forward
<
Fun
>
(
fun
),
std
::
forward
<
Args
>
(
args
)...);
}
/**
/**
* @brief Spawns an actor of type @p ActorImpl.
* @brief Spawns an actor of type @p ActorImpl.
...
@@ -519,7 +596,9 @@ actor_ptr spawn_in_group(Fun fun, Args&&... args);
...
@@ -519,7 +596,9 @@ actor_ptr spawn_in_group(Fun fun, Args&&... args);
* @returns An {@link actor_ptr} to the spawned {@link actor}.
* @returns An {@link actor_ptr} to the spawned {@link actor}.
*/
*/
template
<
class
ActorImpl
,
typename
...
Args
>
template
<
class
ActorImpl
,
typename
...
Args
>
actor_ptr
spawn
(
const
group_ptr
&
grp
,
Args
&&
...
args
);
actor_ptr
spawn
(
Args
&&
...
args
)
{
return
get_scheduler
()
->
spawn
(
new
ActorImpl
(
std
::
forward
<
Args
>
(
args
)...));
}
/**
/**
* @brief Spawns an actor of type @p ActorImpl that joins @p grp immediately.
* @brief Spawns an actor of type @p ActorImpl that joins @p grp immediately.
...
@@ -533,182 +612,12 @@ actor_ptr spawn(const group_ptr& grp, Args&&... args);
...
@@ -533,182 +612,12 @@ actor_ptr spawn(const group_ptr& grp, Args&&... args);
* the group before this function returns.
* the group before this function returns.
*/
*/
template
<
class
ActorImpl
,
typename
...
Args
>
template
<
class
ActorImpl
,
typename
...
Args
>
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
Args
&&
...
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
);
}
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
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
);
}
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
)...);
}
template
<
class
ActorImpl
,
typename
...
Args
>
inline
actor_ptr
spawn
(
Args
&&
...
args
)
{
return
get_scheduler
()
->
spawn
(
new
ActorImpl
(
std
::
forward
<
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
);
});
}
inline
actor_ptr
spawn_in_group
(
const
group_ptr
&
grp
,
void_function
fun
)
{
return
spawn_in_group
<
scheduled
>
(
grp
,
std
::
move
(
fun
));
}
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
)...);
}
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
)...),
return
get_scheduler
()
->
spawn
(
new
ActorImpl
(
std
::
forward
<
Args
>
(
args
)...),
[
&
grp
](
local_actor
*
ptr
)
{
ptr
->
join
(
grp
);
});
[
&
grp
](
local_actor
*
ptr
)
{
ptr
->
join
(
grp
);
});
}
}
namespace
detail
{
/** @} */
inline
void
send_impl
(
channel
*
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
self
->
send_message
(
whom
,
std
::
move
(
what
));
}
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
>
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
;
}
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
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
)...);
}
// 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
...
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 in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
*/
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.
* @param rel_time Relative time duration to delay the message in
* microseconds, milliseconds, seconds or minutes.
* @param what Message elements.
* @see delayed_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
)...);
}
/**
/**
* @brief Blocks execution of this actor until all
* @brief Blocks execution of this actor until all
...
...
cppa/scheduler.hpp
View file @
0f8c067e
...
@@ -55,6 +55,20 @@ class scheduler_helper;
...
@@ -55,6 +55,20 @@ class scheduler_helper;
typedef
std
::
function
<
void
()
>
void_function
;
typedef
std
::
function
<
void
()
>
void_function
;
typedef
std
::
function
<
void
(
local_actor
*
)
>
init_callback
;
typedef
std
::
function
<
void
(
local_actor
*
)
>
init_callback
;
namespace
detail
{
// forwards self_type as actor_ptr, otherwise equal to std::forward
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
();
}
};
}
// namespace detail
/**
/**
* @brief
* @brief
*/
*/
...
@@ -84,6 +98,31 @@ class scheduler {
...
@@ -84,6 +98,31 @@ class scheduler {
virtual
void
enqueue
(
scheduled_actor
*
)
=
0
;
virtual
void
enqueue
(
scheduled_actor
*
)
=
0
;
/**
* @brief Informs the scheduler about a converted context
* (a thread that acts as actor).
* @note Calls <tt>what->attach(...)</tt>.
*/
virtual
void
register_converted_context
(
local_actor
*
what
);
/**
* @brief Informs the scheduler about a hidden (non-actor)
* context that should be counted by await_others_done().
* @returns An {@link attachable} that the hidden context has to destroy
* if his lifetime ends.
*/
virtual
attachable
*
register_hidden_context
();
template
<
typename
Duration
,
typename
...
Data
>
void
delayed_send
(
const
channel_ptr
&
to
,
const
Duration
&
rel_time
,
Data
&&
...
data
)
{
static_assert
(
sizeof
...(
Data
)
>
0
,
"no message to send"
);
auto
sub
=
make_any_tuple
(
std
::
forward
<
Data
>
(
data
)...);
auto
tup
=
make_any_tuple
(
util
::
duration
{
rel_time
},
to
,
std
::
move
(
sub
));
delayed_send_helper
()
->
enqueue
(
self
,
std
::
move
(
tup
));
}
/**
/**
* @brief Spawns a new actor that executes <code>fun()</code>
* @brief Spawns a new actor that executes <code>fun()</code>
* with the scheduling policy @p hint if possible.
* with the scheduling policy @p hint if possible.
...
@@ -112,31 +151,46 @@ class scheduler {
...
@@ -112,31 +151,46 @@ class scheduler {
*/
*/
virtual
actor_ptr
spawn
(
scheduled_actor
*
what
,
init_callback
init_cb
)
=
0
;
virtual
actor_ptr
spawn
(
scheduled_actor
*
what
,
init_callback
init_cb
)
=
0
;
/**
// hide implementation details for documentation
* @brief Informs the scheduler about a converted context
# ifndef CPPA_DOCUMENTATION
* (a thread that acts as actor).
* @note Calls <tt>what->attach(...)</tt>.
template
<
typename
Fun
,
typename
Arg0
,
typename
...
Args
>
*/
actor_ptr
spawn_impl
(
scheduling_hint
hint
,
Fun
&&
fun
,
Arg0
&&
arg0
,
Args
&&
...
args
)
{
virtual
void
register_converted_context
(
local_actor
*
what
);
return
this
->
spawn
(
std
::
bind
(
std
::
forward
<
Fun
>
(
fun
),
detail
::
spawn_fwd_
<
typename
util
::
rm_ref
<
Arg0
>::
type
>::
_
(
arg0
),
detail
::
spawn_fwd_
<
typename
util
::
rm_ref
<
Args
>::
type
>::
_
(
args
)...),
hint
);
}
/**
template
<
typename
Fun
>
* @brief Informs the scheduler about a hidden (non-actor)
actor_ptr
spawn_impl
(
scheduling_hint
hint
,
Fun
&&
fun
)
{
* context that should be counted by await_others_done().
return
this
->
spawn
(
std
::
forward
<
Fun
>
(
fun
),
hint
);
* @returns An {@link attachable} that the hidden context has to destroy
}
* if his lifetime ends.
*/
virtual
attachable
*
register_hidden_context
();
template
<
typename
Duration
,
typename
...
Data
>
template
<
typename
InitCallback
,
typename
Fun
,
typename
Arg0
,
typename
...
Args
>
void
delayed_send
(
const
actor_ptr
&
to
,
actor_ptr
spawn_cb_impl
(
scheduling_hint
hint
,
const
Duration
&
rel_time
,
InitCallback
&&
init_cb
,
Data
&&
...
data
)
{
Fun
&&
fun
,
Arg0
&&
arg0
,
Args
&&
...
args
)
{
static_assert
(
sizeof
...(
Data
)
>
0
,
"no message to send"
);
return
this
->
spawn
(
auto
sub
=
make_any_tuple
(
std
::
forward
<
Data
>
(
data
)...);
std
::
bind
(
auto
tup
=
make_any_tuple
(
util
::
duration
{
rel_time
},
to
,
std
::
move
(
sub
));
std
::
forward
<
Fun
>
(
fun
),
delayed_send_helper
()
->
enqueue
(
self
,
std
::
move
(
tup
));
detail
::
spawn_fwd_
<
typename
util
::
rm_ref
<
Arg0
>::
type
>::
_
(
arg0
),
detail
::
spawn_fwd_
<
typename
util
::
rm_ref
<
Args
>::
type
>::
_
(
args
)...),
hint
,
std
::
forward
<
InitCallback
>
(
init_cb
));
}
}
template
<
typename
InitCallback
,
typename
Fun
>
actor_ptr
spawn_cb_impl
(
scheduling_hint
hint
,
InitCallback
&&
init_cb
,
Fun
&&
fun
)
{
return
this
->
spawn
(
std
::
forward
<
Fun
>
(
fun
),
hint
,
std
::
forward
<
InitCallback
>
(
init_cb
));
}
# endif // CPPA_DOCUMENTATION
};
};
/**
/**
...
...
cppa/self.hpp
View file @
0f8c067e
...
@@ -49,7 +49,8 @@ extern local_actor* self;
...
@@ -49,7 +49,8 @@ extern local_actor* self;
class
local_actor
;
class
local_actor
;
// convertible<...> enables "actor_ptr this_actor = self;"
// convertible<...> enables "actor_ptr this_actor = self;"
class
self_type
:
public
convertible
<
self_type
,
actor
*>
{
class
self_type
:
public
convertible
<
self_type
,
actor
*>
,
public
convertible
<
self_type
,
channel
*>
{
self_type
(
const
self_type
&
)
=
delete
;
self_type
(
const
self_type
&
)
=
delete
;
self_type
&
operator
=
(
const
self_type
&
)
=
delete
;
self_type
&
operator
=
(
const
self_type
&
)
=
delete
;
...
...
src/local_actor.cpp
View file @
0f8c067e
...
@@ -68,8 +68,7 @@ class down_observer : public attachable {
...
@@ -68,8 +68,7 @@ class down_observer : public attachable {
}
// namespace <anonymous>
}
// namespace <anonymous>
local_actor
::
local_actor
(
bool
sflag
)
local_actor
::
local_actor
(
bool
sflag
)
:
m_chaining
(
sflag
),
m_trap_exit
(
false
),
m_is_scheduled
(
sflag
)
{
:
m_chaining
(
sflag
),
m_trap_exit
(
false
),
m_is_scheduled
(
sflag
)
{
}
}
void
local_actor
::
monitor
(
actor_ptr
whom
)
{
void
local_actor
::
monitor
(
actor_ptr
whom
)
{
if
(
whom
)
whom
->
attach
(
new
down_observer
(
this
,
whom
));
if
(
whom
)
whom
->
attach
(
new
down_observer
(
this
,
whom
));
...
@@ -85,14 +84,14 @@ void local_actor::on_exit() { }
...
@@ -85,14 +84,14 @@ void local_actor::on_exit() { }
void
local_actor
::
init
()
{
}
void
local_actor
::
init
()
{
}
void
local_actor
::
join
(
const
group_ptr
&
what
)
{
void
local_actor
::
join
(
const
group_ptr
&
what
)
{
if
(
!
what
)
return
;
if
(
what
)
attach
(
what
->
subscribe
(
this
));
attach
(
what
->
subscribe
(
this
));
}
}
void
local_actor
::
leave
(
const
group_ptr
&
what
)
{
void
local_actor
::
leave
(
const
group_ptr
&
what
)
{
if
(
!
what
)
return
;
if
(
what
)
{
attachable
::
token
group_token
(
typeid
(
group
::
unsubscriber
),
what
.
get
());
attachable
::
token
group_token
(
typeid
(
group
::
unsubscriber
),
what
.
get
());
detach
(
group_token
);
detach
(
group_token
);
}
}
}
}
// namespace cppa
}
// namespace cppa
src/scheduler.cpp
View file @
0f8c067e
...
@@ -108,8 +108,8 @@ void scheduler_helper::time_emitter(scheduler_helper::ptr_type m_self) {
...
@@ -108,8 +108,8 @@ void scheduler_helper::time_emitter(scheduler_helper::ptr_type m_self) {
bool
done
=
false
;
bool
done
=
false
;
// message handling rules
// message handling rules
auto
mfun
=
(
auto
mfun
=
(
on
<
util
::
duration
,
actor
_ptr
,
anything
>
()
>>
[
&
](
const
util
::
duration
&
d
,
on
<
util
::
duration
,
channel
_ptr
,
anything
>
()
>>
[
&
](
const
util
::
duration
&
d
,
const
actor
_ptr
&
)
{
const
channel
_ptr
&
)
{
// calculate timeout
// calculate timeout
auto
timeout
=
now
();
auto
timeout
=
now
();
timeout
+=
d
;
timeout
+=
d
;
...
...
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