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
04fc1827
Commit
04fc1827
authored
Mar 14, 2013
by
Joseph Noir
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'unstable' into topic/opencl
parents
16cb9399
05d61a8d
Changes
98
Show whitespace changes
Inline
Side-by-side
Showing
98 changed files
with
1591 additions
and
1821 deletions
+1591
-1821
CMakeLists.txt
CMakeLists.txt
+1
-2
cppa.files
cppa.files
+8
-8
cppa/actor.hpp
cppa/actor.hpp
+4
-4
cppa/actor_companion_mixin.hpp
cppa/actor_companion_mixin.hpp
+29
-25
cppa/actor_proxy.hpp
cppa/actor_proxy.hpp
+1
-1
cppa/announce.hpp
cppa/announce.hpp
+9
-10
cppa/any_tuple.hpp
cppa/any_tuple.hpp
+13
-8
cppa/atom.hpp
cppa/atom.hpp
+5
-1
cppa/behavior.hpp
cppa/behavior.hpp
+81
-36
cppa/channel.hpp
cppa/channel.hpp
+2
-8
cppa/context_switching_actor.hpp
cppa/context_switching_actor.hpp
+5
-6
cppa/cow_tuple.hpp
cppa/cow_tuple.hpp
+25
-20
cppa/cppa.hpp
cppa/cppa.hpp
+54
-26
cppa/detail/behavior_stack.hpp
cppa/detail/behavior_stack.hpp
+7
-7
cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/default_uniform_type_info_impl.hpp
+15
-15
cppa/detail/empty_tuple.hpp
cppa/detail/empty_tuple.hpp
+2
-2
cppa/detail/event_based_actor_factory.hpp
cppa/detail/event_based_actor_factory.hpp
+9
-11
cppa/detail/get_behavior.hpp
cppa/detail/get_behavior.hpp
+22
-28
cppa/detail/memory.hpp
cppa/detail/memory.hpp
+12
-11
cppa/detail/projection.hpp
cppa/detail/projection.hpp
+29
-28
cppa/detail/ptype_to_type.hpp
cppa/detail/ptype_to_type.hpp
+21
-23
cppa/detail/receive_loop_helper.hpp
cppa/detail/receive_loop_helper.hpp
+11
-33
cppa/detail/receive_policy.hpp
cppa/detail/receive_policy.hpp
+19
-14
cppa/detail/scheduled_actor_dummy.hpp
cppa/detail/scheduled_actor_dummy.hpp
+3
-4
cppa/detail/singleton_mixin.hpp
cppa/detail/singleton_mixin.hpp
+2
-2
cppa/detail/sync_request_bouncer.hpp
cppa/detail/sync_request_bouncer.hpp
+3
-3
cppa/detail/tdata.hpp
cppa/detail/tdata.hpp
+60
-44
cppa/detail/tuple_vals.hpp
cppa/detail/tuple_vals.hpp
+2
-3
cppa/detail/tuple_view.hpp
cppa/detail/tuple_view.hpp
+9
-8
cppa/detail/type_to_ptype.hpp
cppa/detail/type_to_ptype.hpp
+27
-43
cppa/detail/value_guard.hpp
cppa/detail/value_guard.hpp
+21
-31
cppa/either.hpp
cppa/either.hpp
+0
-279
cppa/enable_weak_ptr.hpp
cppa/enable_weak_ptr.hpp
+3
-3
cppa/event_based_actor.hpp
cppa/event_based_actor.hpp
+19
-24
cppa/extend.hpp
cppa/extend.hpp
+4
-3
cppa/guard_expr.hpp
cppa/guard_expr.hpp
+29
-70
cppa/intrusive_ptr.hpp
cppa/intrusive_ptr.hpp
+6
-13
cppa/local_actor.hpp
cppa/local_actor.hpp
+146
-174
cppa/mailbox_based.hpp
cppa/mailbox_based.hpp
+2
-14
cppa/mailbox_element.hpp
cppa/mailbox_element.hpp
+23
-22
cppa/match.hpp
cppa/match.hpp
+19
-51
cppa/match_expr.hpp
cppa/match_expr.hpp
+80
-65
cppa/message_future.hpp
cppa/message_future.hpp
+17
-17
cppa/message_id.hpp
cppa/message_id.hpp
+16
-16
cppa/network/continuable_reader.hpp
cppa/network/continuable_reader.hpp
+0
-2
cppa/network/default_actor_proxy.hpp
cppa/network/default_actor_proxy.hpp
+5
-6
cppa/network/default_message_queue.hpp
cppa/network/default_message_queue.hpp
+3
-3
cppa/network/default_peer.hpp
cppa/network/default_peer.hpp
+0
-9
cppa/network/message_header.hpp
cppa/network/message_header.hpp
+2
-2
cppa/network/middleman.hpp
cppa/network/middleman.hpp
+4
-3
cppa/network/protocol.hpp
cppa/network/protocol.hpp
+2
-10
cppa/object.hpp
cppa/object.hpp
+1
-1
cppa/on.hpp
cppa/on.hpp
+11
-11
cppa/partial_function.hpp
cppa/partial_function.hpp
+61
-55
cppa/qtsupport/actor_widget_mixin.hpp
cppa/qtsupport/actor_widget_mixin.hpp
+2
-2
cppa/receive.hpp
cppa/receive.hpp
+53
-50
cppa/response_handle.hpp
cppa/response_handle.hpp
+3
-3
cppa/sb_actor.hpp
cppa/sb_actor.hpp
+2
-2
cppa/scheduled_actor.hpp
cppa/scheduled_actor.hpp
+9
-7
cppa/scheduler.hpp
cppa/scheduler.hpp
+1
-1
cppa/stacked.hpp
cppa/stacked.hpp
+31
-44
cppa/thread_mapped_actor.hpp
cppa/thread_mapped_actor.hpp
+4
-32
cppa/threaded.hpp
cppa/threaded.hpp
+169
-0
cppa/tpartial_function.hpp
cppa/tpartial_function.hpp
+16
-16
cppa/util/apply_args.hpp
cppa/util/apply_args.hpp
+8
-8
cppa/util/buffer.hpp
cppa/util/buffer.hpp
+1
-1
cppa/util/callable_trait.hpp
cppa/util/callable_trait.hpp
+32
-74
cppa/util/dptr.hpp
cppa/util/dptr.hpp
+21
-22
cppa/util/get_result_type.hpp
cppa/util/get_result_type.hpp
+20
-10
cppa/util/is_callable.hpp
cppa/util/is_callable.hpp
+33
-23
cppa/util/purge_refs.hpp
cppa/util/purge_refs.hpp
+8
-2
cppa/util/rebindable_reference.hpp
cppa/util/rebindable_reference.hpp
+118
-0
cppa/util/replace_type.hpp
cppa/util/replace_type.hpp
+1
-2
cppa/util/static_foreach.hpp
cppa/util/static_foreach.hpp
+0
-98
cppa/util/type_list.hpp
cppa/util/type_list.hpp
+3
-4
cppa/util/wrapped.hpp
cppa/util/wrapped.hpp
+1
-1
src/actor.cpp
src/actor.cpp
+1
-1
src/behavior_stack.cpp
src/behavior_stack.cpp
+1
-1
src/context_switching_actor.cpp
src/context_switching_actor.cpp
+2
-2
src/default_actor_proxy.cpp
src/default_actor_proxy.cpp
+4
-4
src/event_based_actor.cpp
src/event_based_actor.cpp
+3
-7
src/group_manager.cpp
src/group_manager.cpp
+3
-3
src/local_actor.cpp
src/local_actor.cpp
+6
-10
src/logging.cpp
src/logging.cpp
+0
-2
src/mailbox_element.cpp
src/mailbox_element.cpp
+6
-6
src/memory.cpp
src/memory.cpp
+3
-3
src/message_header.cpp
src/message_header.cpp
+1
-1
src/middleman.cpp
src/middleman.cpp
+0
-1
src/protocol.cpp
src/protocol.cpp
+0
-8
src/response_handle.cpp
src/response_handle.cpp
+1
-1
src/scheduled_actor.cpp
src/scheduled_actor.cpp
+7
-3
src/scheduled_actor_dummy.cpp
src/scheduled_actor_dummy.cpp
+3
-4
src/scheduler.cpp
src/scheduler.cpp
+8
-9
src/thread_mapped_actor.cpp
src/thread_mapped_actor.cpp
+3
-9
src/thread_pool_scheduler.cpp
src/thread_pool_scheduler.cpp
+1
-2
src/unicast_network.cpp
src/unicast_network.cpp
+6
-8
src/uniform_type_info.cpp
src/uniform_type_info.cpp
+1
-1
unit_testing/test_spawn.cpp
unit_testing/test_spawn.cpp
+31
-15
No files found.
CMakeLists.txt
View file @
04fc1827
...
...
@@ -124,6 +124,7 @@ set(LIBCPPA_SRC
src/ipv4_io_stream.cpp
src/local_actor.cpp
src/logging.cpp
src/mailbox_element.cpp
src/match.cpp
src/memory.cpp
src/memory_managed.cpp
...
...
@@ -137,8 +138,6 @@ set(LIBCPPA_SRC
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/receive.cpp
src/recursive_queue_node.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
...
...
cppa.files
View file @
04fc1827
...
...
@@ -24,7 +24,6 @@ cppa/detail/atom_val.hpp
cppa/detail/behavior_impl.hpp
cppa/detail/behavior_stack.hpp
cppa/detail/boxed.hpp
cppa/detail/channel.hpp
cppa/detail/container_tuple_view.hpp
cppa/detail/decorated_names_map.hpp
cppa/detail/decorated_tuple.hpp
...
...
@@ -48,7 +47,8 @@ cppa/detail/pseudo_tuple.hpp
cppa/detail/ptype_to_type.hpp
cppa/detail/receive_loop_helper.hpp
cppa/detail/receive_policy.hpp
cppa/detail/recursive_queue_node.hpp
cppa/mailbox_element.hpp
cppa/mailbox_based.hpp
cppa/detail/scheduled_actor_dummy.hpp
cppa/detail/serialize_tuple.hpp
cppa/detail/singleton_manager.hpp
...
...
@@ -68,7 +68,6 @@ cppa/detail/unboxed.hpp
cppa/detail/uniform_type_info_map.hpp
cppa/detail/value_guard.hpp
cppa/detail/yield_interface.hpp
cppa/either.hpp
cppa/enable_weak_ptr.hpp
cppa/event_based_actor.hpp
cppa/exception.hpp
...
...
@@ -80,7 +79,6 @@ cppa/group.hpp
cppa/guard_expr.hpp
cppa/intrusive/blocking_single_reader_queue.hpp
cppa/intrusive/single_reader_queue.hpp
cppa/intrusive_fwd_ptr.hpp
cppa/intrusive_ptr.hpp
cppa/local_actor.hpp
cppa/logging.hpp
...
...
@@ -145,7 +143,6 @@ cppa/util/duration.hpp
cppa/util/element_at.hpp
cppa/util/fiber.hpp
cppa/util/fixed_vector.hpp
cppa/util/if_else.hpp
cppa/util/int_list.hpp
cppa/util/is_array_of.hpp
cppa/util/is_builtin.hpp
...
...
@@ -168,7 +165,6 @@ cppa/util/rm_ref.hpp
cppa/util/scope_guard.hpp
cppa/util/shared_lock_guard.hpp
cppa/util/shared_spinlock.hpp
cppa/util/static_foreach.hpp
cppa/util/tbind.hpp
cppa/util/type_list.hpp
cppa/util/type_pair.hpp
...
...
@@ -244,8 +240,7 @@ src/partial_function.cpp
src/primitive_variant.cpp
src/process_information.cpp
src/protocol.cpp
src/receive.cpp
src/recursive_queue_node.cpp
src/mailbox_element.cpp
src/ref_counted.cpp
src/response_handle.cpp
src/ripemd_160.cpp
...
...
@@ -302,3 +297,8 @@ cppa/extend.hpp
cppa/detail/sync_request_bouncer.hpp
cppa/memory_cached.hpp
cppa/singletons.hpp
cppa/threaded.hpp
cppa/util/dptr.hpp
cppa/util/is_callable.hpp
cppa/util/get_result_type.hpp
cppa/util/rebindable_reference.hpp
cppa/actor.hpp
View file @
04fc1827
...
...
@@ -86,7 +86,7 @@ class actor : public channel {
* @pre <tt>id.valid()</tt>
*/
virtual
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
message_id
id
,
any_tuple
msg
)
=
0
;
/**
...
...
@@ -96,7 +96,7 @@ class actor : public channel {
* its state to @p pending in response to the enqueue operation.
*/
virtual
bool
chained_sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
message_id
id
,
any_tuple
msg
);
/**
...
...
@@ -110,7 +110,7 @@ class actor : public channel {
* otherwise (actor already exited) @p false.
* @warning The actor takes ownership of @p ptr.
*/
virtual
bool
attach
(
attachable_ptr
ptr
);
bool
attach
(
attachable_ptr
ptr
);
/**
* @brief Convenience function that attaches the functor
...
...
@@ -129,7 +129,7 @@ class actor : public channel {
/**
* @brief Detaches the first attached object that matches @p what.
*/
v
irtual
v
oid
detach
(
const
attachable
::
token
&
what
);
void
detach
(
const
attachable
::
token
&
what
);
/**
* @brief Links this actor to @p other.
...
...
cppa/actor_companion_mixin.hpp
View file @
04fc1827
...
...
@@ -59,10 +59,10 @@ class actor_companion_mixin : public Base {
public:
typedef
std
::
unique_ptr
<
detail
::
recursive_queue_node
,
detail
::
disposer
>
message_pointer
;
typedef
std
::
unique_ptr
<
mailbox_element
,
detail
::
disposer
>
message_pointer
;
template
<
typename
...
Arg
s
>
actor_companion_mixin
(
Args
&&
...
args
)
:
super
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
template
<
typename
...
T
s
>
actor_companion_mixin
(
Ts
&&
...
args
)
:
super
(
std
::
forward
<
T
s
>
(
args
)...)
{
m_self
.
reset
(
detail
::
memory
::
create
<
companion
>
(
this
));
}
...
...
@@ -89,9 +89,9 @@ class actor_companion_mixin : public Base {
* @note While the message handler is invoked, @p self will point
* to the companion object to enable send() and reply().
*/
template
<
typename
...
Arg
s
>
void
set_message_handler
(
Args
&&
...
matchExpression
s
)
{
m_message_handler
=
match_expr_convert
(
std
::
forward
<
Args
>
(
matchExpression
s
)...);
template
<
typename
...
T
s
>
void
set_message_handler
(
Ts
&&
...
arg
s
)
{
m_message_handler
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
arg
s
)...);
}
/**
...
...
@@ -112,8 +112,8 @@ class actor_companion_mixin : public Base {
class
companion
:
public
local_actor
{
friend
class
actor_companion_mixin
;
typedef
util
::
shared_spinlock
lock_type
;
typedef
std
::
unique_ptr
<
detail
::
recursive_queue_node
,
detail
::
disposer
>
node_ptr
;
public:
...
...
@@ -129,37 +129,33 @@ class actor_companion_mixin : public Base {
void
enqueue
(
const
actor_ptr
&
sender
,
any_tuple
msg
)
{
util
::
shared_lock_guard
<
lock_type
>
guard
(
m_lock
);
if
(
m_parent
)
{
m_parent
->
new_message
(
new_node_ptr
(
sender
,
std
::
move
(
msg
)));
}
if
(
m_parent
)
push_message
(
sender
,
std
::
move
(
msg
));
}
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
message_id
id
,
any_tuple
msg
)
{
util
::
shared_lock_guard
<
lock_type
>
guard
(
m_lock
);
if
(
m_parent
)
{
m_parent
->
new_message
(
new_node_ptr
(
sender
,
std
::
move
(
msg
),
id
));
}
if
(
m_parent
)
push_message
(
sender
,
std
::
move
(
msg
),
id
);
}
bool
initialized
()
const
{
return
true
;
}
void
quit
(
std
::
uint32_t
)
{
throw
std
::
runtime_error
(
"
ActorWidgetMixin::Gateway::ex
it "
"is
forbidden,
use Qt's widget "
"management instead
!
"
);
throw
std
::
runtime_error
(
"
Using actor_companion_mixin::qu
it "
"is
prohibited;
use Qt's widget "
"management instead
.
"
);
}
void
dequeue
(
behavior
&
)
{
throw_no_recv
();
}
void
dequeue
(
partial_function
&
)
{
throw_no_recv
();
}
void
dequeue
(
behavior
&
)
{
throw_no_recv
();
}
void
dequeue_response
(
behavior
&
,
message_id
_t
)
{
void
dequeue_response
(
behavior
&
,
message_id
)
{
throw_no_recv
();
}
void
become_waiting_for
(
behavior
&&
,
message_id_t
)
{
void
become_waiting_for
(
behavior
,
message_id
)
{
throw_no_become
();
}
...
...
@@ -169,9 +165,11 @@ class actor_companion_mixin : public Base {
private:
template
<
typename
...
Args
>
node_ptr
new_node_ptr
(
Args
&&
...
args
)
{
return
node_ptr
(
detail
::
memory
::
create
<
detail
::
recursive_queue_node
>
(
std
::
forward
<
Args
>
(
args
)...));
template
<
typename
...
Ts
>
void
push_message
(
Ts
&&
...
args
)
{
message_pointer
ptr
;
ptr
.
reset
(
detail
::
memory
::
create
<
mailbox_element
>
(
std
::
forward
<
Ts
>
(
args
)...));
m_parent
->
new_message
(
std
::
move
(
ptr
));
}
void
throw_no_become
()
{
...
...
@@ -186,12 +184,18 @@ class actor_companion_mixin : public Base {
"receive() API"
);
}
// guards access to m_parent
lock_type
m_lock
;
// set to nullptr if this companion became detached
actor_companion_mixin
*
m_parent
;
};
// used as 'self' before calling message handler
intrusive_ptr
<
companion
>
m_self
;
// user-defined message handler for incoming messages
partial_function
m_message_handler
;
};
...
...
cppa/actor_proxy.hpp
View file @
04fc1827
...
...
@@ -46,7 +46,7 @@ class actor_proxy_cache;
* @brief Represents a remote actor.
* @extends actor
*/
class
actor_proxy
:
public
extend
<
actor
,
actor_proxy
>::
with
<
enable_weak_ptr
>
{
class
actor_proxy
:
public
extend
<
actor
>::
with
<
enable_weak_ptr
>
{
typedef
combined_type
super
;
...
...
cppa/announce.hpp
View file @
04fc1827
...
...
@@ -108,9 +108,9 @@ bool announce(const std::type_info& tinfo, uniform_type_info* utype);
* @see {@link announce_4.cpp announce example 4}
* @returns A pair of @p c_ptr and the created meta informations.
*/
template
<
class
C
,
class
Parent
,
typename
...
Arg
s
>
template
<
class
C
,
class
Parent
,
typename
...
T
s
>
std
::
pair
<
C
Parent
::*
,
util
::
abstract_uniform_type_info
<
C
>*>
compound_member
(
C
Parent
::*
c_ptr
,
const
Arg
s
&
...
args
)
{
compound_member
(
C
Parent
::*
c_ptr
,
const
T
s
&
...
args
)
{
return
{
c_ptr
,
new
detail
::
default_uniform_type_info_impl
<
C
>
(
args
...)};
}
...
...
@@ -123,9 +123,9 @@ compound_member(C Parent::*c_ptr, const Args&... args) {
* @see {@link announce_4.cpp announce example 4}
* @returns A pair of @p c_ptr and the created meta informations.
*/
template
<
class
C
,
class
Parent
,
typename
...
Arg
s
>
template
<
class
C
,
class
Parent
,
typename
...
T
s
>
std
::
pair
<
C
&
(
Parent
::*
)(),
util
::
abstract_uniform_type_info
<
C
>*>
compound_member
(
C
&
(
Parent
::*
getter
)(),
const
Arg
s
&
...
args
)
{
compound_member
(
C
&
(
Parent
::*
getter
)(),
const
T
s
&
...
args
)
{
return
{
getter
,
new
detail
::
default_uniform_type_info_impl
<
C
>
(
args
...)};
}
...
...
@@ -140,12 +140,12 @@ compound_member(C& (Parent::*getter)(), const Args&... args) {
* @returns A pair of @p c_ptr and the created meta informations.
*/
template
<
class
Parent
,
typename
GRes
,
typename
SRes
,
typename
SArg
,
typename
...
Arg
s
>
typename
SRes
,
typename
SArg
,
typename
...
T
s
>
std
::
pair
<
std
::
pair
<
GRes
(
Parent
::*
)()
const
,
SRes
(
Parent
::*
)(
SArg
)
>
,
util
::
abstract_uniform_type_info
<
typename
util
::
rm_ref
<
GRes
>::
type
>*>
compound_member
(
const
std
::
pair
<
GRes
(
Parent
::*
)()
const
,
SRes
(
Parent
::*
)(
SArg
)
>&
gspair
,
const
Arg
s
&
...
args
)
{
const
T
s
&
...
args
)
{
typedef
typename
util
::
rm_ref
<
GRes
>::
type
mtype
;
return
{
gspair
,
new
detail
::
default_uniform_type_info_impl
<
mtype
>
(
args
...)};
}
...
...
@@ -157,10 +157,9 @@ compound_member(const std::pair<GRes (Parent::*)() const,
* @returns @c true if @p T was added to the libcppa type system,
* @c false otherwise.
*/
template
<
typename
T
,
typename
...
Args
>
inline
bool
announce
(
const
Args
&
...
args
)
{
return
announce
(
typeid
(
T
),
new
detail
::
default_uniform_type_info_impl
<
T
>
(
args
...));
template
<
typename
T
,
typename
...
Ts
>
inline
bool
announce
(
const
Ts
&
...
args
)
{
return
announce
(
typeid
(
T
),
new
detail
::
default_uniform_type_info_impl
<
T
>
(
args
...));
}
/**
...
...
cppa/any_tuple.hpp
View file @
04fc1827
...
...
@@ -74,14 +74,14 @@ class any_tuple {
/**
* @brief Creates a tuple from @p t.
*/
template
<
typename
...
Arg
s
>
any_tuple
(
const
cow_tuple
<
Args
...
>&
t
)
:
m_vals
(
t
.
vals
())
{
}
template
<
typename
...
T
s
>
any_tuple
(
const
cow_tuple
<
Ts
...
>&
arg
)
:
m_vals
(
arg
.
vals
())
{
}
/**
* @brief Creates a tuple and moves the content from @p t.
*/
template
<
typename
...
Arg
s
>
any_tuple
(
cow_tuple
<
Args
...
>&&
t
)
:
m_vals
(
std
::
move
(
t
.
m_vals
))
{
}
template
<
typename
...
T
s
>
any_tuple
(
cow_tuple
<
Ts
...
>&&
arg
)
:
m_vals
(
std
::
move
(
arg
.
m_vals
))
{
}
/**
* @brief Move constructor.
...
...
@@ -181,10 +181,13 @@ class any_tuple {
inline
const
std
::
type_info
*
type_token
()
const
;
/**
* @brief Checks whether this
* @brief Checks whether this tuple is dynamically typed, i.e.,
* its types were not known during compile time.
*/
inline
bool
dynamically_typed
()
const
;
/** @cond PRIVATE */
template
<
typename
T
>
static
inline
any_tuple
view
(
T
&&
value
);
...
...
@@ -194,6 +197,8 @@ class any_tuple {
explicit
any_tuple
(
detail
::
abstract_tuple
*
);
/** @endcond */
private:
data_ptr
m_vals
;
...
...
@@ -244,9 +249,9 @@ inline bool operator!=(const any_tuple& lhs, const any_tuple& rhs) {
* @brief Creates an {@link any_tuple} containing the elements @p args.
* @param args Values to initialize the tuple elements.
*/
template
<
typename
...
Arg
s
>
inline
any_tuple
make_any_tuple
(
Arg
s
&&
...
args
)
{
return
make_cow_tuple
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
inline
any_tuple
make_any_tuple
(
T
s
&&
...
args
)
{
return
make_cow_tuple
(
std
::
forward
<
T
s
>
(
args
)...);
}
/******************************************************************************
...
...
cppa/atom.hpp
View file @
04fc1827
...
...
@@ -40,7 +40,11 @@ namespace cppa {
/**
* @brief The value type of atoms.
*/
enum
class
atom_value
:
std
::
uint64_t
{
dirty_little_hack
=
37337
};
enum
class
atom_value
:
std
::
uint64_t
{
/** @cond PRIVATE */
dirty_little_hack
=
37337
/** @endcond */
};
/**
* @brief Returns @p what as a string representation.
...
...
cppa/behavior.hpp
View file @
04fc1827
...
...
@@ -39,7 +39,6 @@
#include "cppa/util/tbind.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/util/type_list.hpp"
...
...
@@ -56,10 +55,18 @@ class behavior {
public:
/** @cond PRIVATE */
typedef
intrusive_ptr
<
detail
::
behavior_impl
>
impl_ptr
;
inline
auto
as_behavior_impl
()
const
->
const
impl_ptr
&
;
inline
behavior
(
impl_ptr
ptr
);
static
constexpr
bool
may_have_timeout
=
true
;
/** @endcond */
behavior
()
=
default
;
behavior
(
behavior
&&
)
=
default
;
behavior
(
const
behavior
&
)
=
default
;
...
...
@@ -68,49 +75,39 @@ class behavior {
behavior
(
const
partial_function
&
fun
);
inline
behavior
(
impl_ptr
ptr
)
:
m_impl
(
std
::
move
(
ptr
))
{
}
template
<
typename
F
>
behavior
(
const
timeout_definition
<
F
>&
arg
)
:
m_impl
(
detail
::
new_default_behavior_impl
(
detail
::
dummy_match_expr
{},
arg
.
timeout
,
arg
.
handler
)
)
{
}
behavior
(
const
timeout_definition
<
F
>&
arg
);
template
<
typename
F
>
behavior
(
util
::
duration
d
,
F
f
)
:
m_impl
(
detail
::
new_default_behavior_impl
(
detail
::
dummy_match_expr
{},
d
,
f
))
{
}
template
<
typename
...
Cases
>
behavior
(
const
match_expr
<
Cases
...
>&
arg0
)
:
m_impl
(
detail
::
new_default_behavior_impl
(
arg0
,
util
::
duration
(),
[]()
{
}))
{
}
behavior
(
util
::
duration
d
,
F
f
);
template
<
typename
...
Cases
,
typename
Arg1
,
typename
...
Args
>
behavior
(
const
match_expr
<
Cases
...
>&
arg0
,
const
Arg1
&
arg1
,
const
Args
&
...
args
)
:
m_impl
(
detail
::
match_expr_concat
(
arg0
,
arg1
,
args
...))
{
}
template
<
typename
...
Cases
,
typename
...
Ts
>
behavior
(
const
match_expr
<
Cases
...
>&
arg
,
const
Ts
&
...
args
);
inline
void
handle_timeout
()
{
m_impl
->
handle_timeout
();
}
inline
const
util
::
duration
&
timeout
()
const
{
return
m_impl
->
timeout
();
}
/**
* @brief Invokes the timeout callback.
*/
inline
void
handle_timeout
();
inline
bool
undefined
()
const
{
return
m_impl
==
nullptr
||
m_impl
->
timeout
().
valid
()
==
false
;
}
/**
* @brief Returns the duration after which receives using
* this behavior should time out.
*/
inline
const
util
::
duration
&
timeout
()
const
;
/**
* @copydoc partial_function::operator()()
*/
template
<
typename
T
>
inline
bool
operator
()(
T
&&
arg
)
{
return
(
m_impl
)
&&
m_impl
->
invoke
(
std
::
forward
<
T
>
(
arg
));
}
inline
bool
operator
()(
T
&&
arg
);
/**
* @brief Adds a continuation to this behavior that is executed
* whenever this behavior was successfully applied to
* a message.
*/
template
<
typename
F
>
inline
behavior
add_continuation
(
F
fun
)
{
return
{
new
detail
::
continuation_decorator
<
F
>
(
std
::
move
(
fun
),
m_impl
)};
}
const
impl_ptr
&
as_behavior_impl
()
const
{
return
m_impl
;
}
inline
behavior
add_continuation
(
F
fun
);
private:
...
...
@@ -118,12 +115,60 @@ class behavior {
};
template
<
typename
...
Lhs
,
typename
F
>
inline
behavior
operator
,(
const
match_expr
<
Lhs
...
>&
lhs
,
/**
* @brief Creates a behavior from a match expression and a timeout definition.
* @relates behavior
*/
template
<
typename
...
Cases
,
typename
F
>
inline
behavior
operator
,(
const
match_expr
<
Cases
...
>&
lhs
,
const
timeout_definition
<
F
>&
rhs
)
{
return
match_expr_convert
(
lhs
,
rhs
);
}
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
template
<
typename
F
>
behavior
::
behavior
(
const
timeout_definition
<
F
>&
arg
)
:
m_impl
(
detail
::
new_default_behavior_impl
(
detail
::
dummy_match_expr
{},
arg
.
timeout
,
arg
.
handler
)
)
{
}
template
<
typename
F
>
behavior
::
behavior
(
util
::
duration
d
,
F
f
)
:
m_impl
(
detail
::
new_default_behavior_impl
(
detail
::
dummy_match_expr
{},
d
,
f
))
{
}
template
<
typename
...
Cases
,
typename
...
Ts
>
behavior
::
behavior
(
const
match_expr
<
Cases
...
>&
arg
,
const
Ts
&
...
args
)
:
m_impl
(
detail
::
match_expr_concat
(
arg
,
args
...))
{
}
inline
behavior
::
behavior
(
impl_ptr
ptr
)
:
m_impl
(
std
::
move
(
ptr
))
{
}
inline
void
behavior
::
handle_timeout
()
{
m_impl
->
handle_timeout
();
}
inline
const
util
::
duration
&
behavior
::
timeout
()
const
{
return
m_impl
->
timeout
();
}
template
<
typename
T
>
inline
bool
behavior
::
operator
()(
T
&&
arg
)
{
return
(
m_impl
)
&&
m_impl
->
invoke
(
std
::
forward
<
T
>
(
arg
));
}
inline
auto
behavior
::
as_behavior_impl
()
const
->
const
impl_ptr
&
{
return
m_impl
;
}
template
<
typename
F
>
inline
behavior
behavior
::
add_continuation
(
F
fun
)
{
return
{
new
detail
::
continuation_decorator
<
F
>
(
std
::
move
(
fun
),
m_impl
)};
}
}
// namespace cppa
#endif // CPPA_BEHAVIOR_HPP
cppa/channel.hpp
View file @
04fc1827
...
...
@@ -67,12 +67,6 @@ class channel : public ref_counted {
virtual
~
channel
();
private:
// channel is a sealed class and the only
// allowed subclasses are actor and group.
channel
()
=
default
;
};
/**
...
...
@@ -84,8 +78,8 @@ typedef intrusive_ptr<channel> channel_ptr;
/**
* @brief Convenience alias.
*/
template
<
typename
T
>
using
enable_if_channel
=
std
::
enable_if
<
std
::
is_base_of
<
channel
,
T
>::
value
>
;
template
<
typename
T
,
typename
R
=
void
>
using
enable_if_channel
=
std
::
enable_if
<
std
::
is_base_of
<
channel
,
T
>::
value
,
R
>
;
}
// namespace cppa
...
...
cppa/context_switching_actor.hpp
View file @
04fc1827
...
...
@@ -34,7 +34,6 @@
#include <stack>
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/stacked.hpp"
#include "cppa/scheduled_actor.hpp"
...
...
@@ -64,22 +63,22 @@ class context_switching_actor : public extend<scheduled_actor,context_switching_
*/
context_switching_actor
(
std
::
function
<
void
()
>
fun
);
resume_result
resume
(
util
::
fiber
*
from
,
actor_ptr
&
next_job
);
//override
resume_result
resume
(
util
::
fiber
*
from
,
actor_ptr
&
next_job
);
scheduled_actor_type
impl_type
();
protected:
typedef
std
::
chrono
::
high_resolution_clock
::
time_point
timeout_type
;
timeout_type
init_timeout
(
const
util
::
duration
&
rel_time
);
detail
::
recursive_queue_node
*
await_message
();
mailbox_element
*
await_message
();
detail
::
recursive_queue_node
*
await_message
(
const
timeout_type
&
abs_time
);
mailbox_element
*
await_message
(
const
timeout_type
&
abs_time
);
private:
detail
::
recursive_queue_node
*
receive_node
();
// required by util::fiber
static
void
trampoline
(
void
*
_this
);
...
...
cppa/cow_tuple.hpp
View file @
04fc1827
...
...
@@ -86,6 +86,7 @@ class cow_tuple<Head, Tail...> {
public:
typedef
util
::
type_list
<
Head
,
Tail
...
>
types
;
typedef
cow_ptr
<
detail
::
abstract_tuple
>
cow_ptr_type
;
static
constexpr
size_t
num_elements
=
sizeof
...(
Tail
)
+
1
;
...
...
@@ -96,33 +97,24 @@ class cow_tuple<Head, Tail...> {
* @brief Initializes the cow_tuple with @p args.
* @param args Initialization values.
*/
template
<
typename
...
Arg
s
>
cow_tuple
(
const
Head
&
arg
0
,
Arg
s
&&
...
args
)
:
m_vals
(
new
data_type
(
arg
0
,
std
::
forward
<
Arg
s
>
(
args
)...))
{
}
template
<
typename
...
T
s
>
cow_tuple
(
const
Head
&
arg
,
T
s
&&
...
args
)
:
m_vals
(
new
data_type
(
arg
,
std
::
forward
<
T
s
>
(
args
)...))
{
}
/**
* @brief Initializes the cow_tuple with @p args.
* @param args Initialization values.
*/
template
<
typename
...
Arg
s
>
cow_tuple
(
Head
&&
arg
0
,
Arg
s
&&
...
args
)
:
m_vals
(
new
data_type
(
std
::
move
(
arg
0
),
std
::
forward
<
Arg
s
>
(
args
)...))
{
}
template
<
typename
...
T
s
>
cow_tuple
(
Head
&&
arg
,
T
s
&&
...
args
)
:
m_vals
(
new
data_type
(
std
::
move
(
arg
),
std
::
forward
<
T
s
>
(
args
)...))
{
}
cow_tuple
(
cow_tuple
&&
)
=
default
;
cow_tuple
(
const
cow_tuple
&
)
=
default
;
cow_tuple
&
operator
=
(
cow_tuple
&&
)
=
default
;
cow_tuple
&
operator
=
(
const
cow_tuple
&
)
=
default
;
inline
static
cow_tuple
from
(
cow_ptr_type
ptr
)
{
return
{
priv_ctor
{},
std
::
move
(
ptr
)};
}
inline
static
cow_tuple
from
(
cow_ptr_type
ptr
,
const
util
::
fixed_vector
<
size_t
,
num_elements
>&
mv
)
{
return
{
priv_ctor
{},
decorated_type
::
create
(
std
::
move
(
ptr
),
mv
)};
}
inline
static
cow_tuple
offset_subtuple
(
cow_ptr_type
ptr
,
size_t
offset
)
{
static
cow_tuple
offset_subtuple
(
cow_ptr_type
ptr
,
size_t
offset
)
{
CPPA_REQUIRE
(
offset
>
0
);
return
{
priv_ctor
{},
decorated_type
::
create
(
std
::
move
(
ptr
),
offset
)};
}
...
...
@@ -156,10 +148,23 @@ class cow_tuple<Head, Tail...> {
return
m_vals
->
type_at
(
p
);
}
/** @cond PRIVATE */
static
cow_tuple
from
(
cow_ptr_type
ptr
)
{
return
{
priv_ctor
{},
std
::
move
(
ptr
)};
}
static
cow_tuple
from
(
cow_ptr_type
ptr
,
const
util
::
fixed_vector
<
size_t
,
num_elements
>&
mv
)
{
return
{
priv_ctor
{},
decorated_type
::
create
(
std
::
move
(
ptr
),
mv
)};
}
inline
const
cow_ptr
<
detail
::
abstract_tuple
>&
vals
()
const
{
return
m_vals
;
}
/** @endcond */
};
template
<
typename
TypeList
>
...
...
@@ -206,10 +211,10 @@ typename util::at<N, Ts...>::type& get_ref(cow_tuple<Ts...>& tup) {
* @returns A cow_tuple object containing the values @p args.
* @relates cow_tuple
*/
template
<
typename
...
Arg
s
>
cow_tuple
<
typename
detail
::
strip_and_convert
<
Arg
s
>::
type
...
>
make_cow_tuple
(
Arg
s
&&
...
args
)
{
return
{
std
::
forward
<
Arg
s
>
(
args
)...};
template
<
typename
...
T
s
>
cow_tuple
<
typename
detail
::
strip_and_convert
<
T
s
>::
type
...
>
make_cow_tuple
(
T
s
&&
...
args
)
{
return
{
std
::
forward
<
T
s
>
(
args
)...};
}
/**
...
...
cppa/cppa.hpp
View file @
04fc1827
...
...
@@ -48,6 +48,7 @@
#include "cppa/behavior.hpp"
#include "cppa/announce.hpp"
#include "cppa/sb_actor.hpp"
#include "cppa/threaded.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
...
...
@@ -191,11 +192,20 @@
*
* @defgroup MessageHandling Message handling.
*
*
This is the beating heart of @p libcppa. Actor programming is all about
* message handling.
*
@brief This is the beating heart of @p libcppa. Actor programming is
*
all about
message handling.
*
* A message in @p libcppa is a n-tuple of values (with size >= 1). You can use
* almost every type in a messages.
* almost every type in a messages - as long as it is announced, i.e., known
* by libcppa's type system.
*
* @defgroup BlockingAPI Blocking API.
*
* @brief Blocking functions to receive messages.
*
* The blocking API of libcppa is intended to be used for migrating
* previously threaded applications. When writing new code, you should use
* ibcppas nonblocking become/unbecome API.
*
* @section Send Send messages
*
...
...
@@ -414,15 +424,14 @@ namespace cppa {
namespace
detail
{
template
<
typename
T
>
inline
void
send_impl
(
T
*
whom
,
any_tuple
&&
what
)
{
if
(
whom
)
self
->
send_message
(
whom
,
std
::
move
(
what
));
inline
void
send_impl
(
T
*
ptr
,
any_tuple
&&
arg
)
{
if
(
ptr
)
self
->
send_message
(
ptr
,
std
::
move
(
arg
));
}
template
<
typename
T
,
typename
...
Ts
>
inline
void
send_tpl_impl
(
T
*
whom
,
Ts
&&
...
what
)
{
inline
void
send_tpl_impl
(
T
*
ptr
,
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
if
(
whom
)
self
->
send_message
(
whom
,
make_any_tuple
(
std
::
forward
<
Ts
>
(
what
)...));
if
(
ptr
)
self
->
send_message
(
ptr
,
make_any_tuple
(
std
::
forward
<
Ts
>
(
args
)...));
}
}
// namespace detail
...
...
@@ -438,7 +447,7 @@ inline void send_tpl_impl(T* whom, Ts&&... what) {
* @param what Message content as tuple.
*/
template
<
class
C
,
typename
...
Ts
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
>::
type
inline
typename
enable_if_channel
<
C
>::
type
send_tuple
(
const
intrusive_ptr
<
C
>&
whom
,
any_tuple
what
)
{
detail
::
send_impl
(
whom
.
get
(),
std
::
move
(
what
));
}
...
...
@@ -450,9 +459,9 @@ send_tuple(const intrusive_ptr<C>& whom, any_tuple what) {
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
template
<
class
C
,
typename
...
Ts
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
>::
type
send
(
const
intrusive_ptr
<
C
>&
whom
,
Ts
&&
...
what
)
{
detail
::
send_tpl_impl
(
whom
.
get
(),
std
::
forward
<
Ts
>
(
what
)...);
inline
typename
enable_if_channel
<
C
>::
type
send
(
const
intrusive_ptr
<
C
>&
whom
,
Ts
&&
...
args
)
{
detail
::
send_tpl_impl
(
whom
.
get
(),
std
::
forward
<
Ts
>
(
args
)...);
}
/**
...
...
@@ -464,7 +473,7 @@ send(const intrusive_ptr<C>& whom, Ts&&... what) {
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
template
<
class
C
,
typename
...
Ts
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
>::
type
inline
typename
enable_if_channel
<
C
>::
type
send_tuple_as
(
const
actor_ptr
&
from
,
const
intrusive_ptr
<
C
>&
whom
,
any_tuple
what
)
{
if
(
whom
)
whom
->
enqueue
(
from
.
get
(),
std
::
move
(
what
));
}
...
...
@@ -478,7 +487,7 @@ send_tuple_as(const actor_ptr& from, const intrusive_ptr<C>& whom, any_tuple wha
* @pre <tt>sizeof...(Ts) > 0</tt>
*/
template
<
class
C
,
typename
...
Ts
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
>::
type
inline
typename
enable_if_channel
<
C
>::
type
send_as
(
const
actor_ptr
&
from
,
const
intrusive_ptr
<
C
>&
whom
,
Ts
&&
...
what
)
{
send_tuple_as
(
from
,
whom
,
make_any_tuple
(
std
::
forward
<
Ts
>
(
what
)...));
}
...
...
@@ -495,8 +504,7 @@ send_as(const actor_ptr& from, const intrusive_ptr<C>& whom, Ts&&... what) {
* @returns @p whom.
*/
template
<
class
C
>
inline
typename
std
::
enable_if
<
std
::
is_base_of
<
channel
,
C
>::
value
,
const
intrusive_ptr
<
C
>&
>::
type
inline
typename
enable_if_channel
<
C
,
const
intrusive_ptr
<
C
>&>::
type
operator
<<
(
const
intrusive_ptr
<
C
>&
whom
,
any_tuple
what
)
{
send_tuple
(
whom
,
std
::
move
(
what
));
return
whom
;
...
...
@@ -683,18 +691,20 @@ inline void delayed_reply(const std::chrono::duration<Rep, Period>& rtime,
delayed_reply_tuple
(
rtime
,
make_any_tuple
(
std
::
forward
<
Ts
>
(
what
)...));
}
/** @} */
/**
* @}
*/
// matches "send(this, ...)" and "send(self, ...)"
inline
void
send_tuple
(
local_actor
*
whom
,
any_tuple
what
)
{
inline
void
send_tuple
(
channel
*
whom
,
any_tuple
what
)
{
detail
::
send_impl
(
whom
,
std
::
move
(
what
));
}
template
<
typename
...
Ts
>
inline
void
send
(
local_actor
*
whom
,
Ts
&&
...
args
)
{
inline
void
send
(
channel
*
whom
,
Ts
&&
...
args
)
{
detail
::
send_tpl_impl
(
whom
,
std
::
forward
<
Ts
>
(
args
)...);
}
inline
const
self_type
&
operator
<<
(
const
self_type
&
s
,
any_tuple
what
)
{
detail
::
send_impl
(
s
.
get
(
),
std
::
move
(
what
));
detail
::
send_impl
(
s
tatic_cast
<
channel
*>
(
s
.
get
()
),
std
::
move
(
what
));
return
s
;
}
inline
actor_ptr
eval_sopts
(
spawn_options
opts
,
actor_ptr
ptr
)
{
...
...
@@ -732,7 +742,14 @@ actor_ptr spawn(Ts&&... args) {
*/
template
<
class
Impl
,
spawn_options
Options
=
no_spawn_options
,
typename
...
Ts
>
actor_ptr
spawn
(
Ts
&&
...
args
)
{
auto
rawptr
=
detail
::
memory
::
create
<
Impl
>
(
std
::
forward
<
Ts
>
(
args
)...);
static_assert
(
std
::
is_base_of
<
event_based_actor
,
Impl
>::
value
,
"Impl is not a derived type of event_based_actor"
);
scheduled_actor
*
rawptr
;
if
(
has_detach_flag
(
Options
))
{
typedef
typename
extend
<
Impl
>::
template
with
<
threaded
>
derived
;
rawptr
=
detail
::
memory
::
create
<
derived
>
(
std
::
forward
<
Ts
>
(
args
)...);
}
else
rawptr
=
detail
::
memory
::
create
<
Impl
>
(
std
::
forward
<
Ts
>
(
args
)...);
return
eval_sopts
(
Options
,
get_scheduler
()
->
exec
(
Options
,
rawptr
));
}
...
...
@@ -844,15 +861,24 @@ void shutdown(); // note: implemented in singleton_manager.cpp
*/
inline
void
quit_actor
(
const
actor_ptr
&
whom
,
std
::
uint32_t
reason
)
{
CPPA_REQUIRE
(
reason
!=
exit_reason
::
normal
);
send
(
whom
,
atom
(
"EXIT"
),
reason
);
send
(
whom
.
get
()
,
atom
(
"EXIT"
),
reason
);
}
/**
* @brief Sets the actor's behavior and discards the previous behavior
* unless {@link keep_behavior} is given as first argument.
*/
template
<
typename
...
Ts
>
inline
void
become
(
Ts
&&
...
args
)
{
self
->
become
(
std
::
forward
<
Ts
>
(
args
)...);
}
inline
void
unbecome
()
{
self
->
unbecome
();
}
/**
* @brief Returns to a previous behavior if available.
*/
inline
void
unbecome
()
{
self
->
unbecome
();
}
struct
actor_ostream
{
...
...
@@ -883,9 +909,11 @@ inline const actor_ostream& operator<<(const actor_ostream& o, const any_tuple&
}
template
<
typename
T
>
inline
typename
std
::
enable_if
<
!
std
::
is_convertible
<
T
,
std
::
string
>::
value
inline
typename
std
::
enable_if
<
!
std
::
is_convertible
<
T
,
std
::
string
>::
value
&&
!
std
::
is_convertible
<
T
,
any_tuple
>::
value
,
const
actor_ostream
&>::
type
const
actor_ostream
&
>::
type
operator
<<
(
const
actor_ostream
&
o
,
T
&&
arg
)
{
return
o
.
write
(
std
::
to_string
(
std
::
forward
<
T
>
(
arg
)));
}
...
...
cppa/detail/behavior_stack.hpp
View file @
04fc1827
...
...
@@ -40,7 +40,7 @@
#include "cppa/config.hpp"
#include "cppa/behavior.hpp"
#include "cppa/message_id.hpp"
#include "cppa/
detail/recursive_queue_node
.hpp"
#include "cppa/
mailbox_element
.hpp"
namespace
cppa
{
namespace
detail
{
...
...
@@ -54,14 +54,14 @@ class behavior_stack
behavior_stack
(
const
behavior_stack
&
)
=
delete
;
behavior_stack
&
operator
=
(
const
behavior_stack
&
)
=
delete
;
typedef
std
::
pair
<
behavior
,
message_id
_t
>
element_type
;
typedef
std
::
pair
<
behavior
,
message_id
>
element_type
;
public:
behavior_stack
()
=
default
;
// @pre expected_response.valid()
option
<
behavior
&>
sync_handler
(
message_id
_t
expected_response
);
option
<
behavior
&>
sync_handler
(
message_id
expected_response
);
// erases the last asynchronous message handler
void
pop_async_back
();
...
...
@@ -69,7 +69,7 @@ class behavior_stack
void
clear
();
// erases the synchronous response handler associated with @p rid
void
erase
(
message_id
_t
rid
)
{
void
erase
(
message_id
rid
)
{
erase_if
([
=
](
const
element_type
&
e
)
{
return
e
.
second
==
rid
;
});
}
...
...
@@ -81,7 +81,7 @@ class behavior_stack
}
inline
void
push_back
(
behavior
&&
what
,
message_id
_t
response_id
=
message_id_t
::
invalid
)
{
message_id
response_id
=
message_id
::
invalid
)
{
m_elements
.
emplace_back
(
std
::
move
(
what
),
response_id
);
}
...
...
@@ -90,7 +90,7 @@ class behavior_stack
}
template
<
class
Policy
,
class
Client
>
bool
invoke
(
Policy
&
policy
,
Client
*
client
,
recursive_queue_node
*
node
)
{
bool
invoke
(
Policy
&
policy
,
Client
*
client
,
mailbox_element
*
node
)
{
CPPA_REQUIRE
(
!
empty
());
CPPA_REQUIRE
(
client
!=
nullptr
);
CPPA_REQUIRE
(
node
!=
nullptr
);
...
...
@@ -122,7 +122,7 @@ class behavior_stack
template
<
class
Policy
,
class
Client
>
void
exec
(
Policy
&
policy
,
Client
*
client
)
{
while
(
!
empty
())
{
invoke
(
policy
,
client
,
client
->
await_message
(
));
invoke
(
policy
,
client
,
policy
.
fetch_message
(
client
));
cleanup
();
}
}
...
...
cppa/detail/default_uniform_type_info_impl.hpp
View file @
04fc1827
...
...
@@ -434,44 +434,44 @@ class default_uniform_type_info_impl : public util::abstract_uniform_type_info<T
// terminates recursion
inline
void
push_back
()
{
}
template
<
typename
R
,
class
C
,
typename
...
Arg
s
>
void
push_back
(
R
C
::*
memptr
,
Arg
s
&&
...
args
)
{
template
<
typename
R
,
class
C
,
typename
...
T
s
>
void
push_back
(
R
C
::*
memptr
,
T
s
&&
...
args
)
{
m_members
.
push_back
(
new_member_tinfo
(
memptr
));
push_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
push_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
// pr.first = member pointer
// pr.second = meta object to handle pr.first
template
<
typename
R
,
class
C
,
typename
...
Arg
s
>
template
<
typename
R
,
class
C
,
typename
...
T
s
>
void
push_back
(
const
std
::
pair
<
R
C
::*
,
util
::
abstract_uniform_type_info
<
R
>*>&
pr
,
Arg
s
&&
...
args
)
{
T
s
&&
...
args
)
{
m_members
.
push_back
(
new_member_tinfo
(
pr
.
first
,
unique_uti
(
pr
.
second
)));
push_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
push_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
// pr.first = getter / setter pair
// pr.second = meta object to handle pr.first
template
<
typename
GRes
,
typename
SRes
,
typename
SArg
,
typename
C
,
typename
...
Arg
s
>
template
<
typename
GRes
,
typename
SRes
,
typename
SArg
,
typename
C
,
typename
...
T
s
>
void
push_back
(
const
std
::
pair
<
GRes
(
C
::*
)()
const
,
SRes
(
C
::*
)(
SArg
)
>&
pr
,
Arg
s
&&
...
args
)
{
T
s
&&
...
args
)
{
m_members
.
push_back
(
new_member_tinfo
(
pr
.
first
,
pr
.
second
));
push_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
push_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
// pr.first = getter / setter pair
// pr.second = meta object to handle pr.first
template
<
typename
GRes
,
typename
SRes
,
typename
SArg
,
typename
C
,
typename
...
Arg
s
>
template
<
typename
GRes
,
typename
SRes
,
typename
SArg
,
typename
C
,
typename
...
T
s
>
void
push_back
(
const
std
::
pair
<
std
::
pair
<
GRes
(
C
::*
)()
const
,
SRes
(
C
::*
)(
SArg
)
>
,
util
::
abstract_uniform_type_info
<
typename
util
::
rm_ref
<
GRes
>::
type
>*>&
pr
,
Arg
s
&&
...
args
)
{
T
s
&&
...
args
)
{
m_members
.
push_back
(
new_member_tinfo
(
pr
.
first
.
first
,
pr
.
first
.
second
,
unique_uti
(
pr
.
second
)));
push_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
push_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
public:
template
<
typename
...
Arg
s
>
default_uniform_type_info_impl
(
Arg
s
&&
...
args
)
{
push_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
default_uniform_type_info_impl
(
T
s
&&
...
args
)
{
push_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
default_uniform_type_info_impl
()
{
...
...
cppa/detail/empty_tuple.hpp
View file @
04fc1827
...
...
@@ -59,8 +59,8 @@ class empty_tuple : public singleton_mixin<empty_tuple,abstract_tuple> {
empty_tuple
();
inline
void
initialize
()
/*override*/
{
ref
();
}
inline
void
destroy
()
/*override*/
{
deref
();
}
inline
void
initialize
()
{
ref
();
}
inline
void
destroy
()
{
deref
();
}
};
...
...
cppa/detail/event_based_actor_factory.hpp
View file @
04fc1827
...
...
@@ -47,10 +47,10 @@ class event_based_actor_impl : public event_based_actor {
public:
template
<
typename
...
Arg
s
>
event_based_actor_impl
(
InitFun
fun
,
CleanupFun
cfun
,
Arg
s
&&
...
args
)
template
<
typename
...
T
s
>
event_based_actor_impl
(
InitFun
fun
,
CleanupFun
cfun
,
T
s
&&
...
args
)
:
m_init
(
std
::
move
(
fun
)),
m_on_exit
(
std
::
move
(
cfun
))
,
m_members
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
}
,
m_members
(
std
::
forward
<
T
s
>
(
args
)...)
{
}
void
init
()
{
apply
(
m_init
);
}
...
...
@@ -71,9 +71,9 @@ class event_based_actor_impl : public event_based_actor {
f
(
args
...);
}
template
<
typename
F
,
typename
...
Arg
s
>
void
apply
(
F
&
f
,
Arg
s
...
args
)
{
apply
(
f
,
args
...,
&
get_ref
<
sizeof
...(
Arg
s
)
>
(
m_members
));
template
<
typename
F
,
typename
...
T
s
>
void
apply
(
F
&
f
,
T
s
...
args
)
{
apply
(
f
,
args
...,
&
get_ref
<
sizeof
...(
T
s
)
>
(
m_members
));
}
typedef
std
::
integral_constant
<
size_t
,
0
>
zero_t
;
...
...
@@ -102,11 +102,9 @@ class event_based_actor_factory {
event_based_actor_factory
(
InitFun
fun
,
CleanupFun
cfun
)
:
m_init
(
std
::
move
(
fun
)),
m_on_exit
(
std
::
move
(
cfun
))
{
}
template
<
typename
...
Args
>
actor_ptr
spawn
(
Args
&&
...
args
)
{
auto
ptr
=
memory
::
create
<
impl
>
(
m_init
,
m_on_exit
,
std
::
forward
<
Args
>
(
args
)...);
template
<
typename
...
Ts
>
actor_ptr
spawn
(
Ts
&&
...
args
)
{
auto
ptr
=
memory
::
create
<
impl
>
(
m_init
,
m_on_exit
,
std
::
forward
<
Ts
>
(
args
)...);
return
get_scheduler
()
->
exec
(
no_spawn_options
,
ptr
);
}
...
...
cppa/detail/get_behavior.hpp
View file @
04fc1827
...
...
@@ -43,7 +43,7 @@
namespace
cppa
{
namespace
detail
{
// default: <true, false, F>
template
<
bool
IsFunctionPtr
,
bool
HasArguments
,
typename
F
,
typename
...
Arg
s
>
template
<
bool
IsFunctionPtr
,
bool
HasArguments
,
typename
F
,
typename
...
T
s
>
class
ftor_behavior
:
public
scheduled_actor
{
F
m_fun
;
...
...
@@ -56,15 +56,15 @@ class ftor_behavior : public scheduled_actor {
};
template
<
typename
F
,
typename
...
Arg
s
>
class
ftor_behavior
<
true
,
true
,
F
,
Arg
s
...
>
:
public
scheduled_actor
{
template
<
typename
F
,
typename
...
T
s
>
class
ftor_behavior
<
true
,
true
,
F
,
T
s
...
>
:
public
scheduled_actor
{
static_assert
(
sizeof
...(
Args
)
>
0
,
"sizeof...(Arg
s) == 0"
);
static_assert
(
sizeof
...(
Ts
)
>
0
,
"sizeof...(T
s) == 0"
);
F
m_fun
;
typedef
typename
tdata_from_type_list
<
typename
util
::
tl_map
<
util
::
type_list
<
Arg
s
...
>
,
typename
util
::
tl_map
<
util
::
type_list
<
T
s
...
>
,
implicit_conversions
>::
type
>::
type
tdata_type
;
...
...
@@ -72,7 +72,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor {
public:
ftor_behavior
(
F
ptr
,
const
Arg
s
&
...
args
)
:
m_fun
(
ptr
),
m_args
(
args
...)
{
}
ftor_behavior
(
F
ptr
,
const
T
s
&
...
args
)
:
m_fun
(
ptr
),
m_args
(
args
...)
{
}
virtual
void
act
()
{
util
::
apply_args
(
m_fun
,
m_args
,
util
::
get_indices
(
m_args
));
...
...
@@ -95,15 +95,15 @@ class ftor_behavior<false, false, F> : public scheduled_actor {
};
template
<
typename
F
,
typename
...
Arg
s
>
class
ftor_behavior
<
false
,
true
,
F
,
Arg
s
...
>
:
public
scheduled_actor
{
template
<
typename
F
,
typename
...
T
s
>
class
ftor_behavior
<
false
,
true
,
F
,
T
s
...
>
:
public
scheduled_actor
{
static_assert
(
sizeof
...(
Args
)
>
0
,
"sizeof...(Arg
s) == 0"
);
static_assert
(
sizeof
...(
Ts
)
>
0
,
"sizeof...(T
s) == 0"
);
F
m_fun
;
typedef
typename
tdata_from_type_list
<
typename
util
::
tl_map
<
util
::
type_list
<
Arg
s
...
>
,
typename
util
::
tl_map
<
util
::
type_list
<
T
s
...
>
,
implicit_conversions
>::
type
>::
type
tdata_type
;
...
...
@@ -111,10 +111,10 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor {
public:
ftor_behavior
(
const
F
&
f
,
const
Arg
s
&
...
args
)
:
m_fun
(
f
),
m_args
(
args
...)
{
ftor_behavior
(
const
F
&
f
,
const
T
s
&
...
args
)
:
m_fun
(
f
),
m_args
(
args
...)
{
}
ftor_behavior
(
F
&&
f
,
const
Arg
s
&
...
args
)
:
m_fun
(
std
::
move
(
f
))
ftor_behavior
(
F
&&
f
,
const
T
s
&
...
args
)
:
m_fun
(
std
::
move
(
f
))
,
m_args
(
args
...)
{
}
...
...
@@ -143,31 +143,25 @@ scheduled_actor* get_behavior(std::integral_constant<bool,false>, F&& ftor) {
return
new
ftor_behavior
<
false
,
false
,
ftype
>
(
std
::
forward
<
F
>
(
ftor
));
}
template
<
typename
F
,
typename
Arg0
,
typename
...
Args
>
scheduled_actor
*
get_behavior
(
std
::
integral_constant
<
bool
,
true
>
,
F
fptr
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
static_assert
(
std
::
is_convertible
<
decltype
(
fptr
(
arg0
,
args
...)),
scheduled_actor
*>::
value
==
false
,
template
<
typename
F
,
typename
T
,
typename
...
Ts
>
scheduled_actor
*
get_behavior
(
std
::
true_type
,
F
fptr
,
const
T
&
arg
,
const
Ts
&
...
args
)
{
static_assert
(
std
::
is_convertible
<
decltype
(
fptr
(
arg
,
args
...)),
scheduled_actor
*>::
value
==
false
,
"Spawning a function returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that function?"
);
typedef
ftor_behavior
<
true
,
true
,
F
,
Arg0
,
Arg
s
...
>
impl
;
return
new
impl
(
fptr
,
arg
0
,
args
...);
typedef
ftor_behavior
<
true
,
true
,
F
,
T
,
T
s
...
>
impl
;
return
new
impl
(
fptr
,
arg
,
args
...);
}
template
<
typename
F
,
typename
Arg0
,
typename
...
Args
>
scheduled_actor
*
get_behavior
(
std
::
integral_constant
<
bool
,
false
>
,
F
ftor
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
static_assert
(
std
::
is_convertible
<
decltype
(
ftor
(
arg0
,
args
...)),
scheduled_actor
*>::
value
==
false
,
template
<
typename
F
,
typename
T
,
typename
...
Ts
>
scheduled_actor
*
get_behavior
(
std
::
false_type
,
F
ftor
,
const
T
&
arg
,
const
Ts
&
...
args
)
{
static_assert
(
std
::
is_convertible
<
decltype
(
ftor
(
arg
,
args
...)),
scheduled_actor
*>::
value
==
false
,
"Spawning a functor returning an actor_behavior? "
"Are you sure that you do not want to spawn the behavior "
"returned by that functor?"
);
typedef
typename
util
::
rm_ref
<
F
>::
type
ftype
;
typedef
ftor_behavior
<
false
,
true
,
ftype
,
Arg0
,
Arg
s
...
>
impl
;
return
new
impl
(
std
::
forward
<
F
>
(
ftor
),
arg
0
,
args
...);
typedef
ftor_behavior
<
false
,
true
,
ftype
,
T
,
T
s
...
>
impl
;
return
new
impl
(
std
::
forward
<
F
>
(
ftor
),
arg
,
args
...);
}
}
}
// namespace cppa::detail
...
...
cppa/detail/memory.hpp
View file @
04fc1827
...
...
@@ -33,6 +33,7 @@
#include <new>
#include <vector>
#include <memory>
#include <utility>
#include <typeinfo>
#include <iostream>
...
...
@@ -40,6 +41,8 @@
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
namespace
cppa
{
class
mailbox_element
;
}
namespace
cppa
{
namespace
detail
{
namespace
{
...
...
@@ -49,8 +52,6 @@ constexpr size_t s_cache_size = 10240; // cache about 10kb per thread
}
// namespace <anonymous>
class
recursive_queue_node
;
class
instance_wrapper
{
public:
...
...
@@ -158,6 +159,12 @@ class basic_memory_cache : public memory_cache {
};
struct
disposer
{
inline
void
operator
()(
memory_managed
*
ptr
)
const
{
ptr
->
request_deletion
();
}
};
class
memory
{
memory
()
=
delete
;
...
...
@@ -171,11 +178,11 @@ class memory {
* @brief Allocates storage, initializes a new object, and returns
* the new instance.
*/
template
<
typename
T
,
typename
...
Arg
s
>
static
inline
T
*
create
(
Arg
s
&&
...
args
)
{
template
<
typename
T
,
typename
...
T
s
>
static
T
*
create
(
T
s
&&
...
args
)
{
auto
mc
=
get_or_set_cache_map_entry
<
T
>
();
auto
p
=
mc
->
new_instance
();
auto
result
=
new
(
p
.
second
)
T
(
std
::
forward
<
Arg
s
>
(
args
)...);
auto
result
=
new
(
p
.
second
)
T
(
std
::
forward
<
T
s
>
(
args
)...);
result
->
outer_memory
=
p
.
first
;
return
result
;
}
...
...
@@ -198,12 +205,6 @@ class memory {
};
struct
disposer
{
inline
void
operator
()(
memory_managed
*
ptr
)
const
{
ptr
->
request_deletion
();
}
};
}
}
// namespace cppa::detail
#endif // CPPA_MEMORY_HPP
cppa/detail/projection.hpp
View file @
04fc1827
...
...
@@ -39,6 +39,7 @@
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/get_result_type.hpp"
#include "cppa/detail/tdata.hpp"
...
...
@@ -49,7 +50,7 @@ inline bool is_defined_at(Fun& f, Tuple& tup, util::int_list<Is...>) {
return
f
.
defined_at
(
get_cv_aware
<
Is
>
(
tup
)...);
}
template
<
typename
ProjectionFuns
,
typename
...
Arg
s
>
template
<
typename
ProjectionFuns
,
typename
...
T
s
>
struct
collected_args_tuple
{
typedef
typename
tdata_from_type_list
<
typename
util
::
tl_zip
<
...
...
@@ -59,7 +60,7 @@ struct collected_args_tuple {
util
::
rm_option
>::
type
,
typename
util
::
tl_map
<
util
::
type_list
<
Arg
s
...
>
,
util
::
type_list
<
T
s
...
>
,
mutable_gref_wrapped
>::
type
,
util
::
left_or_right
...
...
@@ -71,7 +72,7 @@ struct collected_args_tuple {
/**
* @brief Projection implemented by a set of functors.
*/
template
<
class
ProjectionFuns
,
typename
...
Arg
s
>
template
<
class
ProjectionFuns
,
typename
...
T
s
>
class
projection
{
public:
...
...
@@ -90,10 +91,10 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template
<
class
Part
ial
Fun
>
bool
invoke
(
Part
ialFun
&
fun
,
typename
PartialFun
::
result_type
&
result
,
Arg
s
...
args
)
const
{
typename
collected_args_tuple
<
ProjectionFuns
,
Arg
s
...
>::
type
pargs
;
if
(
collect
(
pargs
,
m_funs
,
std
::
forward
<
Arg
s
>
(
args
)...))
{
template
<
class
PartFun
>
bool
invoke
(
Part
Fun
&
fun
,
typename
PartFun
::
result_type
&
result
,
T
s
...
args
)
const
{
typename
collected_args_tuple
<
ProjectionFuns
,
T
s
...
>::
type
pargs
;
if
(
collect
(
pargs
,
m_funs
,
std
::
forward
<
T
s
>
(
args
)...))
{
auto
indices
=
util
::
get_indices
(
pargs
);
if
(
is_defined_at
(
fun
,
pargs
,
indices
))
{
result
=
util
::
apply_args
(
fun
,
pargs
,
indices
);
...
...
@@ -106,11 +107,11 @@ class projection {
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
template
<
class
Part
ial
Fun
>
bool
operator
()(
Part
ialFun
&
fun
,
Arg
s
...
args
)
const
{
typename
collected_args_tuple
<
ProjectionFuns
,
Arg
s
...
>::
type
pargs
;
template
<
class
PartFun
>
bool
operator
()(
Part
Fun
&
fun
,
T
s
...
args
)
const
{
typename
collected_args_tuple
<
ProjectionFuns
,
T
s
...
>::
type
pargs
;
auto
indices
=
util
::
get_indices
(
pargs
);
if
(
collect
(
pargs
,
m_funs
,
std
::
forward
<
Arg
s
>
(
args
)...))
{
if
(
collect
(
pargs
,
m_funs
,
std
::
forward
<
T
s
>
(
args
)...))
{
if
(
is_defined_at
(
fun
,
pargs
,
indices
))
{
util
::
apply_args
(
fun
,
pargs
,
indices
);
return
true
;
...
...
@@ -123,13 +124,13 @@ class projection {
* @brief Invokes @p fun with a projection of <tt>args...</tt> and stores
* the result of @p fun in @p result.
*/
template
<
class
Part
ial
Fun
>
inline
bool
operator
()(
Part
ialFun
&
fun
,
typename
PartialFun
::
result_type
&
result
,
Arg
s
...
args
)
const
{
template
<
class
PartFun
>
inline
bool
operator
()(
Part
Fun
&
fun
,
typename
PartFun
::
result_type
&
result
,
T
s
...
args
)
const
{
return
invoke
(
fun
,
result
,
args
...);
}
template
<
class
Part
ial
Fun
>
inline
bool
operator
()(
Part
ialFun
&
fun
,
const
util
::
void_type
&
,
Arg
s
...
args
)
const
{
template
<
class
PartFun
>
inline
bool
operator
()(
Part
Fun
&
fun
,
const
util
::
void_type
&
,
T
s
...
args
)
const
{
return
(
*
this
)(
fun
,
args
...);
}
...
...
@@ -166,11 +167,11 @@ class projection {
return
true
;
}
template
<
class
TData
,
class
Trans
,
typename
T0
,
typename
...
T
s
>
template
<
class
TData
,
class
Trans
,
typename
U
,
typename
...
U
s
>
static
inline
bool
collect
(
TData
&
td
,
const
Trans
&
tr
,
T0
&&
arg0
,
T
s
&&
...
args
)
{
return
store
(
td
.
head
,
fetch
(
tr
.
head
,
std
::
forward
<
T0
>
(
arg0
)))
&&
collect
(
td
.
tail
(),
tr
.
tail
(),
std
::
forward
<
T
s
>
(
args
)...);
U
&&
arg
,
U
s
&&
...
args
)
{
return
store
(
td
.
head
,
fetch
(
tr
.
head
,
std
::
forward
<
U
>
(
arg
)))
&&
collect
(
td
.
tail
(),
tr
.
tail
(),
std
::
forward
<
U
s
>
(
args
)...);
}
fun_container
m_funs
;
...
...
@@ -186,8 +187,8 @@ class projection<util::empty_type_list> {
projection
(
const
tdata
<>&
)
{
}
projection
(
const
projection
&
)
=
default
;
template
<
class
Part
ial
Fun
>
bool
operator
()(
Part
ial
Fun
&
fun
)
const
{
template
<
class
PartFun
>
bool
operator
()(
PartFun
&
fun
)
const
{
if
(
fun
.
defined_at
())
{
fun
();
return
true
;
...
...
@@ -195,8 +196,8 @@ class projection<util::empty_type_list> {
return
false
;
}
template
<
class
Part
ial
Fun
>
bool
operator
()(
Part
ial
Fun
&
fun
,
const
util
::
void_type
&
)
const
{
template
<
class
PartFun
>
bool
operator
()(
PartFun
&
fun
,
const
util
::
void_type
&
)
const
{
if
(
fun
.
defined_at
())
{
fun
();
return
true
;
...
...
@@ -204,8 +205,8 @@ class projection<util::empty_type_list> {
return
false
;
}
template
<
class
Part
ial
Fun
>
bool
operator
()(
Part
ialFun
&
fun
,
typename
Partial
Fun
::
result_type
&
res
)
const
{
template
<
class
PartFun
>
bool
operator
()(
Part
Fun
&
fun
,
typename
Part
Fun
::
result_type
&
res
)
const
{
if
(
fun
.
defined_at
())
{
res
=
fun
();
return
true
;
...
...
@@ -218,9 +219,9 @@ class projection<util::empty_type_list> {
template
<
class
ProjectionFuns
,
class
List
>
struct
projection_from_type_list
;
template
<
class
ProjectionFuns
,
typename
...
Arg
s
>
struct
projection_from_type_list
<
ProjectionFuns
,
util
::
type_list
<
Arg
s
...
>
>
{
typedef
projection
<
ProjectionFuns
,
Arg
s
...
>
type
;
template
<
class
ProjectionFuns
,
typename
...
T
s
>
struct
projection_from_type_list
<
ProjectionFuns
,
util
::
type_list
<
T
s
...
>
>
{
typedef
projection
<
ProjectionFuns
,
T
s
...
>
type
;
};
}
}
// namespace cppa::detail
...
...
cppa/detail/ptype_to_type.hpp
View file @
04fc1827
...
...
@@ -35,35 +35,33 @@
#include "cppa/primitive_type.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/wrapped.hpp"
namespace
cppa
{
namespace
detail
{
// maps the primitive_type PT to the corresponding type
template
<
primitive_type
PT
>
struct
ptype_to_type
:
// signed integers
util
::
if_else_c
<
PT
==
pt_int8
,
std
::
int8_t
,
util
::
if_else_c
<
PT
==
pt_int16
,
std
::
int16_t
,
util
::
if_else_c
<
PT
==
pt_int32
,
std
::
int32_t
,
util
::
if_else_c
<
PT
==
pt_int64
,
std
::
int64_t
,
util
::
if_else_c
<
PT
==
pt_uint8
,
std
::
uint8_t
,
// unsigned integers
util
::
if_else_c
<
PT
==
pt_uint16
,
std
::
uint16_t
,
util
::
if_else_c
<
PT
==
pt_uint32
,
std
::
uint32_t
,
util
::
if_else_c
<
PT
==
pt_uint64
,
std
::
uint64_t
,
// floating points
util
::
if_else_c
<
PT
==
pt_float
,
float
,
util
::
if_else_c
<
PT
==
pt_double
,
double
,
util
::
if_else_c
<
PT
==
pt_long_double
,
long
double
,
// strings
util
::
if_else_c
<
PT
==
pt_u8string
,
std
::
string
,
util
::
if_else_c
<
PT
==
pt_u16string
,
std
::
u16string
,
util
::
if_else_c
<
PT
==
pt_u32string
,
std
::
u32string
,
// default case
void
>
>
>
>
>
>
>
>
>
>
>
>
>
>
{
};
struct
ptype_to_type
:
util
::
wrapped
<
void
>
{
};
// integer types
template
<
>
struct
ptype_to_type
<
pt_int8
>
:
util
::
wrapped
<
std
::
int8_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_uint8
>
:
util
::
wrapped
<
std
::
uint8_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_int16
>
:
util
::
wrapped
<
std
::
int16_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_uint16
>
:
util
::
wrapped
<
std
::
uint16_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_int32
>
:
util
::
wrapped
<
std
::
int32_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_uint32
>
:
util
::
wrapped
<
std
::
uint32_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_int64
>
:
util
::
wrapped
<
std
::
int64_t
>
{
};
template
<
>
struct
ptype_to_type
<
pt_uint64
>
:
util
::
wrapped
<
std
::
uint64_t
>
{
};
// floating points
template
<
>
struct
ptype_to_type
<
pt_float
>
:
util
::
wrapped
<
float
>
{
};
template
<
>
struct
ptype_to_type
<
pt_double
>
:
util
::
wrapped
<
double
>
{
};
template
<
>
struct
ptype_to_type
<
pt_long_double
>
:
util
::
wrapped
<
long
double
>
{
};
// strings
template
<
>
struct
ptype_to_type
<
pt_u8string
>
:
util
::
wrapped
<
std
::
string
>
{
};
template
<
>
struct
ptype_to_type
<
pt_u16string
>
:
util
::
wrapped
<
std
::
u16string
>
{
};
template
<
>
struct
ptype_to_type
<
pt_u32string
>
:
util
::
wrapped
<
std
::
u32string
>
{
};
}
}
// namespace cppa::detail
...
...
cppa/detail/receive_loop_helper.hpp
View file @
04fc1827
...
...
@@ -51,24 +51,15 @@ struct receive_while_helper {
template
<
typename
S
>
receive_while_helper
(
S
&&
stmt
)
:
m_stmt
(
std
::
forward
<
S
>
(
stmt
))
{
}
void
operator
()(
behavior
&
bhvr
)
{
template
<
typename
...
Ts
>
void
operator
()(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"operator() requires at least one argument"
);
behavior
tmp
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
local_actor
*
sptr
=
self
;
while
(
m_stmt
())
sptr
->
dequeue
(
bhvr
);
while
(
m_stmt
())
sptr
->
dequeue
(
tmp
);
}
void
operator
()(
partial_function
&
fun
)
{
local_actor
*
sptr
=
self
;
while
(
m_stmt
())
sptr
->
dequeue
(
fun
);
}
template
<
typename
Arg0
,
typename
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
(
*
this
)(
tmp
);
}
};
template
<
typename
T
>
...
...
@@ -81,21 +72,11 @@ class receive_for_helper {
receive_for_helper
(
T
&
first
,
const
T
&
last
)
:
begin
(
first
),
end
(
last
)
{
}
void
operator
()(
behavior
&
bhvr
)
{
template
<
typename
...
Ts
>
void
operator
()(
Ts
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
local_actor
*
sptr
=
self
;
for
(
;
begin
!=
end
;
++
begin
)
sptr
->
dequeue
(
bhvr
);
}
void
operator
()(
partial_function
&
fun
)
{
local_actor
*
sptr
=
self
;
for
(
;
begin
!=
end
;
++
begin
)
sptr
->
dequeue
(
fun
);
}
template
<
typename
Arg0
,
typename
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
(
*
this
)(
tmp
);
for
(
;
begin
!=
end
;
++
begin
)
sptr
->
dequeue
(
tmp
);
}
};
...
...
@@ -106,10 +87,7 @@ class do_receive_helper {
public:
template
<
typename
...
Args
>
do_receive_helper
(
Args
&&
...
args
)
:
m_bhvr
(
match_expr_convert
(
std
::
forward
<
Args
>
(
args
)...))
{
}
inline
do_receive_helper
(
behavior
&&
bhvr
)
:
m_bhvr
(
std
::
move
(
bhvr
))
{
}
do_receive_helper
(
do_receive_helper
&&
)
=
default
;
...
...
cppa/detail/receive_policy.hpp
View file @
04fc1827
...
...
@@ -41,10 +41,10 @@
#include "cppa/to_string.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace
cppa
{
namespace
detail
{
...
...
@@ -62,8 +62,8 @@ class receive_policy {
public:
typedef
recursive_queue_node
*
pointer
;
typedef
std
::
unique_ptr
<
recursive_queue_node
,
disposer
>
smart_pointer
;
typedef
mailbox_element
*
pointer
;
typedef
std
::
unique_ptr
<
mailbox_element
,
disposer
>
smart_pointer
;
enum
handle_message_result
{
hm_timeout_msg
,
...
...
@@ -76,7 +76,7 @@ class receive_policy {
template
<
class
Client
,
class
Fun
>
bool
invoke_from_cache
(
Client
*
client
,
Fun
&
fun
,
message_id
_t
awaited_response
=
message_id_t
()
)
{
message_id
awaited_response
=
message_id
{}
)
{
std
::
integral_constant
<
receive_policy_flag
,
Client
::
receive_flag
>
policy
;
auto
i
=
m_cache
.
begin
();
auto
e
=
m_cache
.
end
();
...
...
@@ -108,7 +108,7 @@ class receive_policy {
bool
invoke
(
Client
*
client
,
pointer
node_ptr
,
Fun
&
fun
,
message_id
_t
awaited_response
=
message_id_t
())
{
message_id
awaited_response
=
message_id
())
{
smart_pointer
node
(
node_ptr
);
std
::
integral_constant
<
receive_policy_flag
,
Client
::
receive_flag
>
policy
;
switch
(
this
->
handle_message
(
client
,
node
.
get
(),
fun
,
...
...
@@ -176,7 +176,7 @@ class receive_policy {
}
template
<
class
Client
>
void
receive
(
Client
*
client
,
behavior
&
bhvr
,
message_id
_t
mid
)
{
void
receive
(
Client
*
client
,
behavior
&
bhvr
,
message_id
mid
)
{
CPPA_REQUIRE
(
mid
.
is_response
());
if
(
!
invoke_from_cache
(
client
,
bhvr
,
mid
))
{
if
(
bhvr
.
timeout
().
valid
())
{
...
...
@@ -195,12 +195,17 @@ class receive_policy {
}
}
template
<
class
Client
>
mailbox_element
*
fetch_message
(
Client
*
client
)
{
return
client
->
await_message
();
}
private:
typedef
typename
rp_flag
<
rp_nestable
>::
type
nestable
;
typedef
typename
rp_flag
<
rp_sequential
>::
type
sequential
;
std
::
list
<
std
::
unique_ptr
<
recursive_queue_node
,
disposer
>
>
m_cache
;
std
::
list
<
std
::
unique_ptr
<
mailbox_element
,
disposer
>
>
m_cache
;
template
<
class
Client
>
inline
void
handle_timeout
(
Client
*
client
,
behavior
&
bhvr
)
{
...
...
@@ -231,7 +236,7 @@ class receive_policy {
template
<
class
Client
>
filter_result
filter_msg
(
Client
*
client
,
pointer
node
)
{
const
any_tuple
&
msg
=
node
->
msg
;
auto
m
essage_
id
=
node
->
mid
;
auto
mid
=
node
->
mid
;
auto
&
arr
=
detail
::
static_types_array
<
atom_value
,
std
::
uint32_t
>::
arr
;
if
(
msg
.
size
()
==
2
&&
msg
.
type_at
(
0
)
==
arr
[
0
]
...
...
@@ -239,7 +244,7 @@ class receive_policy {
auto
v0
=
msg
.
get_as
<
atom_value
>
(
0
);
auto
v1
=
msg
.
get_as
<
std
::
uint32_t
>
(
1
);
if
(
v0
==
atom
(
"EXIT"
))
{
CPPA_REQUIRE
(
!
m
essage_
id
.
valid
());
CPPA_REQUIRE
(
!
mid
.
valid
());
if
(
client
->
m_trap_exit
==
false
)
{
if
(
v1
!=
exit_reason
::
normal
)
{
client
->
quit
(
v1
);
...
...
@@ -249,7 +254,7 @@ class receive_policy {
}
}
else
if
(
v0
==
atom
(
"SYNC_TOUT"
))
{
CPPA_REQUIRE
(
!
m
essage_
id
.
valid
());
CPPA_REQUIRE
(
!
mid
.
valid
());
return
client
->
waits_for_timeout
(
v1
)
?
timeout_message
:
expired_timeout_message
;
}
...
...
@@ -257,11 +262,11 @@ class receive_policy {
else
if
(
msg
.
size
()
==
1
&&
msg
.
type_at
(
0
)
==
arr
[
0
]
&&
msg
.
get_as
<
atom_value
>
(
0
)
==
atom
(
"TIMEOUT"
)
&&
m
essage_
id
.
is_response
())
{
&&
mid
.
is_response
())
{
return
timeout_response_message
;
}
if
(
m
essage_
id
.
is_response
())
{
return
(
client
->
awaits
(
m
essage_
id
))
?
sync_response
if
(
mid
.
is_response
())
{
return
(
client
->
awaits
(
mid
))
?
sync_response
:
expired_sync_response
;
}
return
ordinary_message
;
...
...
@@ -340,7 +345,7 @@ class receive_policy {
handle_message_result
handle_message
(
Client
*
client
,
pointer
node
,
Fun
&
fun
,
message_id
_t
awaited_response
,
message_id
awaited_response
,
Policy
policy
)
{
bool
handle_sync_failure_on_mismatch
=
true
;
if
(
hm_should_skip
(
node
,
policy
))
{
...
...
cppa/detail/scheduled_actor_dummy.hpp
View file @
04fc1827
...
...
@@ -38,14 +38,13 @@ namespace cppa { namespace detail {
struct
scheduled_actor_dummy
:
scheduled_actor
{
scheduled_actor_dummy
();
void
enqueue
(
const
actor_ptr
&
,
any_tuple
);
void
sync_enqueue
(
const
actor_ptr
&
,
message_id
_t
,
any_tuple
);
void
sync_enqueue
(
const
actor_ptr
&
,
message_id
,
any_tuple
);
resume_result
resume
(
util
::
fiber
*
,
actor_ptr
&
);
void
quit
(
std
::
uint32_t
);
void
dequeue
(
behavior
&
);
void
dequeue
(
partial_function
&
);
void
dequeue_response
(
behavior
&
,
message_id_t
);
void
dequeue_response
(
behavior
&
,
message_id
);
void
do_become
(
behavior
&&
,
bool
);
void
become_waiting_for
(
behavior
&&
,
message_id_t
);
void
become_waiting_for
(
behavior
,
message_id
);
bool
has_behavior
();
scheduled_actor_type
impl_type
();
};
...
...
cppa/detail/singleton_mixin.hpp
View file @
04fc1827
...
...
@@ -50,8 +50,8 @@ class singleton_mixin : public Base {
protected:
template
<
typename
...
Arg
s
>
singleton_mixin
(
Args
&&
...
args
)
:
Base
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
}
template
<
typename
...
T
s
>
singleton_mixin
(
Ts
&&
...
args
)
:
Base
(
std
::
forward
<
T
s
>
(
args
)...)
{
}
virtual
~
singleton_mixin
()
{
}
...
...
cppa/detail/sync_request_bouncer.hpp
View file @
04fc1827
...
...
@@ -37,7 +37,7 @@
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/
detail/recursive_queue_node
.hpp"
#include "cppa/
mailbox_element
.hpp"
namespace
cppa
{
namespace
detail
{
...
...
@@ -45,7 +45,7 @@ struct sync_request_bouncer {
std
::
uint32_t
rsn
;
constexpr
sync_request_bouncer
(
std
::
uint32_t
r
)
:
rsn
(
r
==
exit_reason
::
not_exited
?
exit_reason
::
normal
:
r
)
{
}
inline
void
operator
()(
const
actor_ptr
&
sender
,
const
message_id
_t
&
mid
)
const
{
inline
void
operator
()(
const
actor_ptr
&
sender
,
const
message_id
&
mid
)
const
{
CPPA_REQUIRE
(
rsn
!=
exit_reason
::
not_exited
);
if
(
mid
.
is_request
()
&&
sender
!=
nullptr
)
{
actor_ptr
nobody
;
...
...
@@ -54,7 +54,7 @@ struct sync_request_bouncer {
make_any_tuple
(
atom
(
"EXITED"
),
rsn
));
}
}
inline
void
operator
()(
const
recursive_queue_node
&
e
)
const
{
inline
void
operator
()(
const
mailbox_element
&
e
)
const
{
(
*
this
)(
e
.
sender
.
get
(),
e
.
mid
);
}
};
...
...
cppa/detail/tdata.hpp
View file @
04fc1827
...
...
@@ -42,6 +42,7 @@
#include "cppa/util/wrapped.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
...
...
@@ -113,6 +114,11 @@ struct unbox_ref<std::reference_wrapper<T> > {
typedef
typename
std
::
remove_const
<
T
>::
type
type
;
};
template
<
typename
T
>
struct
unbox_ref
<
util
::
rebindable_reference
<
T
>
>
{
typedef
typename
std
::
remove_const
<
T
>::
type
type
;
};
/*
* "enhanced" std::tuple
*/
...
...
@@ -136,9 +142,9 @@ struct tdata<> {
constexpr
tdata
()
{
}
// swallow any number of additional boxed or void_type arguments silently
template
<
typename
...
Arg
s
>
tdata
(
Arg
s
&&
...)
{
typedef
util
::
type_list
<
typename
util
::
rm_ref
<
Arg
s
>::
type
...
>
incoming
;
template
<
typename
...
T
s
>
tdata
(
T
s
&&
...)
{
typedef
util
::
type_list
<
typename
util
::
rm_ref
<
T
s
>::
type
...
>
incoming
;
typedef
typename
util
::
tl_filter_not_type
<
incoming
,
tdata
>::
type
iargs
;
static_assert
(
util
::
tl_forall
<
iargs
,
boxed_or_void
>::
value
,
"Additional unboxed arguments provided"
);
...
...
@@ -239,9 +245,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
typedef
Head
head_type
;
typedef
tdata
<
Tail
...
>
tail_type
;
typedef
typename
util
::
if_else_c
<
(
sizeof
...(
Tail
)
>
0
),
typedef
typename
std
::
conditional
<
(
sizeof
...(
Tail
)
>
0
),
typename
tdata
<
Tail
...
>::
back_type
,
util
::
wrapped
<
Head
>
Head
>::
type
back_type
;
...
...
@@ -252,10 +259,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
tdata
(
const
Head
&
arg
)
:
super
(),
head
(
arg
)
{
}
tdata
(
Head
&&
arg
)
:
super
(),
head
(
std
::
move
(
arg
))
{
}
template
<
typename
Arg0
,
typename
Arg1
,
typename
...
Arg
s
>
tdata
(
Arg0
&&
arg0
,
Arg1
&&
arg1
,
Arg
s
&&
...
args
)
:
super
(
std
::
forward
<
Arg1
>
(
arg1
),
std
::
forward
<
Arg
s
>
(
args
)...)
,
head
(
td_filter
<
Head
>
(
std
::
forward
<
Arg
0
>
(
arg0
)))
{
template
<
typename
T0
,
typename
T1
,
typename
...
T
s
>
tdata
(
T0
&&
arg0
,
T1
&&
arg1
,
T
s
&&
...
args
)
:
super
(
std
::
forward
<
T1
>
(
arg1
),
std
::
forward
<
T
s
>
(
args
)...)
,
head
(
td_filter
<
Head
>
(
std
::
forward
<
T
0
>
(
arg0
)))
{
}
tdata
(
const
tdata
&
)
=
default
;
...
...
@@ -285,10 +292,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
return
*
this
;
}
template
<
typename
Arg0
,
typename
...
Arg
s
>
inline
void
set
(
Arg0
&&
arg0
,
Arg
s
&&
...
args
)
{
head
=
std
::
forward
<
Arg0
>
(
arg0
);
super
::
set
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
T
,
typename
...
T
s
>
inline
void
set
(
T
&&
arg
,
T
s
&&
...
args
)
{
head
=
std
::
forward
<
T
>
(
arg
);
super
::
set
(
std
::
forward
<
T
s
>
(
args
)...);
}
inline
size_t
size
()
const
{
return
num_elements
;
}
...
...
@@ -317,10 +324,8 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
case
2
:
return
ptr_to
(
super
::
super
::
head
);
case
3
:
return
ptr_to
(
super
::
super
::
super
::
head
);
case
4
:
return
ptr_to
(
super
::
super
::
super
::
super
::
head
);
case
5
:
return
ptr_to
(
super
::
super
::
super
::
super
::
super
::
head
);
default:
return
super
::
at
(
p
-
1
);
default:
return
super
::
super
::
super
::
super
::
super
::
at
(
p
-
5
);
}
//return (p == 0) ? ptr_to(head) : super::at(p - 1);
}
inline
void
*
mutable_at
(
size_t
p
)
{
...
...
@@ -335,40 +340,47 @@ struct tdata<Head, Tail...> : tdata<Tail...> {
# else
return
const_cast
<
void
*>
(
at
(
p
));
# endif
}
inline
const
uniform_type_info
*
type_at
(
size_t
p
)
const
{
return
(
p
==
0
)
?
utype_of
(
head
)
:
super
::
type_at
(
p
-
1
);
CPPA_REQUIRE
(
p
<
num_elements
);
switch
(
p
)
{
case
0
:
return
utype_of
(
head
);
case
1
:
return
utype_of
(
super
::
head
);
case
2
:
return
utype_of
(
super
::
super
::
head
);
case
3
:
return
utype_of
(
super
::
super
::
super
::
head
);
case
4
:
return
utype_of
(
super
::
super
::
super
::
super
::
head
);
default:
return
super
::
super
::
super
::
super
::
super
::
type_at
(
p
-
5
);
}
}
Head
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
{
Head
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
{
return
head
;
}
template
<
size_t
Pos
>
back_type
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
{
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
back_type
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
{
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
return
super
::
_back
(
token
);
}
back_type
&
back
()
{
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
return
_back
(
token
);
}
const
Head
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
const
{
const
Head
&
_back
(
std
::
integral_constant
<
size_t
,
0
>
)
const
{
return
head
;
}
template
<
size_t
Pos
>
const
back_type
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
const
{
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
const
back_type
&
_back
(
std
::
integral_constant
<
size_t
,
Pos
>
)
const
{
std
::
integral_constant
<
size_t
,
Pos
-
1
>
token
;
return
super
::
_back
(
token
);
}
const
back_type
&
back
()
const
{
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
std
::
integral_constant
<
size_t
,
sizeof
...(
Tail
)
>
token
;
return
_back
(
token
);
}
};
...
...
@@ -398,35 +410,39 @@ struct tdata_upcast_helper<0, Head, Tail...> {
template
<
typename
T
>
struct
tdata_from_type_list
;
template
<
typename
...
T
>
struct
tdata_from_type_list
<
util
::
type_list
<
T
...
>>
{
typedef
tdata
<
T
...
>
type
;
template
<
typename
...
T
s
>
struct
tdata_from_type_list
<
util
::
type_list
<
T
s
...
>>
{
typedef
tdata
<
T
s
...
>
type
;
};
template
<
typename
...
T
>
inline
void
collect_tdata
(
tdata
<
T
...
>&
)
{
}
template
<
typename
T
,
typename
U
>
inline
void
rebind_value
(
T
&
lhs
,
U
&
rhs
)
{
lhs
=
rhs
;
}
template
<
typename
Storage
,
typename
...
Args
>
void
collect_tdata
(
Storage
&
storage
,
const
tdata
<>&
,
const
Args
&
...
arg
s
)
{
collect_tdata
(
storage
,
args
...
);
template
<
typename
T
,
typename
U
>
inline
void
rebind_value
(
util
::
rebindable_reference
<
T
>&
lhs
,
U
&
rh
s
)
{
lhs
.
rebind
(
rhs
);
}
template
<
typename
Storage
,
typename
Arg0
,
typename
...
Args
>
void
collect_tdata
(
Storage
&
storage
,
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
storage
.
head
=
arg0
.
head
;
collect_tdata
(
storage
.
tail
(),
arg0
.
tail
(),
args
...);
template
<
typename
...
Ts
>
inline
void
rebind_tdata
(
tdata
<
Ts
...
>&
)
{
}
template
<
typename
...
Ts
,
typename
...
Vs
>
void
rebind_tdata
(
tdata
<
Ts
...
>&
td
,
const
tdata
<>&
,
const
Vs
&
...
args
)
{
rebind_tdata
(
td
,
args
...);
}
template
<
typename
...
Ts
,
typename
...
Us
,
typename
...
Vs
>
void
rebind_tdata
(
tdata
<
Ts
...
>&
td
,
const
tdata
<
Us
...
>&
arg
,
const
Vs
&
...
args
)
{
rebind_value
(
td
.
head
,
arg
.
head
);
rebind_tdata
(
td
.
tail
(),
arg
.
tail
(),
args
...);
}
}
}
// namespace cppa::detail
namespace
cppa
{
template
<
typename
...
Args
>
detail
::
tdata
<
typename
detail
::
implicit_conversions
<
typename
util
::
rm_ref
<
Args
>::
type
>::
type
...
>
mk_tdata
(
Args
&&
...
args
)
{
return
{
std
::
forward
<
Args
>
(
args
)...};
}
template
<
size_t
N
,
typename
...
Ts
>
const
typename
util
::
at
<
N
,
Ts
...
>::
type
&
get
(
const
detail
::
tdata
<
Ts
...
>&
tv
)
{
static_assert
(
N
<
sizeof
...(
Ts
),
"N >= tv.size()"
);
...
...
cppa/detail/tuple_vals.hpp
View file @
04fc1827
...
...
@@ -58,9 +58,8 @@ class tuple_vals : public abstract_tuple {
tuple_vals
(
const
tuple_vals
&
)
=
default
;
template
<
typename
...
Args
>
tuple_vals
(
Args
&&
...
args
)
:
super
(
false
)
,
m_data
(
std
::
forward
<
Args
>
(
args
)...)
{
}
template
<
typename
...
Us
>
tuple_vals
(
Us
&&
...
args
)
:
super
(
false
),
m_data
(
std
::
forward
<
Us
>
(
args
)...)
{
}
const
void
*
native_data
()
const
{
return
&
m_data
;
...
...
cppa/detail/tuple_view.hpp
View file @
04fc1827
...
...
@@ -31,7 +31,9 @@
#ifndef CPPA_TUPLE_VIEW_HPP
#define CPPA_TUPLE_VIEW_HPP
#include "cppa/util/static_foreach.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
...
...
@@ -58,7 +60,7 @@ class tuple_view : public abstract_tuple {
public:
typedef
tdata
<
Ts
*
...
>
data_type
;
typedef
tdata
<
util
::
rebindable_reference
<
Ts
>
...
>
data_type
;
typedef
types_array
<
Ts
...
>
element_types
;
...
...
@@ -83,20 +85,17 @@ class tuple_view : public abstract_tuple {
}
abstract_tuple
*
copy
()
const
{
auto
result
=
new
tuple_vals
<
Ts
...
>
;
tuple_view_copy_helper
f
{
result
};
util
::
static_foreach
<
0
,
sizeof
...(
Ts
)
>::
_
(
m_data
,
f
);
return
result
;
return
new
tuple_vals
<
Ts
...
>
{
m_data
};
}
const
void
*
at
(
size_t
pos
)
const
{
CPPA_REQUIRE
(
pos
<
size
());
return
m_data
.
at
(
pos
);
return
m_data
.
at
(
pos
)
.
get_ptr
()
;
}
void
*
mutable_at
(
size_t
pos
)
{
CPPA_REQUIRE
(
pos
<
size
());
return
m_data
.
mutable_at
(
pos
);
return
m_data
.
mutable_at
(
pos
)
.
get_ptr
()
;
}
const
uniform_type_info
*
type_at
(
size_t
pos
)
const
{
...
...
@@ -114,6 +113,8 @@ class tuple_view : public abstract_tuple {
static
types_array
<
Ts
...
>
m_types
;
tuple_view
(
const
data_type
&
data
)
:
m_data
(
data
)
{
}
};
template
<
typename
...
Ts
>
...
...
cppa/detail/type_to_ptype.hpp
View file @
04fc1827
...
...
@@ -37,59 +37,43 @@
#include "cppa/primitive_type.hpp"
namespace
cppa
{
namespace
detail
{
// if (IfStmt == true) ptype = PT; else ptype = Else::ptype;
template
<
bool
IfStmt
,
primitive_type
PT
,
class
Else
>
struct
if_else_ptype_c
{
static
const
primitive_type
ptype
=
PT
;
};
#include "cppa/util/rm_ref.hpp"
template
<
primitive_type
PT
,
class
Else
>
struct
if_else_ptype_c
<
false
,
PT
,
Else
>
{
static
const
primitive_type
ptype
=
Else
::
ptype
;
};
// if (Stmt::value == true) ptype = FT; else ptype = Else::ptype;
template
<
class
Stmt
,
primitive_type
PT
,
class
Else
>
struct
if_else_ptype
:
if_else_ptype_c
<
Stmt
::
value
,
PT
,
Else
>
{
};
namespace
cppa
{
namespace
detail
{
template
<
primitive_type
PT
>
struct
wrapped_ptype
{
static
const
primitive_type
ptype
=
PT
;
};
// maps type T the the corresponding fundamental_type
template
<
typename
T
>
struct
type_to_ptype_impl
:
// signed integers
if_else_ptype
<
std
::
is_same
<
T
,
std
::
int8_t
>
,
pt_int8
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
int16_t
>
,
pt_int16
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
int32_t
>
,
pt_int32
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
int64_t
>
,
pt_int64
,
// unsigned integers
if_else_ptype
<
std
::
is_same
<
T
,
std
::
uint8_t
>
,
pt_uint8
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
uint16_t
>
,
pt_uint16
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
uint32_t
>
,
pt_uint32
,
if_else_ptype
<
std
::
is_same
<
T
,
std
::
uint64_t
>
,
pt_uint64
,
// floating points
if_else_ptype
<
std
::
is_same
<
T
,
float
>
,
pt_float
,
if_else_ptype
<
std
::
is_same
<
T
,
double
>
,
pt_double
,
if_else_ptype
<
std
::
is_same
<
T
,
long
double
>
,
pt_long_double
,
// strings
if_else_ptype
<
std
::
is_convertible
<
T
,
std
::
string
>
,
pt_u8string
,
if_else_ptype
<
std
::
is_convertible
<
T
,
std
::
u16string
>
,
pt_u16string
,
if_else_ptype
<
std
::
is_convertible
<
T
,
std
::
u32string
>
,
pt_u32string
,
// default case
wrapped_ptype
<
pt_null
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
{
struct
type_to_ptype_impl
{
static
constexpr
primitive_type
ptype
=
std
::
is_convertible
<
T
,
std
::
string
>::
value
?
pt_u8string
:
(
std
::
is_convertible
<
T
,
std
::
u16string
>::
value
?
pt_u16string
:
(
std
::
is_convertible
<
T
,
std
::
u32string
>::
value
?
pt_u32string
:
pt_null
));
};
template
<
typename
T
>
struct
type_to_ptype
{
typedef
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>::
type
>::
type
type
;
static
const
primitive_type
ptype
=
type_to_ptype_impl
<
type
>::
ptype
;
// integers
template
<
>
struct
type_to_ptype_impl
<
std
::
int8_t
>
:
wrapped_ptype
<
pt_int8
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
uint8_t
>
:
wrapped_ptype
<
pt_uint8
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
int16_t
>
:
wrapped_ptype
<
pt_int16
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
uint16_t
>
:
wrapped_ptype
<
pt_uint16
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
int32_t
>
:
wrapped_ptype
<
pt_int32
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
uint32_t
>
:
wrapped_ptype
<
pt_uint32
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
int64_t
>
:
wrapped_ptype
<
pt_int64
>
{
};
template
<
>
struct
type_to_ptype_impl
<
std
::
uint64_t
>
:
wrapped_ptype
<
pt_uint64
>
{
};
// floating points
template
<
>
struct
type_to_ptype_impl
<
float
>
:
wrapped_ptype
<
pt_float
>
{
};
template
<
>
struct
type_to_ptype_impl
<
double
>
:
wrapped_ptype
<
pt_double
>
{
};
template
<
>
struct
type_to_ptype_impl
<
long
double
>
:
wrapped_ptype
<
pt_long_double
>
{
};
};
template
<
typename
T
>
struct
type_to_ptype
:
type_to_ptype_impl
<
typename
util
::
rm_ref
<
T
>::
type
>
{
};
}
}
// namespace cppa::detail
...
...
cppa/detail/value_guard.hpp
View file @
04fc1827
...
...
@@ -42,30 +42,20 @@
namespace
cppa
{
namespace
detail
{
template
<
bool
IsFun
,
typename
T
>
struct
vg_fwd_
{
static
inline
const
T
&
_
(
const
T
&
arg
)
{
return
arg
;
}
static
inline
T
&&
_
(
T
&&
arg
)
{
return
std
::
move
(
arg
);
}
static
inline
T
&
_
(
T
&
arg
)
{
return
arg
;
}
};
// 'absorbs' callables and instances of `anything`
template
<
typename
T
>
struct
vg_fwd_
<
true
,
T
>
{
template
<
typename
Arg
>
static
inline
util
::
void_type
_
(
Arg
&&
)
{
return
{};
}
};
const
T
&
vg_fwd
(
const
T
&
arg
,
typename
std
::
enable_if
<
not
util
::
is_callable
<
T
>::
value
>::
type
*
=
0
)
{
return
arg
;
}
template
<
>
struct
vg_fwd_
<
false
,
anything
>
{
static
inline
util
::
void_type
_
(
const
anything
&
)
{
return
{};
}
};
inline
util
::
void_type
vg_fwd
(
const
anything
&
)
{
return
{};
}
// absorbs callables and instances of `anything`
template
<
typename
T
>
struct
vg_fwd
:
vg_fwd_
<
util
::
is_callable
<
typename
util
::
rm_ref
<
T
>::
type
>::
value
,
typename
util
::
rm_ref
<
T
>::
type
>
{
};
util
::
void_type
vg_fwd
(
const
T
&
,
typename
std
::
enable_if
<
util
::
is_callable
<
T
>::
value
>::
type
*
=
0
)
{
return
{};
}
template
<
typename
T
>
struct
vg_cmp
{
...
...
@@ -91,11 +81,11 @@ class value_guard {
value_guard
()
=
default
;
value_guard
(
const
value_guard
&
)
=
default
;
template
<
typename
...
Arg
s
>
value_guard
(
const
Args
&
...
args
)
:
m_args
(
vg_fwd
<
Args
>::
_
(
args
)...)
{
}
template
<
typename
...
T
s
>
value_guard
(
const
Ts
&
...
args
)
:
m_args
(
vg_fwd
(
args
)...)
{
}
template
<
typename
...
Arg
s
>
inline
bool
operator
()(
const
Arg
s
&
...
args
)
const
{
template
<
typename
...
T
s
>
inline
bool
operator
()(
const
T
s
&
...
args
)
const
{
return
_eval
(
m_args
.
head
,
m_args
.
tail
(),
args
...);
}
...
...
@@ -117,17 +107,17 @@ class value_guard {
return
true
;
}
template
<
typename
T
0
,
typename
Arg0
,
typename
...
Arg
s
>
static
inline
bool
_eval
(
const
T
0
&
head
,
const
tdata
<>&
,
const
Arg0
&
arg0
,
const
Arg
s
&
...)
{
return
cmp
(
head
,
arg
0
);
template
<
typename
T
,
typename
U
,
typename
...
U
s
>
static
inline
bool
_eval
(
const
T
&
head
,
const
tdata
<>&
,
const
U
&
arg
,
const
U
s
&
...)
{
return
cmp
(
head
,
arg
);
}
template
<
typename
T0
,
typename
T1
,
typename
...
Ts
,
typename
Arg0
,
typename
...
Arg
s
>
typename
U
,
typename
...
U
s
>
static
inline
bool
_eval
(
const
T0
&
head
,
const
tdata
<
T1
,
Ts
...
>&
tail
,
const
Arg0
&
arg0
,
const
Arg
s
&
...
args
)
{
return
cmp
(
head
,
arg
0
)
&&
_eval
(
tail
.
head
,
tail
.
tail
(),
args
...);
const
U
&
arg
,
const
U
s
&
...
args
)
{
return
cmp
(
head
,
arg
)
&&
_eval
(
tail
.
head
,
tail
.
tail
(),
args
...);
}
};
...
...
cppa/either.hpp
deleted
100644 → 0
View file @
16cb9399
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_EITHER_HPP
#define CPPA_EITHER_HPP
#include <new>
#include <utility>
#include <type_traits>
#include "cppa/config.hpp"
namespace
cppa
{
/**
* @brief Represents either a @p Left or a @p Right.
*/
template
<
class
Left
,
class
Right
>
class
either
{
//static_assert( std::is_convertible<Left, Right>::value == false
// && std::is_convertible<Right, Left>::value == false,
// "Left is not allowed to be convertible to Right");
public:
typedef
Left
left_type
;
typedef
Right
right_type
;
/**
* @brief Default constructor, creates a @p Left.
*/
either
()
:
m_is_left
(
true
)
{
new
(
&
m_left
)
left_type
();
}
/**
* @brief Creates a @p Left from @p value.
*/
either
(
const
left_type
&
value
)
:
m_is_left
(
true
)
{
cr_left
(
value
);
}
/**
* @brief Creates a @p Left from @p value.
*/
either
(
Left
&&
value
)
:
m_is_left
(
true
)
{
cr_left
(
std
::
move
(
value
));
}
/**
* @brief Creates a @p Right from @p value.
*/
either
(
const
right_type
&
value
)
:
m_is_left
(
false
)
{
cr_right
(
value
);
}
/**
* @brief Creates a @p Right from @p value.
*/
either
(
Right
&&
value
)
:
m_is_left
(
false
)
{
cr_right
(
std
::
move
(
value
));
}
either
(
const
either
&
other
)
:
m_is_left
(
other
.
m_is_left
)
{
if
(
other
.
m_is_left
)
cr_left
(
other
.
m_left
);
else
cr_right
(
other
.
m_right
);
}
either
(
either
&&
other
)
:
m_is_left
(
other
.
m_is_left
)
{
if
(
other
.
m_is_left
)
cr_left
(
std
::
move
(
other
.
m_left
));
else
cr_right
(
std
::
move
(
other
.
m_right
));
}
~
either
()
{
destroy
();
}
either
&
operator
=
(
const
either
&
other
)
{
if
(
m_is_left
==
other
.
m_is_left
)
{
if
(
m_is_left
)
m_left
=
other
.
m_left
;
else
m_right
=
other
.
m_right
;
}
else
{
destroy
();
m_is_left
=
other
.
m_is_left
;
if
(
other
.
m_is_left
)
cr_left
(
other
.
m_left
);
else
cr_right
(
other
.
m_right
);
}
return
*
this
;
}
either
&
operator
=
(
either
&&
other
)
{
if
(
m_is_left
==
other
.
m_is_left
)
{
if
(
m_is_left
)
m_left
=
std
::
move
(
other
.
m_left
);
else
m_right
=
std
::
move
(
other
.
m_right
);
}
else
{
destroy
();
m_is_left
=
other
.
m_is_left
;
if
(
other
.
m_is_left
)
cr_left
(
std
::
move
(
other
.
m_left
));
else
cr_right
(
std
::
move
(
other
.
m_right
));
}
return
*
this
;
}
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline
bool
is_left
()
const
{
return
m_is_left
;
}
/**
* @brief Returns @p true if this is a @p Left; otherwise @p false.
*/
inline
bool
is_right
()
const
{
return
!
m_is_left
;
}
/**
* @brief Returns this @p either as a @p Left.
*/
inline
Left
&
left
()
{
CPPA_REQUIRE
(
m_is_left
);
return
m_left
;
}
/**
* @brief Returns this @p either as a @p Left.
*/
inline
const
left_type
&
left
()
const
{
CPPA_REQUIRE
(
m_is_left
);
return
m_left
;
}
/**
* @brief Returns this @p either as a @p Right.
*/
inline
Right
&
right
()
{
CPPA_REQUIRE
(
!
m_is_left
);
return
m_right
;
}
/**
* @brief Returns this @p either as a @p Right.
*/
inline
const
right_type
&
right
()
const
{
CPPA_REQUIRE
(
!
m_is_left
);
return
m_right
;
}
template
<
typename
F
>
void
apply
(
const
F
&
fun
)
{
if
(
is_left
())
fun
(
left
());
else
fun
(
right
());
}
template
<
typename
F
>
void
apply
(
const
F
&
fun
)
const
{
if
(
is_left
())
fun
(
left
());
else
fun
(
right
());
}
template
<
typename
Result
,
typename
F
>
Result
inspect
(
const
F
&
fun
)
{
if
(
is_left
())
return
fun
(
left
());
else
return
fun
(
right
());
}
template
<
typename
Result
,
typename
F
>
Result
inspect
(
const
F
&
fun
)
const
{
if
(
is_left
())
return
fun
(
left
());
else
return
fun
(
right
());
}
private:
bool
m_is_left
;
union
{
left_type
m_left
;
right_type
m_right
;
};
void
destroy
()
{
if
(
m_is_left
)
m_left
.
~
Left
();
else
m_right
.
~
Right
();
}
template
<
typename
L
>
void
cr_left
(
L
&&
value
)
{
new
(
&
m_left
)
left_type
(
std
::
forward
<
L
>
(
value
));
}
template
<
typename
R
>
void
cr_right
(
R
&&
value
)
{
new
(
&
m_right
)
right_type
(
std
::
forward
<
R
>
(
value
));
}
};
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
if
(
lhs
.
is_left
()
==
rhs
.
is_left
())
{
if
(
lhs
.
is_left
())
return
lhs
.
left
()
==
rhs
.
left
();
else
return
lhs
.
right
()
==
rhs
.
right
();
}
return
false
;
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>&
lhs
,
const
Left
&
rhs
)
{
return
lhs
.
is_left
()
&&
lhs
.
left
()
==
rhs
;
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
Left
&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
return
rhs
==
lhs
;
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
either
<
Left
,
Right
>&
lhs
,
const
Right
&
rhs
)
{
return
lhs
.
is_right
()
&&
lhs
.
right
()
==
rhs
;
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
==
(
const
Right
&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
return
rhs
==
lhs
;
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>&
lhs
,
const
Left
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
Left
&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
either
<
Left
,
Right
>&
lhs
,
const
Right
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
/** @relates either */
template
<
typename
Left
,
typename
Right
>
bool
operator
!=
(
const
Right
&
lhs
,
const
either
<
Left
,
Right
>&
rhs
)
{
return
!
(
rhs
==
lhs
);
}
}
// namespace cppa
#endif // CPPA_EITHER_HPP
cppa/enable_weak_ptr.hpp
View file @
04fc1827
...
...
@@ -60,9 +60,9 @@ class enable_weak_ptr : public Base {
typedef
enable_weak_ptr
combined_type
;
template
<
typename
...
Arg
s
>
enable_weak_ptr
(
Arg
s
&&
...
args
)
:
Base
(
std
::
forward
<
Arg
s
>
(
args
)...)
template
<
typename
...
T
s
>
enable_weak_ptr
(
T
s
&&
...
args
)
:
Base
(
std
::
forward
<
T
s
>
(
args
)...)
,
m_anchor
(
new
weak_ptr_anchor
(
this
))
{
}
void
request_deletion
()
{
...
...
cppa/event_based_actor.hpp
View file @
04fc1827
...
...
@@ -37,7 +37,6 @@
#include <vector>
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/behavior.hpp"
#include "cppa/scheduled_actor.hpp"
...
...
@@ -60,19 +59,14 @@ class event_based_actor : public scheduled_actor {
* @brief Finishes execution with exit reason
* {@link exit_reason::unallowed_function_call unallowed_function_call}.
*/
void
dequeue
(
behavior
&
);
//override
void
dequeue
(
behavior
&
);
/**
* @copydoc dequeue(behavior&)
*/
void
dequeue
(
partial_function
&
);
//override
void
dequeue
_response
(
behavior
&
,
message_id
);
/**
* @copydoc dequeue(behavior&)
*/
void
dequeue_response
(
behavior
&
,
message_id_t
);
resume_result
resume
(
util
::
fiber
*
,
actor_ptr
&
);
//override
resume_result
resume
(
util
::
fiber
*
,
actor_ptr
&
);
/**
* @brief Initializes the actor.
...
...
@@ -97,9 +91,10 @@ class event_based_actor : public scheduled_actor {
* @brief Provokes a compiler error to ensure that an event-based actor
* does not accidently uses receive() instead of become().
*/
template
<
typename
...
Args
>
void
receive
(
Args
&&
...)
{
static_assert
((
sizeof
...(
Args
)
+
1
)
<
1
,
template
<
typename
...
Ts
>
void
receive
(
Ts
&&
...)
{
// this asssertion always fails
static_assert
((
sizeof
...(
Ts
)
+
1
)
<
1
,
"You shall not use receive in an event-based actor. "
"Use become() instead."
);
}
...
...
@@ -107,30 +102,32 @@ class event_based_actor : public scheduled_actor {
/**
* @brief Provokes a compiler error.
*/
template
<
typename
...
Arg
s
>
void
receive_loop
(
Arg
s
&&
...
args
)
{
receive
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
void
receive_loop
(
T
s
&&
...
args
)
{
receive
(
std
::
forward
<
T
s
>
(
args
)...);
}
/**
* @brief Provokes a compiler error.
*/
template
<
typename
...
Arg
s
>
void
receive_while
(
Arg
s
&&
...
args
)
{
receive
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
void
receive_while
(
T
s
&&
...
args
)
{
receive
(
std
::
forward
<
T
s
>
(
args
)...);
}
/**
* @brief Provokes a compiler error.
*/
template
<
typename
...
Arg
s
>
void
do_receive
(
Arg
s
&&
...
args
)
{
receive
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
void
do_receive
(
T
s
&&
...
args
)
{
receive
(
std
::
forward
<
T
s
>
(
args
)...);
}
void
do_become
(
behavior
&&
bhvr
,
bool
discard_old
);
void
become_waiting_for
(
behavior
&&
bhvr
,
message_id_t
mf
);
void
become_waiting_for
(
behavior
bhvr
,
message_id
mf
);
detail
::
receive_policy
m_recv_policy
;
private:
...
...
@@ -154,8 +151,6 @@ class event_based_actor : public scheduled_actor {
}
}
detail
::
receive_policy
m_policy
;
};
}
// namespace cppa
...
...
cppa/extend.hpp
View file @
04fc1827
...
...
@@ -56,12 +56,13 @@ struct extend_helper<B,D,M,Ms...> : extend_helper<B,M<D,B>,Ms...> { };
*
* Mixins in libcppa always have two template parameters: base type and
* derived type. This allows mixins to make use of the curiously recurring
* template pattern (CRTP).
* template pattern (CRTP). However, if none of the used mixins use CRTP,
* the second template argument can ignored (it is then set to Base).
*/
template
<
class
Base
,
class
Derived
>
template
<
class
Base
,
class
Derived
=
Base
>
struct
extend
{
/**
* @brief
An alias for the result
type.
* @brief
Identifies the combined
type.
*/
template
<
template
<
class
,
class
>
class
...
Mixins
>
using
with
=
typename
detail
::
extend_helper
<
Derived
,
Base
,
Mixins
...
>::
type
;
...
...
cppa/guard_expr.hpp
View file @
04fc1827
...
...
@@ -44,6 +44,7 @@
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/tdata.hpp"
...
...
@@ -96,8 +97,8 @@ struct guard_expr {
guard_expr
(
const
guard_expr
&
)
=
default
;
guard_expr
(
guard_expr
&&
other
)
:
m_args
(
std
::
move
(
other
.
m_args
))
{
}
template
<
typename
...
Arg
s
>
bool
operator
()(
const
Arg
s
&
...
args
)
const
;
template
<
typename
...
T
s
>
bool
operator
()(
const
T
s
&
...
args
)
const
;
};
...
...
@@ -109,58 +110,16 @@ struct guard_expr {
SubMacro (greater_eq_op, >=) SubMacro (equal_op, ==) \
SubMacro (not_equal_op, !=)
template
<
typename
T
>
struct
ge_mutable_reference_wrapper
{
T
*
value
;
ge_mutable_reference_wrapper
()
:
value
(
nullptr
)
{
}
ge_mutable_reference_wrapper
(
T
&&
)
=
delete
;
ge_mutable_reference_wrapper
(
T
&
vref
)
:
value
(
&
vref
)
{
}
ge_mutable_reference_wrapper
(
const
ge_mutable_reference_wrapper
&
)
=
default
;
ge_mutable_reference_wrapper
&
operator
=
(
T
&
vref
)
{
value
=
&
vref
;
return
*
this
;
}
ge_mutable_reference_wrapper
&
operator
=
(
const
ge_mutable_reference_wrapper
&
)
=
default
;
T
&
get
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
operator
T
&
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
};
template
<
typename
T
>
struct
ge_reference_wrapper
{
const
T
*
value
;
ge_reference_wrapper
(
T
&&
)
=
delete
;
ge_reference_wrapper
()
:
value
(
nullptr
)
{
}
ge_reference_wrapper
(
const
T
&
val_ref
)
:
value
(
&
val_ref
)
{
}
ge_reference_wrapper
(
const
ge_reference_wrapper
&
)
=
default
;
ge_reference_wrapper
&
operator
=
(
const
T
&
vref
)
{
value
=
&
vref
;
return
*
this
;
}
ge_reference_wrapper
&
operator
=
(
const
ge_reference_wrapper
&
)
=
default
;
const
T
&
get
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
operator
const
T
&
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
};
// support use of gref(BooleanVariable) as receive loop 'guard'
template
<
>
struct
ge_reference_wrapper
<
bool
>
{
const
bool
*
value
;
ge_reference_wrapper
(
bool
&&
)
=
delete
;
ge_reference_wrapper
(
const
bool
&
val_ref
)
:
value
(
&
val_ref
)
{
}
ge_reference_wrapper
(
const
ge_reference_wrapper
&
)
=
default
;
ge_reference_wrapper
&
operator
=
(
const
ge_reference_wrapper
&
)
=
default
;
const
bool
&
get
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
operator
const
bool
&
()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
bool
operator
()()
const
{
CPPA_REQUIRE
(
value
!=
0
);
return
*
value
;
}
};
/**
* @brief Creates a reference wrapper similar to std::reference_wrapper<const T>
* that could be used in guard expressions or to enforce lazy evaluation.
*/
template
<
typename
T
>
ge_reference_wrapper
<
T
>
gref
(
const
T
&
value
)
{
return
{
value
};
}
util
::
rebindable_reference
<
const
T
>
gref
(
const
T
&
value
)
{
return
{
value
};
}
//ge_reference_wrapper<T> gref(const T& value) { return {value}; }
// bind utility for placeholders
...
...
@@ -385,7 +344,7 @@ template<typename T, class Tuple>
struct
ge_unbound
{
typedef
T
type
;
};
template
<
typename
T
,
class
Tuple
>
struct
ge_unbound
<
ge_reference_wrapper
<
T
>
,
Tuple
>
{
typedef
T
type
;
};
struct
ge_unbound
<
util
::
rebindable_reference
<
const
T
>
,
Tuple
>
{
typedef
T
type
;
};
template
<
typename
T
,
class
Tuple
>
struct
ge_unbound
<
std
::
reference_wrapper
<
T
>
,
Tuple
>
{
typedef
T
type
;
};
...
...
@@ -418,7 +377,7 @@ struct is_ge_type<guard_placeholder<X> > {
};
template
<
typename
T
>
struct
is_ge_type
<
ge_reference_wrapper
<
T
>
>
{
struct
is_ge_type
<
util
::
rebindable_reference
<
T
>
>
{
static
constexpr
bool
value
=
true
;
};
...
...
@@ -553,7 +512,7 @@ inline const T& ge_resolve(const Tuple&, const std::reference_wrapper<const T>&
}
template
<
class
Tuple
,
typename
T
>
inline
const
T
&
ge_resolve
(
const
Tuple
&
,
const
ge_reference_wrapper
<
T
>&
value
)
{
inline
const
T
&
ge_resolve
(
const
Tuple
&
,
const
util
::
rebindable_reference
<
const
T
>&
value
)
{
return
value
.
get
();
}
...
...
@@ -644,19 +603,19 @@ auto ge_resolve(const Tuple& tup,
return
ge_eval
<
OP
>
(
tup
,
ge
.
m_args
.
first
,
ge
.
m_args
.
second
);
}
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
Arg
s
>
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
T
s
>
auto
ge_invoke_step2
(
const
guard_expr
<
OP
,
First
,
Second
>&
ge
,
const
detail
::
tdata
<
Arg
s
...
>&
tup
)
->
typename
ge_result
<
OP
,
First
,
Second
,
detail
::
tdata
<
Arg
s
...
>>::
type
{
const
detail
::
tdata
<
T
s
...
>&
tup
)
->
typename
ge_result
<
OP
,
First
,
Second
,
detail
::
tdata
<
T
s
...
>>::
type
{
return
ge_eval
<
OP
>
(
tup
,
ge
.
m_args
.
first
,
ge
.
m_args
.
second
);
}
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
Arg
s
>
template
<
operator_id
OP
,
typename
First
,
typename
Second
,
typename
...
T
s
>
auto
ge_invoke
(
const
guard_expr
<
OP
,
First
,
Second
>&
ge
,
const
Arg
s
&
...
args
)
const
T
s
&
...
args
)
->
typename
ge_result
<
OP
,
First
,
Second
,
detail
::
tdata
<
std
::
reference_wrapper
<
const
Arg
s
>
...
>>::
type
{
detail
::
tdata
<
std
::
reference_wrapper
<
const
Arg
s
>
...
>
tup
{
args
...};
detail
::
tdata
<
std
::
reference_wrapper
<
const
T
s
>
...
>>::
type
{
detail
::
tdata
<
std
::
reference_wrapper
<
const
T
s
>
...
>
tup
{
args
...};
return
ge_invoke_step2
(
ge
,
tup
);
}
...
...
@@ -664,9 +623,9 @@ template<class GuardExpr>
struct
ge_invoke_helper
{
const
GuardExpr
&
ge
;
ge_invoke_helper
(
const
GuardExpr
&
arg
)
:
ge
(
arg
)
{
}
template
<
typename
...
Arg
s
>
bool
operator
()(
Arg
s
&&
...
args
)
const
{
return
ge_invoke
(
ge
,
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
bool
operator
()(
T
s
&&
...
args
)
const
{
return
ge_invoke
(
ge
,
std
::
forward
<
T
s
>
(
args
)...);
}
};
...
...
@@ -687,10 +646,10 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
>::
type
result_type
;
using
namespace
util
;
typename
if_else
<
std
::
is_same
<
typename
TupleTypes
::
back
,
anything
>
,
typename
std
::
conditional
<
std
::
is_same
<
typename
TupleTypes
::
back
,
anything
>::
value
,
TupleTypes
,
wrapped
<
typename
tl_push_back
<
TupleTypes
,
anything
>::
type
>
wrapped
<
typename
tl_push_back
<
TupleTypes
,
anything
>::
type
>
>::
type
cast_token
;
auto
x
=
tuple_cast
(
tup
,
cast_token
);
...
...
@@ -700,8 +659,8 @@ ge_invoke_any(const guard_expr<OP, First, Second>& ge,
}
template
<
operator_id
OP
,
typename
First
,
typename
Second
>
template
<
typename
...
Arg
s
>
bool
guard_expr
<
OP
,
First
,
Second
>::
operator
()(
const
Arg
s
&
...
args
)
const
{
template
<
typename
...
T
s
>
bool
guard_expr
<
OP
,
First
,
Second
>::
operator
()(
const
T
s
&
...
args
)
const
{
static_assert
(
std
::
is_same
<
decltype
(
ge_invoke
(
*
this
,
args
...)),
bool
>::
value
,
"guard expression does not return a boolean"
);
return
ge_invoke
(
*
this
,
args
...);
...
...
@@ -711,17 +670,17 @@ bool guard_expr<OP, First, Second>::operator()(const Args&... args) const {
template
<
typename
T
>
struct
gref_wrapped
{
typedef
ge_reference_wrapper
<
typename
util
::
rm_ref
<
T
>::
type
>
type
;
typedef
util
::
rebindable_reference
<
const
typename
util
::
rm_ref
<
T
>::
type
>
type
;
};
template
<
typename
T
>
struct
mutable_gref_wrapped
{
typedef
ge_mutable_reference_wrapper
<
T
>
type
;
typedef
util
::
rebindable_reference
<
T
>
type
;
};
template
<
typename
T
>
struct
mutable_gref_wrapped
<
T
&>
{
typedef
ge_mutable_reference_wrapper
<
T
>
type
;
typedef
util
::
rebindable_reference
<
T
>
type
;
};
// finally ...
...
...
cppa/intrusive_ptr.hpp
View file @
04fc1827
...
...
@@ -36,7 +36,6 @@
#include <stdexcept>
#include <type_traits>
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/util/comparable.hpp"
namespace
cppa
{
...
...
@@ -73,12 +72,6 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
intrusive_ptr
(
const
intrusive_ptr
&
other
)
{
set_ptr
(
other
.
get
());
}
template
<
typename
Y
,
typename
Ref
,
typename
Deref
>
intrusive_ptr
(
intrusive_fwd_ptr
<
Y
,
Ref
,
Deref
>
other
)
:
m_ptr
(
other
.
release
())
{
static_assert
(
std
::
is_convertible
<
Y
*
,
T
*>::
value
,
"Y* is not assignable to T*"
);
}
template
<
typename
Y
>
intrusive_ptr
(
intrusive_ptr
<
Y
>
other
)
:
m_ptr
(
other
.
release
())
{
static_assert
(
std
::
is_convertible
<
Y
*
,
T
*>::
value
,
...
...
@@ -120,9 +113,9 @@ class intrusive_ptr : util::comparable<intrusive_ptr<T> >,
set_ptr
(
new_value
);
}
template
<
typename
...
Arg
s
>
void
emplace
(
Arg
s
&&
...
args
)
{
reset
(
new
T
(
std
::
forward
<
Arg
s
>
(
args
)...));
template
<
typename
...
T
s
>
void
emplace
(
T
s
&&
...
args
)
{
reset
(
new
T
(
std
::
forward
<
T
s
>
(
args
)...));
}
intrusive_ptr
&
operator
=
(
pointer
ptr
)
{
...
...
@@ -214,9 +207,9 @@ inline bool operator!=(const intrusive_ptr<X>& lhs, const intrusive_ptr<Y>& rhs)
* @brief Constructs an object of type T which must be a derived type
* of {@link ref_counted} and wraps it in an {@link intrusive_ptr}.
*/
template
<
typename
T
,
typename
...
Arg
s
>
intrusive_ptr
<
T
>
make_counted
(
Arg
s
&&
...
args
)
{
return
{
new
T
(
std
::
forward
<
Arg
s
>
(
args
)...)};
template
<
typename
T
,
typename
...
T
s
>
intrusive_ptr
<
T
>
make_counted
(
T
s
&&
...
args
)
{
return
{
new
T
(
std
::
forward
<
T
s
>
(
args
)...)};
}
}
// namespace cppa
...
...
cppa/local_actor.hpp
View file @
04fc1827
...
...
@@ -42,14 +42,14 @@
#include "cppa/message_id.hpp"
#include "cppa/match_expr.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/memory_cached.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/response_handle.hpp"
#include "cppa/partial_function.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/memory_cached.hpp"
#include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace
cppa
{
...
...
@@ -85,15 +85,10 @@ constexpr keep_behavior_t keep_behavior = keep_behavior_t{};
* @brief Base class for local running Actors.
* @extends actor
*/
class
local_actor
:
public
extend
<
actor
,
local_actor
>::
with
<
memory_cached
>
{
class
local_actor
:
public
extend
<
actor
>::
with
<
memory_cached
>
{
typedef
combined_type
super
;
friend
class
scheduler
;
friend
class
detail
::
memory
;
friend
class
detail
::
receive_policy
;
template
<
typename
>
friend
class
detail
::
basic_memory_cache
;
public:
/**
...
...
@@ -119,36 +114,11 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
* linked actors, sets its state to @c exited and finishes execution.
* @param reason Exit reason that will be send to
* linked actors and monitors.
* @note Throws {@link actor_exited} to unwind the stack
* when called in context-switching or thread-based actors.
*/
virtual
void
quit
(
std
::
uint32_t
reason
=
exit_reason
::
normal
)
=
0
;
/**
* @brief Removes the first element from the mailbox @p pfun is defined
* for and invokes @p pfun with the removed element.
* Blocks until a matching message arrives if @p pfun is not
* defined for any message in the actor's mailbox.
* @param pfun A partial function denoting the actor's response to the
* next incoming message.
* @warning You should not call this member function by hand.
* Use the {@link cppa::receive receive} function or
* the @p become member function in case of event-based actors.
*/
virtual
void
dequeue
(
partial_function
&
pfun
)
=
0
;
/**
* @brief Removes the first element from the mailbox @p bhvr is defined
* for and invokes @p bhvr with the removed element.
* Blocks until either a matching message arrives if @p bhvr is not
* defined for any message in the actor's mailbox or until a
* timeout occurs.
* @param bhvr A partial function with optional timeout denoting the
* actor's response to the next incoming message.
* @warning You should not call this member function by hand.
* Use the {@link cppa::receive receive} function or
* the @p become member function in case of event-based actors.
*/
virtual
void
dequeue
(
behavior
&
bhvr
)
=
0
;
/**
* @brief Checks whether this actor traps exit messages.
*/
...
...
@@ -191,47 +161,13 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
* @param whom The actor that should be monitored by this actor.
* @note Each call to @p monitor creates a new, independent monitor.
*/
void
monitor
(
actor_ptr
whom
);
void
monitor
(
const
actor_ptr
&
whom
);
/**
* @brief Removes a monitor from @p whom.
* @param whom A monitored actor.
*/
void
demonitor
(
actor_ptr
whom
);
// become/unbecome API
/**
* @brief Sets the actor's behavior to @p bhvr and discards the
* previous behavior if the policy is {@link discard_behavior}.
*/
template
<
bool
Discard
>
inline
void
become
(
behavior_policy
<
Discard
>
,
behavior
bhvr
);
/**
* @brief Sets the actor's behavior and discards the
* previous behavior if the policy is {@link discard_behavior}.
*/
template
<
bool
Discard
,
typename
T0
,
typename
T1
,
typename
...
Ts
>
inline
void
become
(
behavior_policy
<
Discard
>
,
T0
&&
a0
,
T1
&&
a1
,
Ts
&&
...
as
);
/**
* @brief Sets the actor's behavior;
* equal to <tt>become(discard_old, bhvr</tt>.
*/
inline
void
become
(
behavior
bhvr
);
/**
* @brief Sets the actor's behavior;
* equal to <tt>become(discard_old, bhvr</tt>.
*/
template
<
typename
...
Cases
,
typename
...
Ts
>
inline
void
become
(
match_expr
<
Cases
...
>
a
,
Ts
&&
...
as
);
/**
* @brief Returns to a previous behavior if available.
*/
inline
void
unbecome
();
void
demonitor
(
const
actor_ptr
&
whom
);
/**
* @brief Can be overridden to initialize an actor before any
...
...
@@ -256,6 +192,7 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
std
::
vector
<
group_ptr
>
joined_groups
();
/**
* @ingroup BlockingAPI
* @brief Executes an actor's behavior stack until it is empty.
*
* This member function allows thread-based and context-switching actors
...
...
@@ -308,146 +245,108 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
else
quit
(
exit_reason
::
unhandled_sync_failure
);
}
// library-internal members and member functions that shall
// not appear in the documentation
/** @cond PRIVATE */
virtual
void
dequeue
(
behavior
&
bhvr
)
=
0
;
inline
void
dequeue
(
behavior
&&
bhvr
);
virtual
void
dequeue_response
(
behavior
&
,
message_id
)
=
0
;
inline
void
dequeue_response
(
behavior
&&
,
message_id
);
# ifndef CPPA_DOCUMENTATION
template
<
bool
Discard
,
typename
...
Ts
>
void
become
(
behavior_policy
<
Discard
>
,
Ts
&&
...
args
);
// backward compatiblity, handle_response was part of local_actor
// until version 0.6
sync_handle_helper
handle_response
(
const
message_future
&
mf
);
template
<
typename
T
,
typename
...
Ts
>
void
become
(
T
arg
,
Ts
&&
...
args
);
inline
void
unbecome
();
local_actor
(
bool
is_scheduled
=
false
);
virtual
bool
initialized
()
const
=
0
;
inline
bool
chaining_enabled
()
{
return
m_chaining
&&
!
m_chained_actor
;
}
inline
bool
chaining_enabled
();
inline
void
send_message
(
channel
*
whom
,
any_tuple
&&
what
)
{
whom
->
enqueue
(
this
,
std
::
move
(
what
));
}
inline
void
send_message
(
channel
*
whom
,
any_tuple
&&
what
);
inline
void
send_message
(
const
actor_ptr
&
whom
,
any_tuple
&&
what
)
{
if
(
chaining_enabled
())
{
if
(
whom
->
chained_enqueue
(
this
,
std
::
move
(
what
)))
{
m_chained_actor
=
whom
;
}
}
else
whom
->
enqueue
(
this
,
std
::
move
(
what
));
}
inline
void
send_message
(
actor
*
whom
,
any_tuple
&&
what
);
inline
message_id_t
send_sync_message
(
const
actor_ptr
&
whom
,
any_tuple
&&
what
)
{
auto
id
=
++
m_last_request_id
;
CPPA_REQUIRE
(
id
.
is_request
());
if
(
chaining_enabled
())
{
if
(
whom
->
chained_sync_enqueue
(
this
,
id
,
std
::
move
(
what
)))
{
m_chained_actor
=
whom
;
}
}
else
whom
->
sync_enqueue
(
this
,
id
,
std
::
move
(
what
));
auto
awaited_response
=
id
.
response_id
();
m_pending_responses
.
push_back
(
awaited_response
);
return
awaited_response
;
}
inline
message_id
send_sync_message
(
const
actor_ptr
&
whom
,
any_tuple
&&
what
);
message_id
_t
send_timed_sync_message
(
const
actor_ptr
&
whom
,
message_id
send_timed_sync_message
(
const
actor_ptr
&
whom
,
const
util
::
duration
&
rel_time
,
any_tuple
&&
what
);
// returns 0 if last_dequeued() is an asynchronous or sync request message,
// a response id generated from the request id otherwise
inline
message_id_t
get_response_id
()
{
auto
id
=
m_current_node
->
mid
;
return
(
id
.
is_request
())
?
id
.
response_id
()
:
message_id_t
();
}
inline
message_id
get_response_id
();
void
reply_message
(
any_tuple
&&
what
);
void
forward_message
(
const
actor_ptr
&
new_receiver
);
inline
const
actor_ptr
&
chained_actor
()
{
return
m_chained_actor
;
}
inline
const
actor_ptr
&
chained_actor
();
inline
void
chained_actor
(
const
actor_ptr
&
value
)
{
m_chained_actor
=
value
;
}
inline
void
chained_actor
(
const
actor_ptr
&
value
);
inline
bool
awaits
(
message_id_t
response_id
)
{
CPPA_REQUIRE
(
response_id
.
is_response
());
return
std
::
any_of
(
m_pending_responses
.
begin
(),
m_pending_responses
.
end
(),
[
=
](
message_id_t
other
)
{
return
response_id
==
other
;
});
}
inline
bool
awaits
(
message_id
response_id
);
inline
void
mark_arrived
(
message_id_t
response_id
)
{
auto
last
=
m_pending_responses
.
end
();
auto
i
=
std
::
find
(
m_pending_responses
.
begin
(),
last
,
response_id
);
if
(
i
!=
last
)
m_pending_responses
.
erase
(
i
);
}
inline
void
mark_arrived
(
message_id
response_id
);
virtual
void
dequeue_response
(
behavior
&
,
message_id_t
)
=
0
;
virtual
void
become_waiting_for
(
behavior
,
message_id
)
=
0
;
inline
void
dequeue_response
(
behavior
&&
bhvr
,
message_id_t
mid
)
{
behavior
tmp
{
std
::
move
(
bhvr
)};
dequeue_response
(
tmp
,
mid
);
}
inline
detail
::
behavior_stack
&
bhvr_stack
();
virtual
void
become_waiting_for
(
behavior
&&
,
message_id_t
)
=
0
;
protected:
inline
detail
::
behavior_stack
&
bhvr_stack
()
{
return
m_bhvr_stack
;
}
virtual
void
do_become
(
behavior
&&
bhvr
,
bool
discard_old
)
=
0
;
protected:
inline
void
do_become
(
const
behavior
&
bhvr
,
bool
discard_old
);
inline
void
remove_handler
(
message_id
id
);
void
cleanup
(
std
::
uint32_t
reason
);
// true if this actor uses the chained_send optimization
bool
m_chaining
;
// true if this actor receives EXIT messages as ordinary messages
bool
m_trap_exit
;
// true if this actor takes part in cooperative scheduling
bool
m_is_scheduled
;
// pointer to the actor that is marked as successor due to a chained send
actor_ptr
m_chained_actor
;
// identifies the ID of the last sent synchronous request
message_id_t
m_last_request_id
;
message_id
m_last_request_id
;
// identifies all IDs of sync messages waiting for a response
std
::
vector
<
message_id_t
>
m_pending_responses
;
std
::
vector
<
message_id
>
m_pending_responses
;
// "default value" for m_current_node
detail
::
recursive_queue_node
m_dummy_node
;
mailbox_element
m_dummy_node
;
// points to m_dummy_node if no callback is currently invoked,
// points to the node under processing otherwise
detail
::
recursive_queue_node
*
m_current_node
;
mailbox_element
*
m_current_node
;
// {group => subscription} map of all joined groups
std
::
map
<
group_ptr
,
group
::
subscription
>
m_subscriptions
;
// allows actors to keep previous behaviors and enables unbecome()
detail
::
behavior_stack
m_bhvr_stack
;
inline
void
remove_handler
(
message_id_t
id
)
{
m_bhvr_stack
.
erase
(
id
);
}
void
cleanup
(
std
::
uint32_t
reason
);
private:
std
::
function
<
void
()
>
m_sync_failure_handler
;
std
::
function
<
void
()
>
m_sync_timeout_handler
;
# endif // CPPA_DOCUMENTATION
protected:
virtual
void
do_become
(
behavior
&&
bhvr
,
bool
discard_old
)
=
0
;
inline
void
do_become
(
const
behavior
&
bhvr
,
bool
discard_old
)
{
behavior
copy
{
bhvr
};
do_become
(
std
::
move
(
copy
),
discard_old
);
}
/** @endcond */
};
...
...
@@ -457,10 +356,21 @@ class local_actor : public extend<actor,local_actor>::with<memory_cached> {
*/
typedef
intrusive_ptr
<
local_actor
>
local_actor_ptr
;
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
void
local_actor
::
dequeue
(
behavior
&&
bhvr
)
{
behavior
tmp
{
std
::
move
(
bhvr
)};
dequeue
(
tmp
);
}
inline
void
local_actor
::
dequeue_response
(
behavior
&&
bhvr
,
message_id
id
)
{
behavior
tmp
{
std
::
move
(
bhvr
)};
dequeue_response
(
tmp
,
id
);
}
inline
bool
local_actor
::
trap_exit
()
const
{
return
m_trap_exit
;
}
...
...
@@ -485,28 +395,90 @@ inline actor_ptr& local_actor::last_sender() {
return
m_current_node
->
sender
;
}
template
<
bool
Discard
>
inline
void
local_actor
::
become
(
behavior_policy
<
Discard
>
,
behavior
bhvr
)
{
do_become
(
std
::
move
(
bhvr
),
Discard
);
template
<
bool
Discard
,
typename
...
Ts
>
inline
void
local_actor
::
become
(
behavior_policy
<
Discard
>
,
Ts
&&
...
args
)
{
do_become
(
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...
),
Discard
);
}
template
<
bool
Discard
,
typename
T0
,
typename
T1
,
typename
...
Ts
>
inline
void
local_actor
::
become
(
behavior_policy
<
Discard
>
,
T0
&&
a0
,
T1
&&
a1
,
Ts
&&
...
as
)
{
auto
bhvr
=
match_expr_convert
(
std
::
forward
<
T0
>
(
a0
),
std
::
forward
<
T1
>
(
a1
),
std
::
forward
<
Ts
>
(
as
)...);
do_become
(
std
::
move
(
bhvr
),
Discard
);
template
<
typename
T
,
typename
...
Ts
>
inline
void
local_actor
::
become
(
T
arg
,
Ts
&&
...
args
)
{
do_become
(
match_expr_convert
(
arg
,
std
::
forward
<
Ts
>
(
args
)...),
true
);
}
inline
void
local_actor
::
become
(
behavior
bhvr
)
{
do_become
(
std
::
move
(
bhvr
),
true
);
inline
void
local_actor
::
unbecome
(
)
{
m_bhvr_stack
.
pop_async_back
(
);
}
template
<
typename
...
Cases
,
typename
...
Ts
>
inline
void
local_actor
::
become
(
match_expr
<
Cases
...
>
a
,
Ts
&&
...
as
)
{
do_become
(
match_expr_convert
(
std
::
move
(
a
),
std
::
forward
<
Ts
>
(
as
)...),
true
);
inline
bool
local_actor
::
chaining_enabled
()
{
return
m_chaining
&&
!
m_chained_actor
;
}
inline
void
local_actor
::
unbecome
()
{
m_bhvr_stack
.
pop_async_back
();
inline
void
local_actor
::
send_message
(
channel
*
whom
,
any_tuple
&&
what
)
{
whom
->
enqueue
(
this
,
std
::
move
(
what
));
}
inline
void
local_actor
::
send_message
(
actor
*
whom
,
any_tuple
&&
what
)
{
if
(
chaining_enabled
())
{
if
(
whom
->
chained_enqueue
(
this
,
std
::
move
(
what
)))
{
m_chained_actor
.
reset
(
whom
);
}
}
else
whom
->
enqueue
(
this
,
std
::
move
(
what
));
}
inline
message_id
local_actor
::
send_sync_message
(
const
actor_ptr
&
whom
,
any_tuple
&&
what
)
{
auto
id
=
++
m_last_request_id
;
CPPA_REQUIRE
(
id
.
is_request
());
if
(
chaining_enabled
())
{
if
(
whom
->
chained_sync_enqueue
(
this
,
id
,
std
::
move
(
what
)))
{
chained_actor
(
whom
);
}
}
else
whom
->
sync_enqueue
(
this
,
id
,
std
::
move
(
what
));
auto
awaited_response
=
id
.
response_id
();
m_pending_responses
.
push_back
(
awaited_response
);
return
awaited_response
;
}
inline
message_id
local_actor
::
get_response_id
()
{
auto
id
=
m_current_node
->
mid
;
return
(
id
.
is_request
())
?
id
.
response_id
()
:
message_id
();
}
inline
const
actor_ptr
&
local_actor
::
chained_actor
()
{
return
m_chained_actor
;
}
inline
void
local_actor
::
chained_actor
(
const
actor_ptr
&
value
)
{
m_chained_actor
=
value
;
}
inline
bool
local_actor
::
awaits
(
message_id
response_id
)
{
CPPA_REQUIRE
(
response_id
.
is_response
());
return
std
::
any_of
(
m_pending_responses
.
begin
(),
m_pending_responses
.
end
(),
[
=
](
message_id
other
)
{
return
response_id
==
other
;
});
}
inline
void
local_actor
::
mark_arrived
(
message_id
response_id
)
{
auto
last
=
m_pending_responses
.
end
();
auto
i
=
std
::
find
(
m_pending_responses
.
begin
(),
last
,
response_id
);
if
(
i
!=
last
)
m_pending_responses
.
erase
(
i
);
}
inline
detail
::
behavior_stack
&
local_actor
::
bhvr_stack
()
{
return
m_bhvr_stack
;
}
inline
void
local_actor
::
do_become
(
const
behavior
&
bhvr
,
bool
discard_old
)
{
behavior
copy
{
bhvr
};
do_become
(
std
::
move
(
copy
),
discard_old
);
}
inline
void
local_actor
::
remove_handler
(
message_id
id
)
{
m_bhvr_stack
.
erase
(
id
);
}
}
// namespace cppa
...
...
cppa/mailbox_based.hpp
View file @
04fc1827
...
...
@@ -33,10 +33,9 @@
#include <type_traits>
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/sync_request_bouncer.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/intrusive/blocking_single_reader_queue.hpp"
namespace
cppa
{
...
...
@@ -61,14 +60,7 @@ class mailbox_based : public Base {
typedef
mailbox_based
combined_type
;
typedef
detail
::
recursive_queue_node
mailbox_element
;
typedef
typename
std
::
conditional
<
has_blocking_receive
<
Subtype
>::
value
,
intrusive
::
blocking_single_reader_queue
<
mailbox_element
,
del
>
,
intrusive
::
single_reader_queue
<
mailbox_element
,
del
>
>::
type
mailbox_type
;
typedef
intrusive
::
single_reader_queue
<
mailbox_element
,
del
>
mailbox_type
;
template
<
typename
...
Ts
>
mailbox_based
(
Ts
&&
...
args
)
:
Base
(
std
::
forward
<
Ts
>
(
args
)...)
{
}
...
...
@@ -86,10 +78,6 @@ class mailbox_based : public Base {
mailbox_type
m_mailbox
;
private:
inline
Subtype
*
dthis
()
{
return
static_cast
<
Subtype
*>
(
this
);
}
};
}
// namespace cppa
...
...
cppa/
detail/recursive_queue_node
.hpp
→
cppa/
mailbox_element
.hpp
View file @
04fc1827
...
...
@@ -34,51 +34,52 @@
#include <cstdint>
#include "cppa/actor.hpp"
#include "cppa/extend.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/message_id.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/memory_cached.hpp"
// needs access to constructor + destructor to initialize m_dummy_node
namespace
cppa
{
class
local_actor
;
}
namespace
cppa
{
namespace
cppa
{
namespace
detail
{
class
local_actor
;
class
recursive_queue_node
:
public
memory_cached
<
memory_managed
,
recursive_queue_node
>
{
class
mailbox_element
:
public
extend
<
memory_managed
>::
with
<
memory_cached
>
{
friend
class
memory
;
friend
class
::
cppa
::
local_actor
;
friend
class
local_actor
;
friend
class
detail
::
memory
;
public:
typedef
recursive_queue_node
*
pointer
;
typedef
mailbox_element
*
pointer
;
pointer
next
;
// intrusive next pointer
bool
marked
;
// denotes if this node is currently processed
actor_ptr
sender
;
// points to the sender of msg
any_tuple
msg
;
// 'content field'
message_id
_t
mid
;
message_id
mid
;
recursive_queue_node
(
recursive_queue_node
&&
)
=
delete
;
recursive_queue_node
(
const
recursive_queue_node
&
)
=
delete
;
recursive_queue_node
&
operator
=
(
recursive_queue_node
&&
)
=
delete
;
recursive_queue_node
&
operator
=
(
const
recursive_queue_node
&
)
=
delete
;
mailbox_element
(
mailbox_element
&&
)
=
delete
;
mailbox_element
(
const
mailbox_element
&
)
=
delete
;
mailbox_element
&
operator
=
(
mailbox_element
&&
)
=
delete
;
mailbox_element
&
operator
=
(
const
mailbox_element
&
)
=
delete
;
template
<
typename
...
Ts
>
inline
static
recursive_queue_node
*
create
(
Ts
&&
...
args
)
{
return
memory
::
create
<
recursive_queue_node
>
(
std
::
forward
<
Ts
>
(
args
)...);
inline
static
mailbox_element
*
create
(
Ts
&&
...
args
)
{
return
detail
::
memory
::
create
<
mailbox_element
>
(
std
::
forward
<
Ts
>
(
args
)...);
}
private:
recursive_queue_node
()
=
default
;
mailbox_element
()
=
default
;
recursive_queue_node
(
const
actor_ptr
&
sptr
,
mailbox_element
(
const
actor_ptr
&
sptr
,
any_tuple
data
,
message_id_t
id
=
message_id_t
{});
message_id
id
=
message_id
{});
};
}
}
// namespace cppa::detail
}
// namespace cppa
#endif // CPPA_RECURSIVE_QUEUE_NODE_HPP
cppa/match.hpp
View file @
04fc1827
...
...
@@ -51,16 +51,10 @@ struct match_helper {
any_tuple
tup
;
match_helper
(
any_tuple
t
)
:
tup
(
std
::
move
(
t
))
{
}
match_helper
(
match_helper
&&
)
=
default
;
/*
void operator()(partial_function&& arg) {
partial_function tmp{std::move(arg)};
tmp(tup);
}
*/
template
<
class
Arg0
,
class
...
Args
>
bool
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
template
<
typename
...
Ts
>
bool
operator
()(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"at least one argument required"
);
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
static_assert
(
std
::
is_same
<
partial_function
,
decltype
(
tmp
)
>::
value
,
"match statement contains timeout"
);
return
tmp
(
tup
);
...
...
@@ -86,20 +80,15 @@ class match_each_helper {
match_each_helper
(
Iterator
first
,
Iterator
last
,
Projection
proj
)
:
i
(
first
),
e
(
last
),
p
(
proj
)
{
}
template
<
typename
...
Cases
>
void
operator
()(
match_expr
<
Cases
...
>
expr
)
{
template
<
typename
...
Ts
>
void
operator
()(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"at least one argument required"
);
auto
expr
=
match_expr_collect
(
std
::
forward
<
Ts
>
(
args
)...);
for
(;
i
!=
e
;
++
i
)
{
expr
(
p
(
*
i
));
}
}
template
<
class
Arg0
,
class
Arg1
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Arg1
&&
arg1
,
Args
&&
...
args
)
{
(
*
this
)(
match_expr_collect
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Arg1
>
(
arg1
),
std
::
forward
<
Args
>
(
args
)...));
}
private:
Iterator
i
;
...
...
@@ -126,20 +115,15 @@ class match_for_helper {
match_for_helper
(
Iterator
first
,
Predicate
p
,
Advance
a
=
Advance
(),
Projection
pj
=
Projection
())
:
i
(
first
),
adv
(
a
),
pred
(
p
),
proj
(
pj
)
{
}
template
<
typename
...
Cases
>
void
operator
()(
match_expr
<
Cases
...
>
expr
)
{
template
<
typename
...
Ts
>
void
operator
()(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"at least one argument required"
);
auto
expr
=
match_expr_collect
(
std
::
forward
<
Ts
>
(
args
)...);
for
(;
pred
(
i
);
adv
(
i
))
{
expr
(
proj
(
*
i
));
}
}
template
<
class
Arg0
,
class
Arg1
,
class
...
Args
>
void
operator
()(
Arg0
&&
arg0
,
Arg1
&&
arg1
,
Args
&&
...
args
)
{
(
*
this
)(
match_expr_collect
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Arg1
>
(
arg1
),
std
::
forward
<
Args
>
(
args
)...));
}
private:
Iterator
i
;
...
...
@@ -199,8 +183,8 @@ struct unwind_and_call<Size, Size> {
return
target
.
first
.
invoke
(
target
.
second
,
sub_result
,
std
::
forward
<
Unwinded
>
(
args
)...);
}
template
<
typename
T
,
typename
...
Arg
s
>
static
inline
bool
_
(
std
::
vector
<
T
>&
,
Arg
s
&&
...)
{
return
false
;
}
template
<
typename
T
,
typename
...
T
s
>
static
inline
bool
_
(
std
::
vector
<
T
>&
,
T
s
&&
...)
{
return
false
;
}
};
...
...
@@ -272,34 +256,18 @@ class stream_matcher {
stream_matcher
(
iter
first
,
iter
last
)
:
m_pos
(
first
),
m_end
(
last
)
{
}
template
<
typename
...
Cases
>
bool
operator
()(
match_expr
<
Cases
...
>&
expr
)
{
template
<
typename
...
Ts
>
bool
operator
()(
Ts
&&
...
args
)
{
auto
expr
=
match_expr_collect
(
std
::
forward
<
Ts
>
(
args
)...);
typedef
decltype
(
expr
)
expr_type
;
while
(
m_pos
!=
m_end
)
{
if
(
!
unwind_and_call
<
0
,
util
::
tl_size
<
typename
match_expr
<
Cases
...
>
::
cases_list
>::
value
>::
_
(
m_cache
,
m_pos
,
m_end
,
expr
))
{
if
(
!
unwind_and_call
<
0
,
util
::
tl_size
<
typename
expr_type
::
cases_list
>::
value
>::
_
(
m_cache
,
m_pos
,
m_end
,
expr
))
{
return
false
;
}
}
return
true
;
}
template
<
typename
...
Cases
>
bool
operator
()(
match_expr
<
Cases
...
>&&
expr
)
{
auto
tmp
=
std
::
move
(
expr
);
return
(
*
this
)(
tmp
);
}
template
<
typename
...
Cases
>
bool
operator
()(
const
match_expr
<
Cases
...
>&
expr
)
{
auto
tmp
=
expr
;
return
(
*
this
)(
tmp
);
}
template
<
typename
Arg0
,
typename
...
Args
>
bool
operator
()(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
return
(
*
this
)(
match_expr_collect
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...));
}
private:
iter
m_pos
;
...
...
cppa/match_expr.hpp
View file @
04fc1827
...
...
@@ -44,6 +44,8 @@
#include "cppa/util/disjunction.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/deduce_ref_type.hpp"
#include "cppa/util/get_result_type.hpp"
#include "cppa/util/rebindable_reference.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/projection.hpp"
...
...
@@ -197,10 +199,10 @@ struct invoke_policy_impl<wildcard_position::nil,
>::
type
*
=
0
)
{
if
(
arg_types
==
typeid
(
util
::
type_list
<
Ts
...
>
))
{
if
(
native_arg
)
{
typedef
typename
util
::
if_else_c
<
typedef
typename
std
::
conditional
<
std
::
is_const
<
PtrType
>::
value
,
const
native_data_type
*
,
util
::
wrapped
<
native_data_type
*>
native_data_type
*
>::
type
cast_type
;
auto
arg
=
reinterpret_cast
<
cast_type
>
(
native_arg
);
...
...
@@ -356,9 +358,9 @@ struct invoke_policy
template
<
class
Pattern
,
class
Projection
,
class
PartialFun
>
struct
projection_partial_function_pair
:
std
::
pair
<
Projection
,
PartialFun
>
{
template
<
typename
...
Arg
s
>
projection_partial_function_pair
(
Arg
s
&&
...
args
)
:
std
::
pair
<
Projection
,
PartialFun
>
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
}
template
<
typename
...
T
s
>
projection_partial_function_pair
(
T
s
&&
...
args
)
:
std
::
pair
<
Projection
,
PartialFun
>
(
std
::
forward
<
T
s
>
(
args
)...)
{
}
typedef
Pattern
pattern_type
;
};
...
...
@@ -558,11 +560,6 @@ inline std::uint64_t calc_bitmask(PPFPs& fs, long_constant<N>, const std::type_i
return
result
|
calc_bitmask
(
fs
,
long_constant
<
N
-
1l
>
(),
tinf
,
tup
);
}
template
<
typename
T
>
struct
is_manipulator_case
{
static
constexpr
bool
value
=
T
::
second_type
::
manipulates_args
;
};
template
<
bool
IsManipulator
,
typename
T0
,
typename
T1
>
struct
mexpr_fwd_
{
typedef
T1
type
;
...
...
@@ -620,29 +617,35 @@ inline const void* fetch_native_data(const Ptr& ptr, std::false_type) {
namespace
cppa
{
template
<
class
...
Cases
>
/** @cond PRIVATE */
template
<
typename
T
>
struct
is_manipulator_case
{
static
constexpr
bool
value
=
T
::
second_type
::
manipulates_args
;
};
/** @endcond */
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>.
*/
template
<
class
...
Cs
>
class
match_expr
{
static_assert
(
sizeof
...(
C
ase
s
)
<
64
,
"too many functions"
);
static_assert
(
sizeof
...(
Cs
)
<
64
,
"too many functions"
);
public:
static
constexpr
bool
may_have_timeout
=
false
;
typedef
util
::
type_list
<
C
ase
s
...
>
cases_list
;
typedef
util
::
type_list
<
Cs
...
>
cases_list
;
static
constexpr
size_t
num_cases
=
sizeof
...(
Cases
)
;
static
constexpr
bool
has_manipulator
=
util
::
tl_exists
<
cases_list
,
is_manipulator_case
>::
value
;
static
constexpr
bool
has_manipulator
=
util
::
tl_exists
<
cases_list
,
detail
::
is_manipulator_case
>::
value
;
typedef
detail
::
long_constant
<
static_cast
<
long
>
(
num_cases
)
-
1l
>
idx_token_type
;
typedef
detail
::
long_constant
<
sizeof
...(
Cs
)
-
1l
>
idx_token_type
;
static
constexpr
idx_token_type
idx_token
=
idx_token_type
{};
template
<
typename
...
Arg
s
>
match_expr
(
Args
&&
...
args
)
:
m_cases
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
template
<
typename
...
T
s
>
match_expr
(
Ts
&&
...
args
)
:
m_cases
(
std
::
forward
<
T
s
>
(
args
)...)
{
init
();
}
...
...
@@ -692,31 +695,34 @@ class match_expr {
return
invoke_impl
(
tmp
);
}
template
<
typename
...
Args
>
bool
operator
()(
Args
&&
...
args
)
{
template
<
typename
...
Ts
>
bool
operator
()(
Ts
&&
...
args
)
{
// wraps and applies implicit conversions to args
typedef
detail
::
tdata
<
typename
detail
::
mexpr_fwd
<
has_manipulator
,
Args
>::
type
...
>
typename
detail
::
mexpr_fwd
<
has_manipulator
,
Ts
>::
type
...
>
tuple_type
;
// applies implicit conversions etc
tuple_type
tup
{
std
::
forward
<
Args
>
(
args
)...};
tuple_type
tup
{
std
::
forward
<
Ts
>
(
args
)...};
auto
&
type_token
=
typeid
(
typename
tuple_type
::
types
);
auto
bitmask
=
get_cache_entry
(
&
type_token
,
tup
);
typedef
typename
util
::
if_else_c
<
// ref_type keeps track of whether this match_expr is a mutator
typedef
typename
std
::
conditional
<
has_manipulator
,
tuple_type
&
,
const
util
::
wrapped
<
tuple_type
&>
const
tuple_type
&
>::
type
ref_type
;
typedef
typename
util
::
if_else_c
<
// same here
typedef
typename
std
::
conditional
<
has_manipulator
,
void
*
,
util
::
wrapped
<
const
void
*>
const
void
*
>::
type
ptr_type
;
ptr_type
ptr_arg
=
nullptr
;
// iterate over cases and return if any case was invoked
bool
invoke_result
=
true
;
bool
unroll_result
=
unroll_expr
(
m_cases
,
invoke_result
,
...
...
@@ -724,21 +730,20 @@ class match_expr {
idx_token
,
type_token
,
false
,
// not dynamically_typed
ptr_arg
,
static_cast
<
ptr_type
>
(
nullptr
)
,
static_cast
<
ref_type
>
(
tup
));
return
unroll_result
&&
invoke_result
;
}
template
<
class
...
OtherCases
>
match_expr
<
Cases
...,
OtherCases
...
>
or_else
(
const
match_expr
<
OtherCases
...
>&
other
)
const
{
detail
::
tdata
<
ge_reference_wrapper
<
Cases
>
...,
ge_reference_wrapper
<
OtherCases
>
...
>
all_cases
;
collect_tdata
(
all_cases
,
m_cases
,
other
.
cases
());
template
<
class
...
Ds
>
match_expr
<
Cs
...,
Ds
...
>
or_else
(
const
match_expr
<
Ds
...
>&
other
)
const
{
detail
::
tdata
<
util
::
rebindable_reference
<
const
Cs
>
...,
util
::
rebindable_reference
<
const
Ds
>
...
>
all_cases
;
rebind_tdata
(
all_cases
,
m_cases
,
other
.
cases
());
return
{
all_cases
};
}
inline
const
detail
::
tdata
<
C
ase
s
...
>&
cases
()
const
{
inline
const
detail
::
tdata
<
Cs
...
>&
cases
()
const
{
return
m_cases
;
}
...
...
@@ -770,7 +775,7 @@ class match_expr {
// structure: tdata< tdata<type_list<...>, ...>,
// tdata<type_list<...>, ...>,
// ...>
detail
::
tdata
<
C
ase
s
...
>
m_cases
;
detail
::
tdata
<
Cs
...
>
m_cases
;
static
constexpr
size_t
cache_size
=
10
;
...
...
@@ -828,13 +833,14 @@ class match_expr {
bool
invoke_impl
(
Tuple
&
tup
)
{
std
::
integral_constant
<
bool
,
has_manipulator
>
mutator_token
;
// returns either a reference or a new object
decltype
(
detail
::
detach_if_needed
(
tup
,
mutator_token
))
tref
=
detail
::
detach_if_needed
(
tup
,
mutator_token
);
typedef
decltype
(
detail
::
detach_if_needed
(
tup
,
mutator_token
))
detached
;
detached
tref
=
detail
::
detach_if_needed
(
tup
,
mutator_token
);
auto
&
vals
=
tref
.
vals
();
auto
ndp
=
fetch_native_data
(
vals
,
mutator_token
);
auto
token_ptr
=
vals
->
type_token
();
auto
bitmask
=
get_cache_entry
(
token_ptr
,
*
vals
);
auto
dynamically_typed
=
vals
->
dynamically_typed
();
bool
invoke_result
=
true
;
// maybe set to false by an invoked functor
bool
invoke_result
=
true
;
// may
be set to false by an invoked functor
bool
unroll_result
=
unroll_expr
(
m_cases
,
invoke_result
,
bitmask
,
...
...
@@ -851,9 +857,9 @@ class match_expr {
template
<
class
List
>
struct
match_expr_from_type_list
;
template
<
typename
...
Arg
s
>
struct
match_expr_from_type_list
<
util
::
type_list
<
Arg
s
...
>
>
{
typedef
match_expr
<
Arg
s
...
>
type
;
template
<
typename
...
T
s
>
struct
match_expr_from_type_list
<
util
::
type_list
<
T
s
...
>
>
{
typedef
match_expr
<
T
s
...
>
type
;
};
template
<
typename
...
Lhs
,
typename
...
Rhs
>
...
...
@@ -862,32 +868,41 @@ inline match_expr<Lhs...,Rhs...> operator,(const match_expr<Lhs...>& lhs,
return
lhs
.
or_else
(
rhs
);
}
template
<
typename
Arg0
,
typename
...
Args
>
template
<
typename
...
Cs
>
match_expr
<
Cs
...
>&
match_expr_collect
(
match_expr
<
Cs
...
>&
arg
)
{
return
arg
;
}
template
<
typename
...
Cs
>
match_expr
<
Cs
...
>&&
match_expr_collect
(
match_expr
<
Cs
...
>&&
arg
)
{
return
std
::
move
(
arg
);
}
template
<
typename
...
Cs
>
const
match_expr
<
Cs
...
>&
match_expr_collect
(
const
match_expr
<
Cs
...
>&
arg
)
{
return
arg
;
}
template
<
typename
T
,
typename
...
Ts
>
typename
match_expr_from_type_list
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
>::
type
>::
type
match_expr_collect
(
const
Arg0
&
arg0
,
const
Args
&
...
args
)
{
typedef
typename
match_expr_from_type_list
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Args
::
cases_list
...
typename
T
::
cases_list
,
typename
Ts
::
cases_list
...
>::
type
>::
type
combined_type
;
match_expr_collect
(
const
T
&
arg
,
const
Ts
&
...
args
)
{
typename
detail
::
tdata_from_type_list
<
typename
util
::
tl_map
<
typename
util
::
tl_concat
<
typename
Arg0
::
cases_list
,
typename
Arg
s
::
cases_list
...
typename
T
::
cases_list
,
typename
T
s
::
cases_list
...
>::
type
,
gref_wrapped
>::
type
>::
type
all_cases
;
detail
::
collect_tdata
(
all_cases
,
arg0
.
cases
(),
args
.
cases
()...);
detail
::
rebind_tdata
(
all_cases
,
arg
.
cases
(),
args
.
cases
()...);
return
{
all_cases
};
}
...
...
@@ -921,7 +936,7 @@ behavior_impl* concat_rec(const Data& data, Token, const T& arg, const Ts&... ar
>::
type
next_data
;
next_token_type
next_token
;
collect
_tdata
(
next_data
,
data
,
arg
.
cases
());
rebind
_tdata
(
next_data
,
data
,
arg
.
cases
());
return
concat_rec
(
next_data
,
next_token
,
args
...);
}
...
...
@@ -940,7 +955,7 @@ behavior_impl* concat_expr(with_timeout, const T& arg, const Ts&... args) {
>::
type
>::
type
wrapper
;
detail
::
collect
_tdata
(
wrapper
,
arg
.
cases
());
detail
::
rebind
_tdata
(
wrapper
,
arg
.
cases
());
return
concat_rec
(
wrapper
,
typename
T
::
cases_list
{},
args
...);
}
...
...
@@ -967,7 +982,7 @@ behavior_impl* concat_expr(without_timeout, const T& arg, const Ts&... args) {
combined_type
;
auto
lvoid
=
[]()
{
};
typedef
default_behavior_impl
<
combined_type
,
decltype
(
lvoid
)
>
impl_type
;
collect
_tdata
(
all_cases
,
arg
.
cases
(),
args
.
cases
()...);
rebind
_tdata
(
all_cases
,
arg
.
cases
(),
args
.
cases
()...);
return
new
impl_type
(
all_cases
,
util
::
duration
{},
lvoid
);
}
...
...
cppa/message_future.hpp
View file @
04fc1827
...
...
@@ -56,7 +56,7 @@ class message_future {
public:
inline
continue_helper
(
message_id
_t
mid
)
:
m_mid
(
mid
)
{
}
inline
continue_helper
(
message_id
mid
)
:
m_mid
(
mid
)
{
}
template
<
typename
F
>
void
continue_with
(
F
fun
)
{
...
...
@@ -71,7 +71,7 @@ class message_future {
private:
message_id
_t
m_mid
;
message_id
m_mid
;
};
...
...
@@ -80,20 +80,20 @@ class message_future {
/**
* @brief Sets @p mexpr as event-handler for the response message.
*/
template
<
typename
...
C
ases
,
typename
...
Arg
s
>
continue_helper
then
(
const
match_expr
<
C
ases
...
>&
a0
,
const
Args
&
...
a
s
)
{
template
<
typename
...
C
s
,
typename
...
T
s
>
continue_helper
then
(
const
match_expr
<
C
s
...
>&
arg
,
const
Ts
&
...
arg
s
)
{
check_consistency
();
self
->
become_waiting_for
(
match_expr_convert
(
a
0
,
a
s
...),
m_mid
);
self
->
become_waiting_for
(
match_expr_convert
(
a
rg
,
arg
s
...),
m_mid
);
return
{
m_mid
};
}
/**
* @brief Blocks until the response arrives and then executes @p mexpr.
*/
template
<
typename
...
C
ases
,
typename
...
Arg
s
>
void
await
(
const
match_expr
<
C
ases
...
>&
arg0
,
const
Arg
s
&
...
args
)
{
template
<
typename
...
C
s
,
typename
...
T
s
>
void
await
(
const
match_expr
<
C
s
...
>&
arg
,
const
T
s
&
...
args
)
{
check_consistency
();
self
->
dequeue_response
(
match_expr_convert
(
arg
0
,
args
...),
m_mid
);
self
->
dequeue_response
(
match_expr_convert
(
arg
,
args
...),
m_mid
);
}
/**
...
...
@@ -127,16 +127,16 @@ class message_future {
/**
* @brief Returns the awaited response ID.
*/
inline
const
message_id
_t
&
id
()
const
{
return
m_mid
;
}
inline
const
message_id
&
id
()
const
{
return
m_mid
;
}
message_future
(
const
message_future
&
)
=
default
;
message_future
&
operator
=
(
const
message_future
&
)
=
default
;
inline
message_future
(
const
message_id
_t
&
from
)
:
m_mid
(
from
)
{
}
inline
message_future
(
const
message_id
&
from
)
:
m_mid
(
from
)
{
}
private:
message_id
_t
m_mid
;
message_id
m_mid
;
template
<
typename
...
Fs
>
behavior
fs2bhvr
(
Fs
...
fs
)
{
...
...
@@ -169,9 +169,9 @@ class sync_handle_helper {
inline
sync_handle_helper
(
const
message_future
&
mf
)
:
m_mf
(
mf
)
{
}
template
<
typename
...
Arg
s
>
inline
message_future
::
continue_helper
operator
()(
Arg
s
&&
...
args
)
{
return
m_mf
.
then
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
inline
message_future
::
continue_helper
operator
()(
T
s
&&
...
args
)
{
return
m_mf
.
then
(
std
::
forward
<
T
s
>
(
args
)...);
}
private:
...
...
@@ -186,9 +186,9 @@ class sync_receive_helper {
inline
sync_receive_helper
(
const
message_future
&
mf
)
:
m_mf
(
mf
)
{
}
template
<
typename
...
Arg
s
>
inline
void
operator
()(
Arg
s
&&
...
args
)
{
m_mf
.
await
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
inline
void
operator
()(
T
s
&&
...
args
)
{
m_mf
.
await
(
std
::
forward
<
T
s
>
(
args
)...);
}
private:
...
...
cppa/message_id.hpp
View file @
04fc1827
...
...
@@ -42,7 +42,7 @@ struct invalid_message_id { constexpr invalid_message_id() { } };
* @brief
* @note Asynchronous messages always have an invalid message id.
*/
class
message_id
_t
:
util
::
comparable
<
message_id_t
>
{
class
message_id
:
util
::
comparable
<
message_id
>
{
static
constexpr
std
::
uint64_t
response_flag_mask
=
0x8000000000000000
;
static
constexpr
std
::
uint64_t
answered_flag_mask
=
0x4000000000000000
;
...
...
@@ -50,14 +50,14 @@ class message_id_t : util::comparable<message_id_t> {
public:
constexpr
message_id
_t
()
:
m_value
(
0
)
{
}
constexpr
message_id
()
:
m_value
(
0
)
{
}
message_id
_t
(
message_id_t
&&
)
=
default
;
message_id
_t
(
const
message_id_t
&
)
=
default
;
message_id
_t
&
operator
=
(
message_id_t
&&
)
=
default
;
message_id
_t
&
operator
=
(
const
message_id_t
&
)
=
default
;
message_id
(
message_id
&&
)
=
default
;
message_id
(
const
message_id
&
)
=
default
;
message_id
&
operator
=
(
message_id
&&
)
=
default
;
message_id
&
operator
=
(
const
message_id
&
)
=
default
;
inline
message_id
_t
&
operator
++
()
{
inline
message_id
&
operator
++
()
{
++
m_value
;
return
*
this
;
}
...
...
@@ -78,12 +78,12 @@ class message_id_t : util::comparable<message_id_t> {
return
valid
()
&&
!
is_response
();
}
inline
message_id
_t
response_id
()
const
{
return
message_id
_t
(
valid
()
?
m_value
|
response_flag_mask
:
0
);
inline
message_id
response_id
()
const
{
return
message_id
(
valid
()
?
m_value
|
response_flag_mask
:
0
);
}
inline
message_id
_t
request_id
()
const
{
return
message_id
_t
(
m_value
&
request_id_mask
);
inline
message_id
request_id
()
const
{
return
message_id
(
m_value
&
request_id_mask
);
}
inline
void
mark_as_answered
()
{
...
...
@@ -94,24 +94,24 @@ class message_id_t : util::comparable<message_id_t> {
return
m_value
;
}
static
inline
message_id
_t
from_integer_value
(
std
::
uint64_t
value
)
{
message_id
_t
result
;
static
inline
message_id
from_integer_value
(
std
::
uint64_t
value
)
{
message_id
result
;
result
.
m_value
=
value
;
return
result
;
}
static
constexpr
invalid_message_id
invalid
=
invalid_message_id
{};
constexpr
message_id
_t
(
invalid_message_id
)
:
m_value
(
0
)
{
}
constexpr
message_id
(
invalid_message_id
)
:
m_value
(
0
)
{
}
long
compare
(
const
message_id
_t
&
other
)
const
{
long
compare
(
const
message_id
&
other
)
const
{
return
(
m_value
==
other
.
m_value
)
?
0
:
((
m_value
<
other
.
m_value
)
?
-
1
:
1
);
}
private:
explicit
constexpr
message_id
_t
(
std
::
uint64_t
value
)
:
m_value
(
value
)
{
}
explicit
constexpr
message_id
(
std
::
uint64_t
value
)
:
m_value
(
value
)
{
}
std
::
uint64_t
m_value
;
...
...
cppa/network/continuable_reader.hpp
View file @
04fc1827
...
...
@@ -36,8 +36,6 @@
#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/network/protocol.hpp"
namespace
cppa
{
namespace
network
{
class
middleman
;
...
...
cppa/network/default_actor_proxy.hpp
View file @
04fc1827
...
...
@@ -48,8 +48,7 @@ class basic_memory_cache;
namespace
cppa
{
namespace
network
{
class
sync_request_info
:
public
extend
<
memory_managed
,
sync_request_info
>::
with
<
memory_cached
>
{
class
sync_request_info
:
public
extend
<
memory_managed
>::
with
<
memory_cached
>
{
friend
class
detail
::
memory
;
...
...
@@ -59,11 +58,11 @@ class sync_request_info : public extend<memory_managed,sync_request_info>::
pointer
next
;
// intrusive next pointer
actor_ptr
sender
;
// points to the sender of the message
message_id
_t
mid
;
// sync message ID
message_id
mid
;
// sync message ID
private:
sync_request_info
(
actor_ptr
sptr
,
message_id
_t
id
);
sync_request_info
(
actor_ptr
sptr
,
message_id
id
);
};
...
...
@@ -79,7 +78,7 @@ class default_actor_proxy : public actor_proxy {
void
enqueue
(
const
actor_ptr
&
sender
,
any_tuple
msg
);
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
any_tuple
msg
);
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
id
,
any_tuple
msg
);
void
link_to
(
const
actor_ptr
&
other
);
...
...
@@ -107,7 +106,7 @@ class default_actor_proxy : public actor_proxy {
void
forward_msg
(
const
actor_ptr
&
sender
,
any_tuple
msg
,
message_id
_t
mid
=
message_id_t
());
message_id
mid
=
message_id
());
default_protocol_ptr
m_proto
;
process_information_ptr
m_pinf
;
...
...
cppa/network/default_message_queue.hpp
View file @
04fc1827
...
...
@@ -45,9 +45,9 @@ class default_message_queue : public ref_counted {
typedef
value_type
&
reference
;
template
<
typename
...
Arg
s
>
void
emplace
(
Arg
s
&&
...
args
)
{
m_impl
.
emplace_back
(
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
...
T
s
>
void
emplace
(
T
s
&&
...
args
)
{
m_impl
.
emplace_back
(
std
::
forward
<
T
s
>
(
args
)...);
}
inline
bool
empty
()
const
{
return
m_impl
.
empty
();
}
...
...
cppa/network/default_peer.hpp
View file @
04fc1827
...
...
@@ -146,15 +146,6 @@ class default_peer : public continuable_io {
enqueue
({
nullptr
,
nullptr
},
msg
);
}
/*
template<typename Arg0, typename Arg1, typename... Args>
inline void enqueue(Arg0&& arg0, Arg1&& arg1, Args&&... args) {
enqueue(make_any_tuple(std::forward<Arg0>(arg0),
std::forward<Arg1>(arg1),
std::forward<Args>(args)...));
}
*/
};
typedef
intrusive_ptr
<
default_peer
>
default_peer_ptr
;
...
...
cppa/network/message_header.hpp
View file @
04fc1827
...
...
@@ -49,13 +49,13 @@ class message_header {
actor_ptr
sender
;
actor_ptr
receiver
;
message_id
_t
id
;
message_id
id
;
message_header
();
message_header
(
const
actor_ptr
&
sender
,
const
actor_ptr
&
receiver
,
message_id
_t
id
=
message_id_t
::
invalid
);
message_id
id
=
message_id
::
invalid
);
inline
void
deliver
(
any_tuple
msg
)
const
{
if
(
receiver
)
{
...
...
cppa/network/middleman.hpp
View file @
04fc1827
...
...
@@ -36,15 +36,16 @@
#include <memory>
#include <functional>
#include "cppa/network/protocol.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/continuable_reader.hpp"
#include "cppa/network/continuable_io.hpp"
namespace
cppa
{
namespace
detail
{
class
singleton_manager
;
}
}
namespace
cppa
{
namespace
network
{
class
protocol
;
typedef
intrusive_ptr
<
protocol
>
protocol_ptr
;
/**
* @brief Multiplexes asynchronous IO.
*/
...
...
cppa/network/protocol.hpp
View file @
04fc1827
...
...
@@ -39,9 +39,9 @@
#include "cppa/actor.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/intrusive_fwd_ptr.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/middleman.hpp"
namespace
cppa
{
class
actor_addressing
;
}
...
...
@@ -83,14 +83,6 @@ class protocol : public ref_counted {
void
run_later
(
std
::
function
<
void
()
>
fun
);
struct
ref_ftor
{
void
operator
()(
abstract_middleman
*
)
const
;
};
struct
deref_ftor
{
void
operator
()(
abstract_middleman
*
)
const
;
};
protected:
// note: not thread-safe; call only in run_later functor!
...
...
@@ -111,7 +103,7 @@ class protocol : public ref_counted {
private:
intrusive_
fwd_ptr
<
abstract_middleman
,
ref_ftor
,
deref_ftor
>
m_parent
;
intrusive_
ptr
<
abstract_middleman
>
m_parent
;
};
...
...
cppa/object.hpp
View file @
04fc1827
...
...
@@ -119,7 +119,7 @@ class object {
/**
* @brief Creates a (deep) copy of @p other and assigns it to @p this.
* @return @p *this
* @return
s
@p *this
*/
object
&
operator
=
(
const
object
&
other
);
...
...
cppa/on.hpp
View file @
04fc1827
...
...
@@ -136,8 +136,8 @@ struct rvalue_builder {
rvalue_builder
()
=
default
;
template
<
typename
...
Arg
s
>
rvalue_builder
(
rvalue_builder_args_ctor
,
const
Arg
s
&
...
args
)
template
<
typename
...
T
s
>
rvalue_builder
(
rvalue_builder_args_ctor
,
const
T
s
&
...
args
)
:
m_guard
(
args
...)
,
m_funs
(
args
...)
{
}
...
...
@@ -262,8 +262,8 @@ __unspecified__ val();
* This overload can be used with the wildcards {@link cppa::val val},
* {@link cppa::any_vals any_vals} and {@link cppa::arg_match arg_match}.
*/
template
<
typename
Arg0
,
typename
...
Arg
s
>
__unspecified__
on
(
const
Arg0
&
arg0
,
const
Arg
s
&
...
args
);
template
<
typename
T
,
typename
...
T
s
>
__unspecified__
on
(
const
T
&
arg
,
const
T
s
&
...
args
);
/**
* @brief Left-hand side of a partial function expression that matches types.
...
...
@@ -297,13 +297,13 @@ typedef typename detail::boxed<util::arg_match_t>::type boxed_arg_match_t;
constexpr
boxed_arg_match_t
arg_match
=
boxed_arg_match_t
();
template
<
typename
Arg0
,
typename
...
Arg
s
>
template
<
typename
T
,
typename
...
T
s
>
detail
::
rvalue_builder
<
detail
::
value_guard
<
typename
util
::
tl_filter_not
<
typename
util
::
tl_trim
<
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Arg
s
...
>
,
util
::
type_list
<
T
,
T
s
...
>
,
detail
::
boxed_and_callable_to_void
,
detail
::
implicit_conversions
>::
type
...
...
@@ -312,13 +312,13 @@ detail::rvalue_builder<
>::
type
>
,
typename
util
::
tl_map
<
util
::
type_list
<
Arg0
,
Arg
s
...
>
,
util
::
type_list
<
T
,
T
s
...
>
,
detail
::
boxed_and_not_callable_to_void
>::
type
,
util
::
type_list
<
typename
detail
::
pattern_type
<
Arg0
>::
type
,
typename
detail
::
pattern_type
<
Arg
s
>::
type
...
>
>
on
(
const
Arg0
&
arg0
,
const
Arg
s
&
...
args
)
{
return
{
detail
::
rvalue_builder_args_ctor
{},
arg
0
,
args
...};
util
::
type_list
<
typename
detail
::
pattern_type
<
T
>::
type
,
typename
detail
::
pattern_type
<
T
s
>::
type
...
>
>
on
(
const
T
&
arg
,
const
T
s
&
...
args
)
{
return
{
detail
::
rvalue_builder_args_ctor
{},
arg
,
args
...};
}
inline
detail
::
rvalue_builder
<
detail
::
empty_value_guard
,
...
...
cppa/partial_function.hpp
View file @
04fc1827
...
...
@@ -61,60 +61,54 @@ class partial_function {
public:
/** @cond PRIVATE */
typedef
intrusive_ptr
<
detail
::
behavior_impl
>
impl_ptr
;
inline
auto
as_behavior_impl
()
const
->
const
impl_ptr
&
;
partial_function
(
impl_ptr
ptr
);
static
constexpr
bool
may_have_timeout
=
false
;
/** @endcond */
partial_function
()
=
default
;
partial_function
(
partial_function
&&
)
=
default
;
partial_function
(
const
partial_function
&
)
=
default
;
partial_function
&
operator
=
(
partial_function
&&
)
=
default
;
partial_function
&
operator
=
(
const
partial_function
&
)
=
default
;
template
<
typename
...
Cases
>
partial_function
(
const
match_expr
<
Cases
...
>&
mexpr
)
:
m_impl
(
mexpr
.
as_behavior_impl
())
{
}
partial_function
(
impl_ptr
ptr
);
inline
bool
undefined
()
const
{
return
m_impl
==
nullptr
;
}
inline
bool
defined_at
(
const
any_tuple
&
value
)
{
return
(
m_impl
)
&&
m_impl
->
defined_at
(
value
);
}
template
<
typename
T
>
inline
bool
operator
()(
T
&&
arg
)
{
return
(
m_impl
)
&&
m_impl
->
invoke
(
std
::
forward
<
T
>
(
arg
));
}
inline
partial_function
or_else
(
const
partial_function
&
other
)
const
{
return
m_impl
->
or_else
(
other
.
m_impl
);
}
inline
behavior
or_else
(
const
behavior
&
other
)
const
{
return
behavior
{
m_impl
->
or_else
(
other
.
m_impl
)};
}
template
<
typename
...
Cs
>
partial_function
(
const
match_expr
<
Cs
...
>&
mexpr
);
/**
* @brief Returns @p true if this partial function is defined for the
* types of @p value, false otherwise.
*/
inline
bool
defined_at
(
const
any_tuple
&
value
);
/**
* @brief Returns @p true if this partial function was applied to
* @p args, false otherwise.
* @note This member function can return @p false even if
* {@link defined_at()} returns @p true, because {@link defined_at()}
* does <b>not</b> evaluate guards.
*/
template
<
typename
T
>
typename
std
::
conditional
<
T
::
may_have_timeout
,
behavior
,
partial_function
>::
type
or_else
(
const
T
&
arg
)
const
;
inline
bool
operator
()(
T
&&
arg
);
template
<
typename
T0
,
typename
T1
,
typename
...
Ts
>
/**
* @brief Adds a fallback which is used where
* this partial function is not defined.
*/
template
<
typename
...
Ts
>
typename
std
::
conditional
<
util
::
disjunction
<
T0
::
may_have_timeout
,
T1
::
may_have_timeout
,
Ts
::
may_have_timeout
...
>::
value
,
util
::
disjunction
<
Ts
::
may_have_timeout
...
>::
value
,
behavior
,
partial_function
>::
type
or_else
(
const
T0
&
arg0
,
const
T1
&
arg1
,
const
Ts
&
...
args
)
const
;
inline
const
impl_ptr
&
as_behavior_impl
()
const
;
or_else
(
Ts
&&
...
args
)
const
;
private:
...
...
@@ -122,45 +116,57 @@ class partial_function {
};
template
<
typename
T
,
typename
...
Ts
>
template
<
typename
T
>
typename
std
::
conditional
<
T
::
may_have_timeout
,
behavior
,
partial_function
>::
type
match_expr_convert
(
const
T
&
arg
)
{
return
{
arg
};
}
template
<
typename
T0
,
typename
T1
,
typename
...
Ts
>
typename
std
::
conditional
<
util
::
disjunction
<
T
::
may_have_timeout
,
T0
::
may_have_timeout
,
T1
::
may_have_timeout
,
Ts
::
may_have_timeout
...
>::
value
,
behavior
,
partial_function
>::
type
match_expr_convert
(
const
T
&
arg0
,
const
Ts
&
...
args
)
{
return
detail
::
match_expr_concat
(
arg0
,
args
...);
match_expr_convert
(
const
T
0
&
arg0
,
const
T1
&
arg1
,
const
Ts
&
...
args
)
{
return
detail
::
match_expr_concat
(
arg0
,
arg
1
,
arg
s
...);
}
/******************************************************************************
* inline and template member function implementations *
******************************************************************************/
inline
const
partial_function
::
impl_ptr
&
partial_function
::
as_behavior_impl
()
const
{
return
m_impl
;
template
<
typename
...
Cs
>
partial_function
::
partial_function
(
const
match_expr
<
Cs
...
>&
mexpr
)
:
m_impl
(
mexpr
.
as_behavior_impl
())
{
}
inline
bool
partial_function
::
defined_at
(
const
any_tuple
&
value
)
{
return
(
m_impl
)
&&
m_impl
->
defined_at
(
value
);
}
template
<
typename
T
>
typename
std
::
conditional
<
T
::
may_have_timeout
,
behavior
,
partial_function
>::
type
partial_function
::
or_else
(
const
T
&
arg
)
const
{
return
m_impl
->
or_else
(
arg
.
as_behavior_impl
());
inline
bool
partial_function
::
operator
()(
T
&&
arg
)
{
return
(
m_impl
)
&&
m_impl
->
invoke
(
std
::
forward
<
T
>
(
arg
));
}
template
<
typename
T0
,
typename
T1
,
typename
...
Ts
>
template
<
typename
...
Ts
>
typename
std
::
conditional
<
util
::
disjunction
<
T0
::
may_have_timeout
,
T1
::
may_have_timeout
,
Ts
::
may_have_timeout
...
>::
value
,
util
::
disjunction
<
Ts
::
may_have_timeout
...
>::
value
,
behavior
,
partial_function
>::
type
partial_function
::
or_else
(
const
T0
&
arg0
,
const
T1
&
arg1
,
const
Ts
&
...
args
)
const
{
return
m_impl
->
or_else
(
match_expr_convert
(
arg0
,
arg1
,
args
...).
as_behavior_impl
());
partial_function
::
or_else
(
Ts
&&
...
args
)
const
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
return
m_impl
->
or_else
(
tmp
.
as_behavior_impl
());
}
inline
auto
partial_function
::
as_behavior_impl
()
const
->
const
impl_ptr
&
{
return
m_impl
;
}
}
// namespace cppa
...
...
cppa/qtsupport/actor_widget_mixin.hpp
View file @
04fc1827
...
...
@@ -47,8 +47,8 @@ class actor_widget_mixin : public actor_companion_mixin<Base> {
public:
template
<
typename
...
Arg
s
>
actor_widget_mixin
(
Args
&&
...
args
)
:
super
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
}
template
<
typename
...
T
s
>
actor_widget_mixin
(
Ts
&&
...
args
)
:
super
(
std
::
forward
<
T
s
>
(
args
)...)
{
}
struct
event_type
:
public
QEvent
{
...
...
cppa/receive.hpp
View file @
04fc1827
...
...
@@ -38,62 +38,64 @@
namespace
cppa
{
#ifdef CPPA_DOCUMENTATION
/**
* @ingroup BlockingAPI
* @{
*/
/**
* @brief Dequeues the next message from the mailbox that's matched
* by @p bhvr and executes the corresponding callback.
* @param bhvr Denotes the actor's response the next incoming message.
* @brief Dequeues the next message from the mailbox that
* is matched by given behavior.
*/
void
receive
(
behavior
&
bhvr
);
template
<
typename
...
Ts
>
void
receive
(
Ts
&&
...
args
);
/**
* @brief Receives messages in an endless loop.
*
* Semantically equal to: <tt>for (;;) { receive(bhvr); }</tt>
* @param bhvr Denotes the actor's response the next incoming message.
* Semantically equal to: <tt>for (;;) { receive(...); }</tt>
*/
void
receive_loop
(
behavior
&
bhvr
);
template
<
typename
...
Ts
>
void
receive_loop
(
Ts
&&
...
args
);
/**
* @brief Receives messages as
long as @p stmt returns true
.
* @brief Receives messages as
in a range-based loop
.
*
* Semantically equal to: <tt>while (stmt()) { receive(...); }</tt>.
* Semantically equal to:
* <tt>for ( ; begin != end; ++begin) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_while([&]() { return (++i <= 10); })
* (
* on<int>() >> int_fun,
* on<float>() >> float_fun
* receive_for(i, 10) (
* on(atom("get")) >> [&]() { reply("result", i); }
* );
* @endcode
* @param stmt Lambda expression, functor or function returning a @c bool.
* @param begin First value in range.
* @param end Last value in range (excluded).
* @returns A functor implementing the loop.
*/
template
<
typename
Statement
>
auto
receive_while
(
Statement
&&
stmt
);
template
<
typename
T
>
detail
::
receive_for_helper
<
T
>
receive_for
(
T
&
begin
,
const
T
&
end
);
/**
* @brief Receives messages as
in a range-based loop
.
* @brief Receives messages as
long as @p stmt returns true
.
*
* Semantically equal to: <tt>
for ( ; begin != end; ++begin
) { receive(...); }</tt>.
* Semantically equal to: <tt>
while (stmt()
) { receive(...); }</tt>.
*
* <b>Usage example:</b>
* @code
* int i = 0;
* receive_
for(i, 10
)
* receive_
while([&]() { return (++i <= 10); }
)
* (
* on(atom("get")) >> [&]() { reply("result", i); }
* on<int>() >> int_fun,
* on<float>() >> float_fun
* );
* @endcode
* @param begin First value in range.
* @param end Last value in range (excluded).
* @param stmt Lambda expression, functor or function returning a @c bool.
* @returns A functor implementing the loop.
*/
template
<
typename
T
>
auto
receive_for
(
T
&
begin
,
const
T
&
end
);
template
<
typename
Statement
>
detail
::
receive_while_helper
<
Statement
>
receive_while
(
Statement
&&
stmt
);
/**
* @brief Receives messages until @p stmt returns true.
...
...
@@ -113,32 +115,34 @@ auto receive_for(T& begin, const T& end);
* @param bhvr Denotes the actor's response the next incoming message.
* @returns A functor providing the @c until member function.
*/
auto
do_receive
(
behavior
&
bhvr
);
template
<
typename
...
Ts
>
detail
::
do_receive_helper
do_receive
(
Ts
&&
...
args
);
#else // CPPA_DOCUMENTATION
/**
* @}
*/
inline
void
receive
(
behavior
&
bhvr
)
{
self
->
dequeue
(
bhvr
);
}
inline
void
receive
(
partial_function
&
fun
)
{
self
->
dequeue
(
fun
);
}
/******************************************************************************
* inline and template function implementations *
******************************************************************************/
template
<
typename
Arg0
,
typename
...
Args
>
void
receive
(
Arg0
&&
arg0
,
Args
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...);
receive
(
tmp
);
template
<
typename
...
Ts
>
void
receive
(
Ts
&&
...
args
)
{
static_assert
(
sizeof
...(
Ts
),
"receive() requires at least one argument"
);
self
->
dequeue
(
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...));
}
void
receive_loop
(
behavior
&
rules
);
void
receive_loop
(
behavior
&&
rules
);
void
receive_loop
(
partial_function
&
rules
);
void
receive_loop
(
partial_function
&&
rules
);
inline
void
receive_loop
(
behavior
rules
)
{
local_actor
*
sptr
=
self
;
for
(;;)
sptr
->
dequeue
(
rules
);
}
template
<
typename
Arg0
,
typename
...
Arg
s
>
void
receive_loop
(
Arg0
&&
arg0
,
Arg
s
&&
...
args
)
{
auto
tmp
=
match_expr_convert
(
std
::
forward
<
Arg0
>
(
arg0
),
std
::
forward
<
Args
>
(
args
)...)
;
receive_loop
(
tmp
);
template
<
typename
...
T
s
>
void
receive_loop
(
T
s
&&
...
args
)
{
behavior
bhvr
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
local_actor
*
sptr
=
self
;
for
(;;)
sptr
->
dequeue
(
bhvr
);
}
template
<
typename
T
>
...
...
@@ -153,13 +157,12 @@ detail::receive_while_helper<Statement> receive_while(Statement&& stmt) {
return
std
::
move
(
stmt
);
}
template
<
typename
...
Args
>
detail
::
do_receive_helper
do_receive
(
Args
&&
...
args
)
{
return
detail
::
do_receive_helper
(
std
::
forward
<
Args
>
(
args
)...);
template
<
typename
...
Ts
>
detail
::
do_receive_helper
do_receive
(
Ts
&&
...
args
)
{
behavior
bhvr
=
match_expr_convert
(
std
::
forward
<
Ts
>
(
args
)...);
return
detail
::
do_receive_helper
(
std
::
move
(
bhvr
));
}
#endif // CPPA_DOCUMENTATION
}
// namespace cppa
#endif // CPPA_RECEIVE_HPP
cppa/response_handle.hpp
View file @
04fc1827
...
...
@@ -52,7 +52,7 @@ class response_handle {
response_handle
(
const
actor_ptr
&
from
,
const
actor_ptr
&
to
,
const
message_id
_t
&
response_id
);
const
message_id
&
response_id
);
/**
* @brief Queries whether response message is still outstanding.
...
...
@@ -73,7 +73,7 @@ class response_handle {
/**
* @brief Returns the message id for the response message.
*/
inline
const
message_id
_t
&
response_id
()
const
{
return
m_id
;
}
inline
const
message_id
&
response_id
()
const
{
return
m_id
;
}
/**
* @brief Returns the actor that is going send the response message.
...
...
@@ -89,7 +89,7 @@ class response_handle {
actor_ptr
m_from
;
actor_ptr
m_to
;
message_id
_t
m_id
;
message_id
m_id
;
};
...
...
cppa/sb_actor.hpp
View file @
04fc1827
...
...
@@ -66,8 +66,8 @@ class sb_actor : public Base {
protected:
template
<
typename
...
Arg
s
>
sb_actor
(
Args
&&
...
args
)
:
Base
(
std
::
forward
<
Arg
s
>
(
args
)...)
{
}
template
<
typename
...
T
s
>
sb_actor
(
Ts
&&
...
args
)
:
Base
(
std
::
forward
<
T
s
>
(
args
)...)
{
}
};
...
...
cppa/scheduled_actor.hpp
View file @
04fc1827
...
...
@@ -38,9 +38,11 @@
#include "cppa/actor_state.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/memory.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace
cppa
{
...
...
@@ -68,7 +70,7 @@ struct has_blocking_receive<scheduled_actor> : std::true_type { };
* @brief A base class for cooperatively scheduled actors.
* @extends local_actor
*/
class
scheduled_actor
:
public
extend
<
local_actor
,
scheduled_actor
>::
with
<
mailbox_based
>
{
class
scheduled_actor
:
public
extend
<
local_actor
>::
with
<
mailbox_based
>
{
typedef
combined_type
super
;
...
...
@@ -115,13 +117,15 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
*/
inline
bool
is_hidden
()
const
;
virtual
void
run_detached
();
void
enqueue
(
const
actor_ptr
&
,
any_tuple
);
bool
chained_enqueue
(
const
actor_ptr
&
,
any_tuple
);
void
sync_enqueue
(
const
actor_ptr
&
,
message_id
_t
,
any_tuple
);
void
sync_enqueue
(
const
actor_ptr
&
,
message_id
,
any_tuple
);
bool
chained_sync_enqueue
(
const
actor_ptr
&
,
message_id
_t
,
any_tuple
);
bool
chained_sync_enqueue
(
const
actor_ptr
&
,
message_id
,
any_tuple
);
void
request_timeout
(
const
util
::
duration
&
d
);
...
...
@@ -160,8 +164,6 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
void
cleanup
(
std
::
uint32_t
reason
);
typedef
detail
::
recursive_queue_node
mailbox_element
;
typedef
intrusive
::
single_reader_queue
<
mailbox_element
,
detail
::
disposer
>
mailbox_type
;
...
...
@@ -195,7 +197,7 @@ class scheduled_actor : public extend<local_actor,scheduled_actor>::with<mailbox
bool
sync_enqueue_impl
(
actor_state
next
,
const
actor_ptr
&
sender
,
any_tuple
&
msg
,
message_id
_t
id
);
message_id
id
);
bool
m_has_pending_tout
;
std
::
uint32_t
m_pending_tout
;
...
...
cppa/scheduler.hpp
View file @
04fc1827
...
...
@@ -144,7 +144,7 @@ class scheduler {
template
<
typename
Duration
,
typename
...
Data
>
void
delayed_reply
(
const
actor_ptr
&
to
,
const
Duration
&
rel_time
,
message_id
_t
id
,
message_id
id
,
any_tuple
data
)
{
CPPA_REQUIRE
(
!
id
.
valid
()
||
id
.
is_response
());
if
(
id
.
valid
())
{
...
...
cppa/stacked.hpp
View file @
04fc1827
...
...
@@ -37,15 +37,18 @@
#include "cppa/behavior.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/util/dptr.hpp"
#include "cppa/detail/behavior_stack.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
namespace
cppa
{
/**
* @tparam Base Either @p scheduled or @p threaded.
* @brief An actor that uses the blocking API of @p libcppa and thus needs
* its own stack.
*/
template
<
class
Base
,
class
Subtype
>
class
stacked
:
public
Base
{
...
...
@@ -61,25 +64,18 @@ class stacked : public Base {
static
constexpr
auto
receive_flag
=
detail
::
rp_nestable
;
virtual
void
dequeue
(
partial_function
&
fun
)
{
m_recv_policy
.
receive
(
dthis
(),
fun
);
}
virtual
void
dequeue
(
behavior
&
bhvr
)
{
m_recv_policy
.
receive
(
dthis
(
),
bhvr
);
m_recv_policy
.
receive
(
util
::
dptr
<
Subtype
>
(
this
),
bhvr
);
}
virtual
void
dequeue_response
(
behavior
&
bhvr
,
message_id
_t
request_id
)
{
m_recv_policy
.
receive
(
dthis
(
),
bhvr
,
request_id
);
virtual
void
dequeue_response
(
behavior
&
bhvr
,
message_id
request_id
)
{
m_recv_policy
.
receive
(
util
::
dptr
<
Subtype
>
(
this
),
bhvr
,
request_id
);
}
virtual
void
run
()
{
if
(
!
dthis
()
->
m_bhvr_stack
.
empty
())
{
dthis
()
->
exec_behavior_stack
();
}
if
(
m_behavior
)
{
m_behavior
();
}
auto
dthis
=
util
::
dptr
<
Subtype
>
(
this
);
if
(
!
dthis
->
m_bhvr_stack
.
empty
())
dthis
->
exec_behavior_stack
();
if
(
m_behavior
)
m_behavior
();
}
inline
void
set_behavior
(
std
::
function
<
void
()
>
fun
)
{
...
...
@@ -91,55 +87,46 @@ class stacked : public Base {
throw
actor_exited
(
reason
);
}
virtual
void
exec_behavior_stack
()
{
this
->
m_bhvr_stack
.
exec
(
m_recv_policy
,
util
::
dptr
<
Subtype
>
(
this
));
}
protected:
template
<
typename
...
Arg
s
>
stacked
(
std
::
function
<
void
()
>
fun
,
Arg
s
&&
...
args
)
:
Base
(
std
::
forward
<
Arg
s
>
(
args
)...),
m_behavior
(
std
::
move
(
fun
))
{
}
template
<
typename
...
T
s
>
stacked
(
std
::
function
<
void
()
>
fun
,
T
s
&&
...
args
)
:
Base
(
std
::
forward
<
T
s
>
(
args
)...),
m_behavior
(
std
::
move
(
fun
))
{
}
virtual
void
do_become
(
behavior
&&
bhvr
,
bool
discard_old
)
{
become_impl
(
std
::
move
(
bhvr
),
discard_old
,
message_id
_t
());
become_impl
(
std
::
move
(
bhvr
),
discard_old
,
message_id
());
}
virtual
void
become_waiting_for
(
behavior
&&
bhvr
,
message_id_t
mid
)
{
virtual
void
become_waiting_for
(
behavior
bhvr
,
message_id
mid
)
{
become_impl
(
std
::
move
(
bhvr
),
false
,
mid
);
}
virtual
bool
has_behavior
()
{
return
static_cast
<
bool
>
(
m_behavior
)
||
!
dthis
()
->
m_bhvr_stack
.
empty
();
return
static_cast
<
bool
>
(
m_behavior
)
||
!
util
::
dptr
<
Subtype
>
(
this
)
->
m_bhvr_stack
.
empty
();
}
typedef
std
::
chrono
::
time_point
<
std
::
chrono
::
high_resolution_clock
>
timeout_type
;
virtual
timeout_type
init_timeout
(
const
util
::
duration
&
rel_time
)
=
0
;
virtual
detail
::
recursive_queue_node
*
await_message
()
=
0
;
virtual
detail
::
recursive_queue_node
*
await_message
(
const
timeout_type
&
abs_time
)
=
0
;
private:
std
::
function
<
void
()
>
m_behavior
;
detail
::
receive_policy
m_recv_policy
;
void
become_impl
(
behavior
&&
bhvr
,
bool
discard_old
,
message_id_t
mid
)
{
private:
void
become_impl
(
behavior
&&
bhvr
,
bool
discard_old
,
message_id
mid
)
{
auto
dthis
=
util
::
dptr
<
Subtype
>
(
this
);
if
(
bhvr
.
timeout
().
valid
())
{
dthis
()
->
reset_timeout
();
dthis
()
->
request_timeout
(
bhvr
.
timeout
());
dthis
->
reset_timeout
();
dthis
->
request_timeout
(
bhvr
.
timeout
());
}
if
(
!
dthis
()
->
m_bhvr_stack
.
empty
()
&&
discard_old
)
{
dthis
()
->
m_bhvr_stack
.
pop_async_back
();
if
(
!
dthis
->
m_bhvr_stack
.
empty
()
&&
discard_old
)
{
dthis
->
m_bhvr_stack
.
pop_async_back
();
}
dthis
()
->
m_bhvr_stack
.
push_back
(
std
::
move
(
bhvr
),
mid
);
dthis
->
m_bhvr_stack
.
push_back
(
std
::
move
(
bhvr
),
mid
);
}
virtual
void
exec_behavior_stack
()
{
this
->
m_bhvr_stack
.
exec
(
m_recv_policy
,
dthis
());
}
inline
Subtype
*
dthis
()
{
return
static_cast
<
Subtype
*>
(
this
);
}
};
}
// namespace cppa
...
...
cppa/thread_mapped_actor.hpp
View file @
04fc1827
...
...
@@ -43,18 +43,16 @@
#include <cstdint>
#include "cppa/atom.hpp"
#include "cppa/either.hpp"
#include "cppa/extend.hpp"
#include "cppa/stacked.hpp"
#include "cppa/threaded.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/mailbox_based.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/detail/receive_policy.hpp"
#include "cppa/detail/recursive_queue_node.hpp"
#include "cppa/intrusive/blocking_single_reader_queue.hpp"
namespace
cppa
{
...
...
@@ -66,10 +64,10 @@ template<>
struct
has_blocking_receive
<
thread_mapped_actor
>
:
std
::
true_type
{
};
/**
* @brief An actor running in its own thread.
* @brief An actor
using the blocking API
running in its own thread.
* @extends local_actor
*/
class
thread_mapped_actor
:
public
extend
<
local_actor
,
thread_mapped_actor
>::
with
<
stacked
,
mailbox_bas
ed
>
{
class
thread_mapped_actor
:
public
extend
<
local_actor
,
thread_mapped_actor
>::
with
<
mailbox_based
,
stacked
,
thread
ed
>
{
friend
class
self_type
;
// needs access to cleanup()
friend
class
scheduler_helper
;
// needs access to mailbox
...
...
@@ -88,40 +86,14 @@ class thread_mapped_actor : public extend<local_actor,thread_mapped_actor>::with
bool
initialized
()
const
;
void
enqueue
(
const
actor_ptr
&
sender
,
any_tuple
msg
);
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id_t
id
,
any_tuple
msg
);
inline
void
reset_timeout
()
{
}
inline
void
request_timeout
(
const
util
::
duration
&
)
{
}
inline
void
handle_timeout
(
behavior
&
bhvr
)
{
bhvr
.
handle_timeout
();
}
inline
void
pop_timeout
()
{
}
inline
void
push_timeout
()
{
}
inline
bool
waits_for_timeout
(
std
::
uint32_t
)
{
return
false
;
}
protected:
typedef
detail
::
recursive_queue_node
mailbox_element
;
typedef
intrusive
::
blocking_single_reader_queue
<
mailbox_element
,
detail
::
disposer
>
mailbox_type
;
void
cleanup
(
std
::
uint32_t
reason
);
private:
timeout_type
init_timeout
(
const
util
::
duration
&
rel_time
);
detail
::
recursive_queue_node
*
await_message
();
detail
::
recursive_queue_node
*
await_message
(
const
timeout_type
&
abs_time
);
bool
m_initialized
;
protected:
mailbox_type
m_mailbox
;
};
typedef
intrusive_ptr
<
thread_mapped_actor
>
thread_mapped_actor_ptr
;
...
...
cppa/
intrusive_fwd_ptr
.hpp
→
cppa/
threaded
.hpp
View file @
04fc1827
...
...
@@ -28,149 +28,142 @@
\******************************************************************************/
#ifndef CPPA_
INTRUSIVE_FWD_PTR
_HPP
#define CPPA_
INTRUSIVE_FWD_PTR
_HPP
#ifndef CPPA_
THREADED
_HPP
#define CPPA_
THREADED
_HPP
#include <memory>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include "cppa/util/comparable.hpp"
#include "cppa/mailbox_element.hpp"
#include "cppa/util/dptr.hpp"
#include "cppa/detail/sync_request_bouncer.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
namespace
cppa
{
namespace
detail
{
class
receive_policy
;
}
}
namespace
cppa
{
/**
* @brief A reference counting smart pointer implementation that
* can be used with forward declarated types.
* @warning libcppa assumes T is derived from ref_counted and
* implicitly converts intrusive_fwd_ptr to intrusive_ptr
* @relates intrusive_ptr
* @relates ref_counted
*/
template
<
typename
T
,
typename
Ref
,
typename
Deref
>
class
intrusive_fwd_ptr
:
util
::
comparable
<
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>
>
,
util
::
comparable
<
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>
,
const
T
*>
,
util
::
comparable
<
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>
,
std
::
nullptr_t
>
{
template
<
class
Base
,
class
Subtype
>
class
threaded
:
public
Base
{
friend
class
detail
::
receive_policy
;
typedef
std
::
unique_lock
<
std
::
mutex
>
lock_type
;
public:
typedef
T
*
pointer
;
typedef
const
T
*
const_pointer
;
typedef
T
element_type
;
typedef
T
&
reference
;
typedef
const
T
&
const_reference
;
template
<
typename
...
Ts
>
threaded
(
Ts
&&
...
args
)
:
Base
(
std
::
forward
<
Ts
>
(
args
)...)
{
}
intrusive_fwd_ptr
(
pointer
raw_ptr
=
nullptr
,
Ref
ref
=
Ref
(),
Deref
deref
=
Deref
())
:
m_ref
(
std
::
move
(
ref
)),
m_deref
(
std
::
move
(
deref
))
{
set_ptr
(
raw_ptr
);
}
inline
void
reset_timeout
()
{
}
intrusive_fwd_ptr
(
intrusive_fwd_ptr
&&
other
)
:
m_ref
(
std
::
move
(
other
.
m_ref
))
,
m_deref
(
std
::
move
(
m_deref
))
,
m_ptr
(
other
.
release
())
{
}
inline
void
request_timeout
(
const
util
::
duration
&
)
{
}
intrusive_fwd_ptr
(
const
intrusive_fwd_ptr
&
other
)
:
m_ref
(
other
.
m_ref
),
m_deref
(
other
.
m_deref
)
{
set_ptr
(
other
.
get
());
}
inline
void
handle_timeout
(
behavior
&
bhvr
)
{
bhvr
.
handle_timeout
();
}
~
intrusive_fwd_ptr
()
{
if
(
m_ptr
)
m_deref
(
m_ptr
);
}
inline
void
pop_timeout
()
{
}
inline
void
swap
(
intrusive_fwd_ptr
&
other
)
{
std
::
swap
(
m_ptr
,
other
.
m_ptr
);
}
inline
void
push_timeout
()
{
}
/**
* @brief Returns the raw pointer without modifying reference count.
*/
pointer
release
()
{
auto
result
=
m_ptr
;
m_ptr
=
nullptr
;
return
result
;
}
inline
bool
waits_for_timeout
(
std
::
uint32_t
)
{
return
false
;
}
/**
* @brief Sets this pointer to @p ptr without modifying reference count.
*/
void
adopt
(
pointer
ptr
)
{
reset
();
m_ptr
=
ptr
;
mailbox_element
*
pop
()
{
wait_for_data
();
return
this
->
m_mailbox
.
try_pop
();
}
void
reset
(
pointer
new_value
=
nullptr
)
{
if
(
m_ptr
)
m_deref
(
m_ptr
);
set_ptr
(
new_value
);
inline
mailbox_element
*
try_pop
()
{
return
this
->
m_mailbox
.
try_pop
();
}
template
<
typename
...
Args
>
void
emplace
(
Args
&&
...
args
)
{
re
set
(
new
T
(
std
::
forward
<
Args
>
(
args
)...))
;
template
<
typename
TimePoint
>
mailbox_element
*
try_pop
(
const
TimePoint
&
abs_time
)
{
re
turn
(
timed_wait_for_data
(
abs_time
))
?
try_pop
()
:
nullptr
;
}
intrusive_fwd_ptr
&
operator
=
(
pointer
ptr
)
{
reset
(
ptr
);
return
*
this
;
bool
push_back
(
mailbox_element
*
new_element
)
{
switch
(
this
->
m_mailbox
.
enqueue
(
new_element
))
{
case
intrusive
:
:
first_enqueued
:
{
lock_type
guard
(
m_mtx
);
m_cv
.
notify_one
();
return
true
;
}
default:
return
true
;
case
intrusive
:
:
queue_closed
:
return
false
;
}
intrusive_fwd_ptr
&
operator
=
(
intrusive_fwd_ptr
&&
other
)
{
swap
(
other
);
return
*
this
;
}
intrusive_fwd_ptr
&
operator
=
(
const
intrusive_fwd_ptr
&
other
)
{
intrusive_fwd_ptr
tmp
(
other
);
swap
(
tmp
);
return
*
this
;
void
run_detached
()
{
auto
dthis
=
util
::
dptr
<
Subtype
>
(
this
);
dthis
->
init
();
dthis
->
m_bhvr_stack
.
exec
(
dthis
->
m_recv_policy
,
dthis
);
dthis
->
on_exit
();
}
inline
pointer
get
()
const
{
return
m_ptr
;
}
protected:
inline
pointer
operator
->
()
const
{
return
m_ptr
;
}
typedef
threaded
combined_type
;
inline
reference
operator
*
()
const
{
return
*
m_ptr
;
}
virtual
void
enqueue
(
const
actor_ptr
&
sender
,
any_tuple
msg
)
{
auto
ptr
=
this
->
new_mailbox_element
(
sender
,
std
::
move
(
msg
));
push_back
(
ptr
);
}
inline
bool
operator
!
()
const
{
return
m_ptr
==
nullptr
;
}
virtual
void
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
id
,
any_tuple
msg
)
{
auto
ptr
=
this
->
new_mailbox_element
(
sender
,
std
::
move
(
msg
),
id
);
if
(
!
push_back
(
ptr
))
{
detail
::
sync_request_bouncer
f
{
this
->
exit_reason
()};
f
(
sender
,
id
);
}
}
inline
explicit
operator
bool
()
const
{
return
m_ptr
!=
nullptr
;
}
typedef
std
::
chrono
::
high_resolution_clock
::
time_point
timeout_type
;
inline
ptrdiff_t
compare
(
const_pointer
ptr
)
const
{
return
static_cast
<
ptrdiff_t
>
(
get
()
-
ptr
);
timeout_type
init_timeout
(
const
util
::
duration
&
rel_time
)
{
auto
result
=
std
::
chrono
::
high_resolution_clock
::
now
();
result
+=
rel_time
;
return
result
;
}
inline
ptrdiff_t
compare
(
const
intrusive_fwd_ptr
&
other
)
const
{
return
compare
(
other
.
get
()
);
mailbox_element
*
await_message
()
{
return
pop
(
);
}
inline
ptrdiff_t
compare
(
std
::
nullptr_t
)
const
{
return
reinterpret_cast
<
ptrdiff_t
>
(
get
()
);
mailbox_element
*
await_message
(
const
timeout_type
&
abs_time
)
{
return
try_pop
(
abs_time
);
}
private:
Ref
m_ref
;
Deref
m_deref
;
pointer
m_ptr
;
bool
timed_wait_for_data
(
const
timeout_type
&
abs_time
)
{
CPPA_REQUIRE
(
not
this
->
m_mailbox
.
closed
());
if
(
this
->
m_mailbox
.
empty
())
{
lock_type
guard
(
m_mtx
);
while
(
this
->
m_mailbox
.
empty
())
{
if
(
m_cv
.
wait_until
(
guard
,
abs_time
)
==
std
::
cv_status
::
timeout
)
{
return
false
;
}
}
}
return
true
;
}
inline
void
set_ptr
(
pointer
raw_ptr
)
{
m_ptr
=
raw_ptr
;
if
(
raw_ptr
)
m_ref
(
raw_ptr
);
void
wait_for_data
()
{
if
(
this
->
m_mailbox
.
empty
())
{
lock_type
guard
(
m_mtx
);
while
(
this
->
m_mailbox
.
empty
())
m_cv
.
wait
(
guard
);
}
}
};
std
::
mutex
m_mtx
;
std
::
condition_variable
m_cv
;
/**
* @relates intrusive_ptr
*/
template
<
typename
T
,
typename
Ref
,
typename
Deref
>
inline
bool
operator
==
(
const
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>&
lhs
,
const
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>&
rhs
)
{
return
lhs
.
get
()
==
rhs
.
get
();
}
/**
* @relates intrusive_ptr
*/
template
<
typename
T
,
typename
Ref
,
typename
Deref
>
inline
bool
operator
!=
(
const
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>&
lhs
,
const
intrusive_fwd_ptr
<
T
,
Ref
,
Deref
>&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
};
}
// namespace cppa
#endif // CPPA_
INTRUSIVE_FWD_PTR
_HPP
#endif // CPPA_
THREADED
_HPP
cppa/tpartial_function.hpp
View file @
04fc1827
...
...
@@ -43,22 +43,22 @@
namespace
cppa
{
template
<
class
Expr
,
class
Guard
,
typename
Result
,
typename
...
Arg
s
>
template
<
class
Expr
,
class
Guard
,
typename
Result
,
typename
...
T
s
>
class
tpartial_function
{
typedef
typename
util
::
get_callable_trait
<
Expr
>::
type
ctrait
;
typedef
typename
ctrait
::
arg_types
ctrait_args
;
static
constexpr
size_t
num_expr_args
=
util
::
tl_size
<
ctrait_args
>::
value
;
static_assert
(
util
::
tl_exists
<
util
::
type_list
<
Arg
s
...
>
,
static_assert
(
util
::
tl_exists
<
util
::
type_list
<
T
s
...
>
,
std
::
is_rvalue_reference
>::
value
==
false
,
"partial functions using rvalue arguments are not supported"
);
public:
typedef
util
::
type_list
<
Arg
s
...
>
arg_types
;
typedef
util
::
type_list
<
T
s
...
>
arg_types
;
static
constexpr
size_t
num_arguments
=
sizeof
...(
Arg
s
);
static
constexpr
size_t
num_arguments
=
sizeof
...(
T
s
);
static
constexpr
bool
manipulates_args
=
util
::
tl_exists
<
arg_types
,
util
::
is_mutable_ref
>::
value
;
...
...
@@ -78,11 +78,11 @@ class tpartial_function {
tpartial_function
(
const
tpartial_function
&
)
=
default
;
bool
defined_at
(
Arg
s
...
args
)
const
{
bool
defined_at
(
T
s
...
args
)
const
{
return
m_guard
(
args
...);
}
result_type
operator
()(
Arg
s
...
args
)
const
{
result_type
operator
()(
T
s
...
args
)
const
{
auto
targs
=
std
::
forward_as_tuple
(
args
...);
auto
indices
=
util
::
get_right_indices
<
num_expr_args
>
(
targs
);
return
util
::
apply_args
(
m_expr
,
targs
,
indices
);
...
...
@@ -95,34 +95,34 @@ class tpartial_function {
};
template
<
class
Expr
,
class
Guard
,
typename
Arg
s
,
template
<
class
Expr
,
class
Guard
,
typename
T
s
,
typename
Result
=
util
::
void_type
,
size_t
Step
=
0
>
struct
get_tpartial_function
;
template
<
class
Expr
,
class
Guard
,
typename
...
Arg
s
,
typename
Result
>
struct
get_tpartial_function
<
Expr
,
Guard
,
util
::
type_list
<
Arg
s
...
>
,
Result
,
1
>
{
typedef
tpartial_function
<
Expr
,
Guard
,
Result
,
Arg
s
...
>
type
;
template
<
class
Expr
,
class
Guard
,
typename
...
T
s
,
typename
Result
>
struct
get_tpartial_function
<
Expr
,
Guard
,
util
::
type_list
<
T
s
...
>
,
Result
,
1
>
{
typedef
tpartial_function
<
Expr
,
Guard
,
Result
,
T
s
...
>
type
;
};
template
<
class
Expr
,
class
Guard
,
typename
...
Arg
s
>
template
<
class
Expr
,
class
Guard
,
typename
...
T
s
>
struct
get_tpartial_function
<
Expr
,
Guard
,
util
::
type_list
<
Arg
s
...
>
,
util
::
void_type
,
0
>
{
util
::
type_list
<
T
s
...
>
,
util
::
void_type
,
0
>
{
typedef
typename
util
::
get_callable_trait
<
Expr
>::
type
ctrait
;
typedef
typename
ctrait
::
arg_types
arg_types
;
static_assert
(
util
::
tl_size
<
arg_types
>::
value
<=
sizeof
...(
Arg
s
),
static_assert
(
util
::
tl_size
<
arg_types
>::
value
<=
sizeof
...(
T
s
),
"Functor takes too much arguments"
);
typedef
typename
get_tpartial_function
<
Expr
,
Guard
,
// fill arg_types of Expr from left with const
Arg
s&
// fill arg_types of Expr from left with const
T
s&
typename
util
::
tl_zip
<
typename
util
::
tl_pad_left
<
typename
ctrait
::
arg_types
,
sizeof
...(
Arg
s
)
sizeof
...(
T
s
)
>::
type
,
util
::
type_list
<
const
Arg
s
&
...
>
,
util
::
type_list
<
const
T
s
&
...
>
,
util
::
left_or_right
>::
type
,
typename
ctrait
::
result_type
,
...
...
cppa/util/apply_args.hpp
View file @
04fc1827
...
...
@@ -44,16 +44,16 @@ inline auto apply_args(F& f, Tuple& tup, util::int_list<Is...>)
return
f
(
get_cv_aware
<
Is
>
(
tup
)...);
}
template
<
typename
F
,
class
Tuple
,
long
...
Is
,
typename
...
Arg
s
>
inline
auto
apply_args_prefixed
(
F
&
f
,
Tuple
&
tup
,
util
::
int_list
<
Is
...
>
,
Arg
s
&&
...
args
)
->
decltype
(
f
(
std
::
forward
<
Arg
s
>
(
args
)...,
get_cv_aware
<
Is
>
(
tup
)...))
{
return
f
(
std
::
forward
<
Arg
s
>
(
args
)...,
get_cv_aware
<
Is
>
(
tup
)...);
template
<
typename
F
,
class
Tuple
,
long
...
Is
,
typename
...
T
s
>
inline
auto
apply_args_prefixed
(
F
&
f
,
Tuple
&
tup
,
util
::
int_list
<
Is
...
>
,
T
s
&&
...
args
)
->
decltype
(
f
(
std
::
forward
<
T
s
>
(
args
)...,
get_cv_aware
<
Is
>
(
tup
)...))
{
return
f
(
std
::
forward
<
T
s
>
(
args
)...,
get_cv_aware
<
Is
>
(
tup
)...);
}
template
<
typename
F
,
class
Tuple
,
long
...
Is
,
typename
...
Arg
s
>
inline
auto
apply_args_suffxied
(
F
&
f
,
Tuple
&
tup
,
util
::
int_list
<
Is
...
>
,
Arg
s
&&
...
args
)
->
decltype
(
f
(
get_cv_aware
<
Is
>
(
tup
)...,
std
::
forward
<
Arg
s
>
(
args
)...))
{
return
f
(
get_cv_aware
<
Is
>
(
tup
)...,
std
::
forward
<
Arg
s
>
(
args
)...);
template
<
typename
F
,
class
Tuple
,
long
...
Is
,
typename
...
T
s
>
inline
auto
apply_args_suffxied
(
F
&
f
,
Tuple
&
tup
,
util
::
int_list
<
Is
...
>
,
T
s
&&
...
args
)
->
decltype
(
f
(
get_cv_aware
<
Is
>
(
tup
)...,
std
::
forward
<
T
s
>
(
args
)...))
{
return
f
(
get_cv_aware
<
Is
>
(
tup
)...,
std
::
forward
<
T
s
>
(
args
)...);
}
}
}
// namespace cppa::util
...
...
cppa/util/buffer.hpp
View file @
04fc1827
...
...
@@ -45,7 +45,7 @@ enum buffer_write_policy {
};
/**
*
*
@brief
*/
class
buffer
{
...
...
cppa/util/callable_trait.hpp
View file @
04fc1827
...
...
@@ -36,60 +36,63 @@
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/conjunction.hpp"
namespace
cppa
{
namespace
util
{
template
<
typename
Signature
>
struct
callable_trait
;
// member
function pointer (const)
template
<
class
C
,
typename
Result
Type
,
typename
...
Arg
s
>
struct
callable_trait
<
Result
Type
(
C
::*
)(
Arg
s
...)
const
>
{
typedef
Result
Type
result_type
;
typedef
type_list
<
Arg
s
...
>
arg_types
;
// member
const function pointer
template
<
class
C
,
typename
Result
,
typename
...
T
s
>
struct
callable_trait
<
Result
(
C
::*
)(
T
s
...)
const
>
{
typedef
Result
result_type
;
typedef
type_list
<
T
s
...
>
arg_types
;
};
// member function pointer
template
<
class
C
,
typename
Result
Type
,
typename
...
Arg
s
>
struct
callable_trait
<
Result
Type
(
C
::*
)(
Arg
s
...)
>
{
typedef
Result
Type
result_type
;
typedef
type_list
<
Arg
s
...
>
arg_types
;
template
<
class
C
,
typename
Result
,
typename
...
T
s
>
struct
callable_trait
<
Result
(
C
::*
)(
T
s
...)
>
{
typedef
Result
result_type
;
typedef
type_list
<
T
s
...
>
arg_types
;
};
// good ol' function
template
<
typename
Result
Type
,
typename
...
Arg
s
>
struct
callable_trait
<
Result
Type
(
Arg
s
...)
>
{
typedef
Result
Type
result_type
;
typedef
type_list
<
Arg
s
...
>
arg_types
;
template
<
typename
Result
,
typename
...
T
s
>
struct
callable_trait
<
Result
(
T
s
...)
>
{
typedef
Result
result_type
;
typedef
type_list
<
T
s
...
>
arg_types
;
};
// good ol' function pointer
template
<
typename
Result
Type
,
typename
...
Arg
s
>
struct
callable_trait
<
Result
Type
(
*
)(
Arg
s
...)
>
{
typedef
Result
Type
result_type
;
typedef
type_list
<
Arg
s
...
>
arg_types
;
template
<
typename
Result
,
typename
...
T
s
>
struct
callable_trait
<
Result
(
*
)(
T
s
...)
>
{
typedef
Result
result_type
;
typedef
type_list
<
T
s
...
>
arg_types
;
};
template
<
bool
IsFun
,
bool
IsMemberFun
,
typename
C
>
// matches (IsFun || IsMemberFun)
template
<
bool
IsFun
,
bool
IsMemberFun
,
typename
T
>
struct
get_callable_trait_helper
{
typedef
callable_trait
<
C
>
type
;
typedef
callable_trait
<
T
>
type
;
};
// assume functor providing operator()
template
<
typename
C
>
struct
get_callable_trait_helper
<
false
,
false
,
C
>
{
// assuming functor
typedef
callable_trait
<
decltype
(
&
C
::
operator
())
>
type
;
};
template
<
typename
C
>
template
<
typename
T
>
struct
get_callable_trait
{
typedef
typename
rm_ref
<
C
>::
type
fun_type
;
typedef
typename
get_callable_trait_helper
<
(
std
::
is_function
<
fun_type
>::
value
||
std
::
is_function
<
typename
std
::
remove_pointer
<
fun_type
>::
type
>::
value
),
std
::
is_member_function_pointer
<
fun_type
>::
value
,
fun_type
>::
type
// type without cv qualifiers
typedef
typename
rm_ref
<
T
>::
type
bare_type
;
// if type is a function pointer, this typedef identifies the function
typedef
typename
std
::
remove_pointer
<
bare_type
>::
type
fun_type
;
typedef
typename
get_callable_trait_helper
<
std
::
is_function
<
bare_type
>::
value
||
std
::
is_function
<
fun_type
>::
value
,
std
::
is_member_function_pointer
<
bare_type
>::
value
,
bare_type
>::
type
type
;
typedef
typename
type
::
result_type
result_type
;
typedef
typename
type
::
arg_types
arg_types
;
...
...
@@ -101,51 +104,6 @@ struct get_arg_types {
typedef
typename
trait_type
::
arg_types
types
;
};
template
<
typename
T
>
struct
is_callable
{
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
C
>::
result_type
*
=
nullptr
)
{
return
true
;
}
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
decltype
(
&
C
::
operator
())
>::
result_type
*
=
nullptr
)
{
return
true
;
}
static
void
_fun
(
void
*
)
{
}
typedef
decltype
(
_fun
(
static_cast
<
typename
rm_ref
<
T
>::
type
*>
(
nullptr
)))
result_type
;
public:
static
constexpr
bool
value
=
std
::
is_same
<
bool
,
result_type
>::
value
;
};
template
<
typename
...
Ts
>
struct
all_callable
{
static
constexpr
bool
value
=
conjunction
<
is_callable
<
Ts
>
...
>::
value
;
};
template
<
bool
IsCallable
,
typename
C
>
struct
get_result_type_impl
{
typedef
typename
get_callable_trait
<
C
>::
type
trait_type
;
typedef
typename
trait_type
::
result_type
type
;
};
template
<
typename
C
>
struct
get_result_type_impl
<
false
,
C
>
{
typedef
void_type
type
;
};
template
<
typename
C
>
struct
get_result_type
{
typedef
typename
get_result_type_impl
<
is_callable
<
C
>::
value
,
C
>::
type
type
;
};
}
}
// namespace cppa::util
#endif // CPPA_UTIL_CALLABLE_TRAIT
cppa/util/
if_else
.hpp
→
cppa/util/
dptr
.hpp
View file @
04fc1827
...
...
@@ -28,34 +28,33 @@
\******************************************************************************/
#ifndef CPPA_
IF_ELSE
_HPP
#define CPPA_
IF_ELSE
_HPP
#ifndef CPPA_
DTHIS
_HPP
#define CPPA_
DTHIS
_HPP
#include
"cppa/util/wrapped.hpp"
#include
<type_traits>
namespace
cppa
{
namespace
util
{
// if (IfStmt == true) type = T; else type = Else::type;
template
<
bool
IfStmt
,
typename
T
,
class
Else
>
struct
if_else_c
{
typedef
T
type
;
};
template
<
typename
T
,
class
Else
>
struct
if_else_c
<
false
,
T
,
Else
>
{
typedef
typename
Else
::
type
type
;
};
/**
* @brief A conditinal expression for types that allows
* nested statements (unlike std::conditional).
*
* @c type is defined as @p T if <tt>IfStmt == true</tt>;
* otherwise @c type is defined as @p Else::type.
* @brief Returns <tt>static_cast<Subtype*>(ptr)</tt> if @p Subtype is a
* derived type of @p MixinType, returns @p ptr without cast otherwise.
*/
template
<
class
Stmt
,
typename
T
,
class
Else
>
struct
if_else
:
if_else_c
<
Stmt
::
value
,
T
,
Else
>
{
};
template
<
class
Subtype
,
class
MixinType
>
typename
std
::
conditional
<
std
::
is_base_of
<
MixinType
,
Subtype
>::
value
,
Subtype
,
MixinType
>::
type
*
dptr
(
MixinType
*
ptr
)
{
typedef
typename
std
::
conditional
<
std
::
is_base_of
<
MixinType
,
Subtype
>::
value
,
Subtype
,
MixinType
>::
type
result_type
;
return
static_cast
<
result_type
*>
(
ptr
);
}
}
}
// namespace cppa::util
#endif // CPPA_
IF_ELSE
_HPP
#endif // CPPA_
DTHIS
_HPP
cppa/
detail/channel
.hpp
→
cppa/
util/get_result_type
.hpp
View file @
04fc1827
...
...
@@ -28,20 +28,30 @@
\******************************************************************************/
#ifndef CPPA_
CHANNEL
_HPP
#define CPPA_
CHANNEL
_HPP
#ifndef CPPA_
GET_RESULT_TYPE
_HPP
#define CPPA_
GET_RESULT_TYPE
_HPP
#include "cppa/ref_counted.hpp"
#include "cppa/util/is_callable.hpp"
#include "cppa/util/callable_trait.hpp"
namespace
cppa
{
class
message
;
}
namespace
cppa
{
namespace
util
{
namespace
cppa
{
namespace
detail
{
template
<
bool
IsCallable
,
typename
C
>
struct
get_result_type_impl
{
typedef
typename
get_callable_trait
<
C
>::
type
trait_type
;
typedef
typename
trait_type
::
result_type
type
;
};
template
<
typename
C
>
struct
get_result_type_impl
<
false
,
C
>
{
typedef
void_type
type
;
};
// public part of the actor interface
struct
channel
:
ref_counted
{
virtual
void
enqueue_msg
(
const
message
&
msg
)
=
0
;
template
<
typename
C
>
struct
get_result_type
{
typedef
typename
get_result_type_impl
<
is_callable
<
C
>::
value
,
C
>::
type
type
;
};
}
}
// namespace cppa::
deta
il
}
}
// namespace cppa::
ut
il
#endif // CPPA_
CHANNEL
_HPP
#endif // CPPA_
GET_RESULT_TYPE
_HPP
src/receive.c
pp
→
cppa/util/is_callable.h
pp
View file @
04fc1827
...
...
@@ -28,33 +28,43 @@
\******************************************************************************/
#i
nclude "cppa/cppa.hpp"
#
include "cppa/receive.hpp"
#i
fndef CPPA_IS_CALLABLE_HPP
#
define CPPA_IS_CALLABLE_HPP
namespace
cppa
{
#include "cppa/util/conjunction.hpp"
#include "cppa/util/callable_trait.hpp"
void
receive_loop
(
behavior
&
rules
)
{
local_actor
*
sptr
=
self
;
for
(;;)
{
sptr
->
dequeue
(
rules
);
}
}
namespace
cppa
{
namespace
util
{
template
<
typename
T
>
struct
is_callable
{
void
receive_loop
(
behavior
&&
rules
)
{
behavior
tmp
(
std
::
move
(
rules
));
receive_loop
(
tmp
)
;
}
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
C
>::
result_type
*
=
nullptr
)
{
return
true
;
}
void
receive_loop
(
partial_function
&
rules
)
{
local_actor
*
sptr
=
self
;
for
(;;)
{
sptr
->
dequeue
(
rules
);
template
<
typename
C
>
static
bool
_fun
(
C
*
,
typename
callable_trait
<
decltype
(
&
C
::
operator
())
>::
result_type
*
=
nullptr
)
{
return
true
;
}
}
void
receive_loop
(
partial_function
&&
rules
)
{
partial_function
tmp
(
std
::
move
(
rules
));
receive_loop
(
tmp
);
}
static
void
_fun
(
void
*
)
{
}
typedef
decltype
(
_fun
(
static_cast
<
typename
rm_ref
<
T
>::
type
*>
(
nullptr
)))
result_type
;
public:
static
constexpr
bool
value
=
std
::
is_same
<
bool
,
result_type
>::
value
;
};
template
<
typename
...
Ts
>
struct
all_callable
{
static
constexpr
bool
value
=
conjunction
<
is_callable
<
Ts
>
...
>::
value
;
};
}
}
// namespace cppa::util
}
// namespace cppa
#endif // CPPA_IS_CALLABLE_HPP
cppa/util/purge_refs.hpp
View file @
04fc1827
...
...
@@ -35,6 +35,7 @@
#include "cppa/guard_expr.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/rebindable_reference.hpp"
namespace
cppa
{
namespace
util
{
...
...
@@ -44,12 +45,12 @@ struct purge_refs_impl {
};
template
<
typename
T
>
struct
purge_refs_impl
<
ge_reference_wrapper
<
T
>
>
{
struct
purge_refs_impl
<
util
::
rebindable_reference
<
T
>
>
{
typedef
T
type
;
};
template
<
typename
T
>
struct
purge_refs_impl
<
ge_mutable_reference_wrapper
<
T
>
>
{
struct
purge_refs_impl
<
util
::
rebindable_reference
<
const
T
>
>
{
typedef
T
type
;
};
...
...
@@ -58,6 +59,11 @@ struct purge_refs_impl<std::reference_wrapper<T> > {
typedef
T
type
;
};
template
<
typename
T
>
struct
purge_refs_impl
<
std
::
reference_wrapper
<
const
T
>
>
{
typedef
T
type
;
};
/**
* @brief Removes references and reference wrappers.
*/
...
...
cppa/util/rebindable_reference.hpp
0 → 100644
View file @
04fc1827
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_REBINDABLE_REFERENCE_HPP
#define CPPA_REBINDABLE_REFERENCE_HPP
#include "cppa/config.hpp"
#include "cppa/util/get_result_type.hpp"
namespace
cppa
{
namespace
util
{
template
<
typename
T
>
struct
call_helper
{
typedef
typename
get_result_type
<
T
>::
type
result_type
;
template
<
typename
...
Ts
>
result_type
operator
()(
T
&
f
,
const
Ts
&
...
args
)
const
{
return
f
(
std
::
forward
<
Ts
>
(
args
)...);
}
};
template
<
>
struct
call_helper
<
bool
>
{
typedef
bool
result_type
;
bool
operator
()(
const
bool
&
value
)
const
{
return
value
;
}
};
template
<
>
struct
call_helper
<
const
bool
>
:
call_helper
<
bool
>
{
};
/**
* @brief A reference wrapper similar to std::reference_wrapper, but
* allows rebinding the reference. Note that this wrapper can
* be 'dangling', because it provides a default constructor.
*/
template
<
typename
T
>
class
rebindable_reference
{
public:
rebindable_reference
()
:
m_ptr
(
nullptr
)
{
}
rebindable_reference
(
T
&
value
)
:
m_ptr
(
&
value
)
{
}
template
<
typename
U
>
rebindable_reference
(
const
rebindable_reference
<
U
>&
other
)
:
m_ptr
(
other
.
ptr
())
{
}
inline
bool
bound
()
const
{
return
m_ptr
!=
nullptr
;
}
inline
void
rebind
(
T
&
value
)
{
m_ptr
=
&
value
;
}
template
<
typename
U
>
inline
void
rebind
(
const
rebindable_reference
<
U
>&
other
)
{
m_ptr
=
other
.
ptr
();
}
inline
T
*
ptr
()
const
{
CPPA_REQUIRE
(
bound
());
return
m_ptr
;
}
inline
T
&
get
()
const
{
CPPA_REQUIRE
(
bound
());
return
*
m_ptr
;
}
inline
operator
T
&
()
const
{
CPPA_REQUIRE
(
bound
());
return
*
m_ptr
;
}
template
<
typename
...
Ts
>
typename
call_helper
<
T
>::
result_type
operator
()(
Ts
&&
...
args
)
{
call_helper
<
T
>
f
;
return
f
(
get
(),
std
::
forward
<
Ts
>
(
args
)...);
}
private:
T
*
m_ptr
;
};
}
}
// namespace cppa::util
#endif // CPPA_REBINDABLE_REFERENCE_HPP
cppa/util/replace_type.hpp
View file @
04fc1827
...
...
@@ -54,8 +54,7 @@ namespace cppa { namespace util {
template
<
typename
What
,
typename
With
,
typename
...
IfStmt
>
struct
replace_type
{
static
constexpr
bool
do_replace
=
disjunction
<
IfStmt
::
value
...
>::
value
;
typedef
typename
detail
::
replace_type
<
do_replace
,
What
,
With
>::
type
type
;
typedef
typename
detail
::
replace_type
<
do_replace
,
What
,
With
>::
type
type
;
};
}
}
// namespace cppa::util
...
...
cppa/util/static_foreach.hpp
deleted
100644 → 0
View file @
16cb9399
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2013 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_STATIC_FOREACH_HPP
#define CPPA_STATIC_FOREACH_HPP
#include "cppa/get.hpp"
namespace
cppa
{
namespace
util
{
template
<
bool
BeginLessEnd
,
size_t
Begin
,
size_t
End
>
struct
static_foreach_impl
{
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_
(
const
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
f
(
get
<
Begin
>
(
c
),
std
::
forward
<
Args
>
(
args
)...);
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>
::
_
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_ref
(
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
f
(
get_ref
<
Begin
>
(
c
),
std
::
forward
<
Args
>
(
args
)...);
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>
::
_ref
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_auto
(
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
_ref
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
void
_auto
(
const
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
_
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
bool
eval
(
const
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
return
f
(
get
<
Begin
>
(
c
),
std
::
forward
<
Args
>
(
args
)...)
&&
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>
::
eval
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
template
<
typename
Container
,
typename
Fun
,
typename
...
Args
>
static
inline
bool
eval_or
(
const
Container
&
c
,
Fun
&
f
,
Args
&&
...
args
)
{
return
f
(
get
<
Begin
>
(
c
),
std
::
forward
<
Args
>
(
args
)...)
||
static_foreach_impl
<
(
Begin
+
1
<
End
),
Begin
+
1
,
End
>
::
eval_or
(
c
,
f
,
std
::
forward
<
Args
>
(
args
)...);
}
};
template
<
size_t
X
,
size_t
Y
>
struct
static_foreach_impl
<
false
,
X
,
Y
>
{
template
<
typename
...
Args
>
static
inline
void
_
(
Args
&&
...)
{
}
template
<
typename
...
Args
>
static
inline
void
_ref
(
Args
&&
...)
{
}
template
<
typename
...
Args
>
static
inline
void
_auto
(
Args
&&
...)
{
}
template
<
typename
...
Args
>
static
inline
bool
eval
(
Args
&&
...)
{
return
true
;
}
template
<
typename
...
Args
>
static
inline
bool
eval_or
(
Args
&&
...)
{
return
false
;
}
};
/**
* @ingroup MetaProgramming
* @brief A for loop that can be used with tuples.
*/
template
<
size_t
Begin
,
size_t
End
>
struct
static_foreach
:
static_foreach_impl
<
(
Begin
<
End
),
Begin
,
End
>
{
};
}
}
// namespace cppa::util
#endif // CPPA_STATIC_FOREACH_HPP
cppa/util/type_list.hpp
View file @
04fc1827
...
...
@@ -36,7 +36,6 @@
#include "cppa/util/at.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/type_pair.hpp"
#include "cppa/util/void_type.hpp"
...
...
@@ -911,10 +910,10 @@ struct tl_is_zipped {
*/
template
<
class
List
,
typename
What
=
void_type
>
struct
tl_trim
{
typedef
typename
util
::
if_else
<
std
::
is_same
<
typename
tl_back
<
List
>::
type
,
What
>
,
typedef
typename
std
::
conditional
<
std
::
is_same
<
typename
tl_back
<
List
>::
type
,
What
>::
value
,
typename
tl_trim
<
typename
tl_pop_back
<
List
>::
type
,
What
>::
type
,
util
::
wrapped
<
List
>
List
>::
type
type
;
};
...
...
cppa/util/wrapped.hpp
View file @
04fc1827
...
...
@@ -35,7 +35,7 @@ namespace cppa { namespace util {
/**
* @ingroup MetaProgramming
* @brief A
type wrapper as used in {@link cppa::util::if_else if_else}
.
* @brief A
simple type wrapper
.
*/
template
<
typename
T
>
struct
wrapped
{
...
...
src/actor.cpp
View file @
04fc1827
...
...
@@ -69,7 +69,7 @@ bool actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) {
return
false
;
}
bool
actor
::
chained_sync_enqueue
(
const
actor_ptr
&
ptr
,
message_id
_t
id
,
any_tuple
msg
)
{
bool
actor
::
chained_sync_enqueue
(
const
actor_ptr
&
ptr
,
message_id
id
,
any_tuple
msg
)
{
sync_enqueue
(
ptr
,
id
,
std
::
move
(
msg
));
return
false
;
}
...
...
src/behavior_stack.cpp
View file @
04fc1827
...
...
@@ -62,7 +62,7 @@ struct behavior_stack_mover : iterator<output_iterator_tag,void,void,void,void>{
inline
behavior_stack_mover
move_iter
(
behavior_stack
*
bs
)
{
return
{
bs
};
}
option
<
behavior
&>
behavior_stack
::
sync_handler
(
message_id
_t
expected_response
)
{
option
<
behavior
&>
behavior_stack
::
sync_handler
(
message_id
expected_response
)
{
if
(
expected_response
.
valid
())
{
auto
e
=
m_elements
.
rend
();
auto
i
=
find_if
(
m_elements
.
rbegin
(),
e
,
[
=
](
element_type
&
val
)
{
...
...
src/context_switching_actor.cpp
View file @
04fc1827
...
...
@@ -48,12 +48,12 @@ auto context_switching_actor::init_timeout(const util::duration& tout) -> timeou
return
{};
}
detail
::
recursive_queue_node
*
context_switching_actor
::
await_message
(
const
timeout_type
&
)
{
mailbox_element
*
context_switching_actor
::
await_message
(
const
timeout_type
&
)
{
// receives requested timeout message if timeout occured
return
await_message
();
}
detail
::
recursive_queue_node
*
context_switching_actor
::
await_message
()
{
mailbox_element
*
context_switching_actor
::
await_message
()
{
auto
e
=
m_mailbox
.
try_pop
();
while
(
e
==
nullptr
)
{
if
(
m_mailbox
.
can_fetch_more
()
==
false
)
{
...
...
src/default_actor_proxy.cpp
View file @
04fc1827
...
...
@@ -42,11 +42,11 @@ using namespace std;
namespace
cppa
{
namespace
network
{
inline
sync_request_info
*
new_req_info
(
actor_ptr
sptr
,
message_id
_t
id
)
{
inline
sync_request_info
*
new_req_info
(
actor_ptr
sptr
,
message_id
id
)
{
return
detail
::
memory
::
create
<
sync_request_info
>
(
std
::
move
(
sptr
),
id
);
}
sync_request_info
::
sync_request_info
(
actor_ptr
sptr
,
message_id
_t
id
)
sync_request_info
::
sync_request_info
(
actor_ptr
sptr
,
message_id
id
)
:
next
(
nullptr
),
sender
(
std
::
move
(
sptr
)),
mid
(
id
)
{
}
default_actor_proxy
::
default_actor_proxy
(
actor_id
mid
,
...
...
@@ -89,7 +89,7 @@ void default_actor_proxy::deliver(const network::message_header& hdr, any_tuple
void
default_actor_proxy
::
forward_msg
(
const
actor_ptr
&
sender
,
any_tuple
msg
,
message_id
_t
mid
)
{
message_id
mid
)
{
CPPA_LOG_TRACE
(
""
);
if
(
sender
&&
mid
.
is_request
())
{
switch
(
m_pending_requests
.
enqueue
(
new_req_info
(
sender
,
mid
)))
{
...
...
@@ -147,7 +147,7 @@ void default_actor_proxy::enqueue(const actor_ptr& sender, any_tuple msg) {
}
void
default_actor_proxy
::
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
mid
,
message_id
mid
,
any_tuple
msg
)
{
CPPA_LOG_TRACE
(
CPPA_TARG
(
sender
,
to_string
)
<<
", "
<<
CPPA_MARG
(
mid
,
integer_value
)
<<
", "
...
...
src/event_based_actor.cpp
View file @
04fc1827
...
...
@@ -78,11 +78,7 @@ void event_based_actor::dequeue(behavior&) {
quit
(
exit_reason
::
unallowed_function_call
);
}
void
event_based_actor
::
dequeue
(
partial_function
&
)
{
quit
(
exit_reason
::
unallowed_function_call
);
}
void
event_based_actor
::
dequeue_response
(
behavior
&
,
message_id_t
)
{
void
event_based_actor
::
dequeue_response
(
behavior
&
,
message_id
)
{
quit
(
exit_reason
::
unallowed_function_call
);
}
...
...
@@ -142,7 +138,7 @@ resume_result event_based_actor::resume(util::fiber*, actor_ptr& next_job) {
}
else
{
CPPA_LOG_DEBUG
(
"try to invoke message: "
<<
to_string
(
e
->
msg
));
if
(
m_bhvr_stack
.
invoke
(
m_policy
,
this
,
e
))
{
if
(
m_bhvr_stack
.
invoke
(
m_
recv_
policy
,
this
,
e
))
{
CPPA_LOG_DEBUG_IF
(
m_chained_actor
,
"set actor with ID "
<<
m_chained_actor
->
id
()
...
...
@@ -193,7 +189,7 @@ void event_based_actor::do_become(behavior&& bhvr, bool discard_old) {
m_bhvr_stack
.
push_back
(
std
::
move
(
bhvr
));
}
void
event_based_actor
::
become_waiting_for
(
behavior
&&
bhvr
,
message_id_t
mf
)
{
void
event_based_actor
::
become_waiting_for
(
behavior
bhvr
,
message_id
mf
)
{
if
(
bhvr
.
timeout
().
valid
())
{
reset_timeout
();
request_timeout
(
bhvr
.
timeout
());
...
...
src/group_manager.cpp
View file @
04fc1827
...
...
@@ -182,9 +182,9 @@ class local_group_proxy : public local_group {
public:
template
<
typename
...
Arg
s
>
local_group_proxy
(
actor_ptr
remote_broker
,
Arg
s
&&
...
args
)
:
super
(
false
,
forward
<
Arg
s
>
(
args
)...)
{
template
<
typename
...
T
s
>
local_group_proxy
(
actor_ptr
remote_broker
,
T
s
&&
...
args
)
:
super
(
false
,
forward
<
T
s
>
(
args
)...)
{
CPPA_REQUIRE
(
m_broker
==
nullptr
);
CPPA_REQUIRE
(
remote_broker
!=
nullptr
);
CPPA_REQUIRE
(
remote_broker
->
is_proxy
());
...
...
src/local_actor.cpp
View file @
04fc1827
...
...
@@ -75,11 +75,11 @@ local_actor::local_actor(bool sflag)
:
m_chaining
(
sflag
),
m_trap_exit
(
false
)
,
m_is_scheduled
(
sflag
),
m_dummy_node
(),
m_current_node
(
&
m_dummy_node
)
{
}
void
local_actor
::
monitor
(
actor_ptr
whom
)
{
void
local_actor
::
monitor
(
const
actor_ptr
&
whom
)
{
if
(
whom
)
whom
->
attach
(
attachable_ptr
{
new
down_observer
(
this
,
whom
)});
}
void
local_actor
::
demonitor
(
actor_ptr
whom
)
{
void
local_actor
::
demonitor
(
const
actor_ptr
&
whom
)
{
attachable
::
token
mtoken
{
typeid
(
down_observer
),
this
};
if
(
whom
)
whom
->
detach
(
mtoken
);
}
...
...
@@ -113,12 +113,12 @@ void local_actor::reply_message(any_tuple&& what) {
}
auto
&
id
=
m_current_node
->
mid
;
if
(
id
.
valid
()
==
false
||
id
.
is_response
())
{
send_message
(
whom
,
std
::
move
(
what
));
send_message
(
whom
.
get
()
,
std
::
move
(
what
));
}
else
if
(
!
id
.
is_answered
())
{
if
(
chaining_enabled
())
{
if
(
whom
->
chained_sync_enqueue
(
this
,
id
.
response_id
(),
std
::
move
(
what
)))
{
m_chained_actor
=
whom
;
chained_actor
(
whom
)
;
}
}
else
{
...
...
@@ -140,7 +140,7 @@ void local_actor::forward_message(const actor_ptr& new_receiver) {
else
{
new_receiver
->
sync_enqueue
(
from
.
get
(),
id
,
m_current_node
->
msg
);
// treat this message as asynchronous message from now on
m_current_node
->
mid
=
message_id
_t
();
m_current_node
->
mid
=
message_id
();
}
}
...
...
@@ -151,7 +151,7 @@ response_handle local_actor::make_response_handle() {
return
std
::
move
(
result
);
}
message_id
_t
local_actor
::
send_timed_sync_message
(
const
actor_ptr
&
whom
,
message_id
local_actor
::
send_timed_sync_message
(
const
actor_ptr
&
whom
,
const
util
::
duration
&
rel_time
,
any_tuple
&&
what
)
{
auto
mid
=
this
->
send_sync_message
(
whom
,
std
::
move
(
what
));
...
...
@@ -164,10 +164,6 @@ void local_actor::exec_behavior_stack() {
// default implementation does nothing
}
sync_handle_helper
local_actor
::
handle_response
(
const
message_future
&
mf
)
{
return
::
cppa
::
handle_response
(
mf
);
}
void
local_actor
::
cleanup
(
std
::
uint32_t
reason
)
{
m_subscriptions
.
clear
();
super
::
cleanup
(
reason
);
...
...
src/logging.cpp
View file @
04fc1827
...
...
@@ -33,8 +33,6 @@
#include <fstream>
#include <algorithm>
#include <execinfo.h> //DEL_ME
#ifndef CPPA_WINDOWS
#include <unistd.h>
#include <sys/types.h>
...
...
src/
recursive_queue_node
.cpp
→
src/
mailbox_element
.cpp
View file @
04fc1827
...
...
@@ -28,13 +28,13 @@
\******************************************************************************/
#include "cppa/
detail/recursive_queue_node
.hpp"
#include "cppa/
mailbox_element
.hpp"
namespace
cppa
{
namespace
detail
{
namespace
cppa
{
recursive_queue_node
::
recursive_queue_node
(
const
actor_ptr
&
sptr
,
mailbox_element
::
mailbox_element
(
const
actor_ptr
&
sptr
,
any_tuple
data
,
message_id_t
id
)
message_id
id
)
:
next
(
nullptr
),
marked
(
false
),
sender
(
sptr
),
msg
(
std
::
move
(
data
)),
mid
(
id
)
{
}
}
}
// namespace cppa::detail
}
// namespace cppa
src/memory.cpp
View file @
04fc1827
...
...
@@ -32,7 +32,7 @@
#include <typeinfo>
#include "cppa/detail/memory.hpp"
#include "cppa/
detail/recursive_queue_node
.hpp"
#include "cppa/
mailbox_element
.hpp"
using
namespace
std
;
...
...
@@ -64,8 +64,8 @@ cache_map& get_cache_map() {
cache
=
new
cache_map
;
pthread_setspecific
(
s_key
,
cache
);
// insert default types
unique_ptr
<
memory_cache
>
tmp
(
new
basic_memory_cache
<
recursive_queue_node
>
);
cache
->
insert
(
make_pair
(
&
typeid
(
recursive_queue_node
),
move
(
tmp
)));
unique_ptr
<
memory_cache
>
tmp
(
new
basic_memory_cache
<
mailbox_element
>
);
cache
->
insert
(
make_pair
(
&
typeid
(
mailbox_element
),
move
(
tmp
)));
}
return
*
cache
;
}
...
...
src/message_header.cpp
View file @
04fc1827
...
...
@@ -34,7 +34,7 @@ namespace cppa { namespace network {
message_header
::
message_header
(
const
actor_ptr
&
s
,
const
actor_ptr
&
r
,
message_id
_t
mid
)
message_id
mid
)
:
sender
(
s
),
receiver
(
r
),
id
(
mid
)
{
}
message_header
::
message_header
()
:
sender
(
nullptr
),
receiver
(
nullptr
),
id
()
{
}
...
...
src/middleman.cpp
View file @
04fc1827
...
...
@@ -40,7 +40,6 @@
#include "cppa/actor.hpp"
#include "cppa/match.hpp"
#include "cppa/config.hpp"
#include "cppa/either.hpp"
#include "cppa/logging.hpp"
#include "cppa/to_string.hpp"
#include "cppa/actor_proxy.hpp"
...
...
src/protocol.cpp
View file @
04fc1827
...
...
@@ -34,14 +34,6 @@
namespace
cppa
{
namespace
network
{
void
protocol
::
ref_ftor
::
operator
()(
abstract_middleman
*
ptr
)
const
{
if
(
ptr
)
ptr
->
ref
();
}
void
protocol
::
deref_ftor
::
operator
()(
abstract_middleman
*
ptr
)
const
{
if
(
ptr
)
ptr
->
deref
();
}
protocol
::
protocol
(
abstract_middleman
*
parent
)
:
m_parent
(
parent
)
{
CPPA_REQUIRE
(
parent
!=
nullptr
);
}
...
...
src/response_handle.cpp
View file @
04fc1827
...
...
@@ -40,7 +40,7 @@ namespace cppa {
response_handle
::
response_handle
(
const
actor_ptr
&
from
,
const
actor_ptr
&
to
,
const
message_id
_t
&
id
)
const
message_id
&
id
)
:
m_from
(
from
),
m_to
(
to
),
m_id
(
id
)
{
CPPA_REQUIRE
(
id
.
is_response
());
}
...
...
src/scheduled_actor.cpp
View file @
04fc1827
...
...
@@ -80,6 +80,10 @@ scheduled_actor::~scheduled_actor() {
}
}
void
scheduled_actor
::
run_detached
()
{
throw
std
::
logic_error
(
"scheduled_actor::run_detached called"
);
}
void
scheduled_actor
::
cleanup
(
std
::
uint32_t
reason
)
{
detail
::
sync_request_bouncer
f
{
reason
};
m_mailbox
.
close
(
f
);
...
...
@@ -133,7 +137,7 @@ bool scheduled_actor::enqueue(actor_state next_state,
bool
scheduled_actor
::
sync_enqueue_impl
(
actor_state
next
,
const
actor_ptr
&
sender
,
any_tuple
&
msg
,
message_id
_t
id
)
{
message_id
id
)
{
bool
err
=
false
;
auto
ptr
=
new_mailbox_element
(
sender
,
std
::
move
(
msg
),
id
);
bool
res
=
enqueue
(
next
,
&
err
,
ptr
);
...
...
@@ -162,13 +166,13 @@ bool scheduled_actor::chained_enqueue(const actor_ptr& sender, any_tuple msg) {
}
void
scheduled_actor
::
sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
message_id
id
,
any_tuple
msg
)
{
sync_enqueue_impl
(
actor_state
::
ready
,
sender
,
msg
,
id
);
}
bool
scheduled_actor
::
chained_sync_enqueue
(
const
actor_ptr
&
sender
,
message_id
_t
id
,
message_id
id
,
any_tuple
msg
)
{
return
sync_enqueue_impl
(
actor_state
::
pending
,
sender
,
msg
,
id
);
}
...
...
src/scheduled_actor_dummy.cpp
View file @
04fc1827
...
...
@@ -38,14 +38,13 @@ scheduled_actor_dummy::scheduled_actor_dummy()
void
scheduled_actor_dummy
::
enqueue
(
const
actor_ptr
&
,
any_tuple
)
{
}
void
scheduled_actor_dummy
::
quit
(
std
::
uint32_t
)
{
}
void
scheduled_actor_dummy
::
dequeue
(
behavior
&
)
{
}
void
scheduled_actor_dummy
::
dequeue
(
partial_function
&
)
{
}
void
scheduled_actor_dummy
::
dequeue_response
(
behavior
&
,
message_id_t
)
{
}
void
scheduled_actor_dummy
::
dequeue_response
(
behavior
&
,
message_id
)
{
}
void
scheduled_actor_dummy
::
do_become
(
behavior
&&
,
bool
)
{
}
void
scheduled_actor_dummy
::
become_waiting_for
(
behavior
&&
,
message_id_t
)
{
}
void
scheduled_actor_dummy
::
become_waiting_for
(
behavior
,
message_id
)
{
}
bool
scheduled_actor_dummy
::
has_behavior
()
{
return
false
;
}
void
scheduled_actor_dummy
::
sync_enqueue
(
const
actor_ptr
&
,
message_id
_t
,
message_id
,
any_tuple
)
{
}
resume_result
scheduled_actor_dummy
::
resume
(
util
::
fiber
*
,
actor_ptr
&
)
{
...
...
src/scheduler.cpp
View file @
04fc1827
...
...
@@ -68,13 +68,13 @@ class delayed_msg {
delayed_msg
(
const
channel_ptr
&
arg0
,
const
actor_ptr
&
arg1
,
message_id
_t
,
message_id
,
any_tuple
&&
arg3
)
:
ptr_a
(
arg0
),
from
(
arg1
),
msg
(
move
(
arg3
))
{
}
delayed_msg
(
const
actor_ptr
&
arg0
,
const
actor_ptr
&
arg1
,
message_id
_t
arg2
,
message_id
arg2
,
any_tuple
&&
arg3
)
:
ptr_b
(
arg0
),
from
(
arg1
),
id
(
arg2
),
msg
(
move
(
arg3
))
{
}
...
...
@@ -94,7 +94,7 @@ class delayed_msg {
channel_ptr
ptr_a
;
actor_ptr
ptr_b
;
actor_ptr
from
;
message_id
_t
id
;
message_id
id
;
any_tuple
msg
;
};
...
...
@@ -146,7 +146,7 @@ inline void insert_dmsg(Map& storage,
const
T
&
to
,
const
actor_ptr
&
sender
,
any_tuple
&&
tup
,
message_id
_t
id
=
message_id_t
{})
{
message_id
id
=
message_id
{})
{
auto
tout
=
hrc
::
now
();
tout
+=
d
;
delayed_msg
dmsg
{
to
,
sender
,
id
,
move
(
tup
)};
...
...
@@ -157,8 +157,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// setup & local variables
self
.
set
(
m_self
.
get
());
bool
done
=
false
;
auto
&
queue
=
m_self
->
m_mailbox
;
std
::
unique_ptr
<
detail
::
recursive_queue_node
,
detail
::
disposer
>
msg_ptr
;
std
::
unique_ptr
<
mailbox_element
,
detail
::
disposer
>
msg_ptr
;
auto
tout
=
hrc
::
now
();
std
::
multimap
<
decltype
(
tout
),
delayed_msg
>
messages
;
// message handling rules
...
...
@@ -170,7 +169,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
},
on
(
atom
(
"REPLY"
),
arg_match
)
>>
[
&
](
const
util
::
duration
&
d
,
const
actor_ptr
&
ptr
,
message_id
_t
id
,
message_id
id
,
any_tuple
&
tup
)
{
insert_dmsg
(
messages
,
d
,
ptr
,
msg_ptr
->
sender
,
move
(
tup
),
id
);
},
...
...
@@ -188,7 +187,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
// loop
while
(
!
done
)
{
while
(
!
msg_ptr
)
{
if
(
messages
.
empty
())
msg_ptr
.
reset
(
queue
.
pop
());
if
(
messages
.
empty
())
msg_ptr
.
reset
(
m_self
->
pop
());
else
{
tout
=
hrc
::
now
();
// handle timeouts (send messages)
...
...
@@ -200,7 +199,7 @@ void scheduler_helper::timer_loop(scheduler_helper::ptr_type m_self) {
}
// wait for next message or next timeout
if
(
it
!=
messages
.
end
())
{
msg_ptr
.
reset
(
queue
.
try_pop
(
it
->
first
));
msg_ptr
.
reset
(
m_self
->
try_pop
(
it
->
first
));
}
}
}
...
...
src/thread_mapped_actor.cpp
View file @
04fc1827
...
...
@@ -48,6 +48,7 @@ thread_mapped_actor::thread_mapped_actor() : super(std::function<void()>{}), m_i
thread_mapped_actor
::
thread_mapped_actor
(
std
::
function
<
void
()
>
fun
)
:
super
(
std
::
move
(
fun
)),
m_initialized
(
false
)
{
}
/*
auto thread_mapped_actor::init_timeout(const util::duration& rel_time) -> timeout_type {
auto result = std::chrono::high_resolution_clock::now();
result += rel_time;
...
...
@@ -60,7 +61,7 @@ void thread_mapped_actor::enqueue(const actor_ptr& sender, any_tuple msg) {
}
void thread_mapped_actor::sync_enqueue(const actor_ptr& sender,
message_id
_t
id
,
message_id id,
any_tuple msg) {
auto ptr = this->new_mailbox_element(sender, std::move(msg), id);
if (!this->m_mailbox.push_back(ptr)) {
...
...
@@ -68,14 +69,7 @@ void thread_mapped_actor::sync_enqueue(const actor_ptr& sender,
f(sender, id);
}
}
detail
::
recursive_queue_node
*
thread_mapped_actor
::
await_message
()
{
return
m_mailbox
.
pop
();
}
detail
::
recursive_queue_node
*
thread_mapped_actor
::
await_message
(
const
timeout_type
&
abs_time
)
{
return
m_mailbox
.
try_pop
(
abs_time
);
}
*/
bool
thread_mapped_actor
::
initialized
()
const
{
return
m_initialized
;
...
...
src/thread_pool_scheduler.cpp
View file @
04fc1827
...
...
@@ -204,8 +204,7 @@ actor_ptr thread_pool_scheduler::exec(spawn_options os, scheduled_actor_ptr p) {
bool
is_hidden
=
has_hide_flag
(
os
);
if
(
has_detach_flag
(
os
))
{
exec_as_thread
(
is_hidden
,
p
,
[
p
]
{
p
->
exec_behavior_stack
();
p
->
on_exit
();
p
->
run_detached
();
});
return
std
::
move
(
p
);
}
...
...
src/unicast_network.cpp
View file @
04fc1827
...
...
@@ -43,29 +43,27 @@
#include "cppa/atom.hpp"
#include "cppa/to_string.hpp"
#include "cppa/exception.hpp"
#include "cppa/singletons.hpp"
#include "cppa/exit_reason.hpp"
#include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp"
#include "cppa/intrusive/single_reader_queue.hpp"
#include "cppa/network/acceptor.hpp"
#include "cppa/network/protocol.hpp"
#include "cppa/network/middleman.hpp"
#include "cppa/network/ipv4_acceptor.hpp"
#include "cppa/network/ipv4_io_stream.hpp"
#include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/singleton_manager.hpp"
namespace
cppa
{
using
namespace
detail
;
using
namespace
network
;
namespace
{
protocol
*
proto
()
{
return
singleton_manager
::
get_middleman
()
->
protocol
(
atom
(
"DEFAULT"
)).
get
();
}
}
// namespace <anonymous>
namespace
{
protocol_ptr
proto
()
{
return
get_middleman
()
->
protocol
(
atom
(
"DEFAULT"
)).
get
();
}
}
void
publish
(
actor_ptr
whom
,
std
::
unique_ptr
<
acceptor
>
aptr
)
{
proto
()
->
publish
(
whom
,
move
(
aptr
),
{});
...
...
src/uniform_type_info.cpp
View file @
04fc1827
...
...
@@ -412,7 +412,7 @@ class msg_hdr_tinfo : public util::abstract_uniform_type_info<network::message_h
actor_ptr_tinfo
::
s_deserialize
(
msg
.
sender
,
source
,
actor_ptr_name
);
actor_ptr_tinfo
::
s_deserialize
(
msg
.
receiver
,
source
,
actor_ptr_name
);
auto
msg_id
=
source
->
read
<
std
::
uint64_t
>
();
msg
.
id
=
message_id
_t
::
from_integer_value
(
msg_id
);
msg
.
id
=
message_id
::
from_integer_value
(
msg_id
);
source
->
end_object
();
}
...
...
unit_testing/test_spawn.cpp
View file @
04fc1827
...
...
@@ -302,9 +302,24 @@ int main() {
);
CPPA_CHECKPOINT
();
CPPA_PRINT
(
"test mirror"
);
{
auto
mirror
=
spawn
<
simple_mirror
,
monitored
>
();
send
(
mirror
,
"hello mirror"
);
receive
(
on
(
"hello mirror"
)
>>
CPPA_CHECKPOINT_CB
(),
others
()
>>
CPPA_UNEXPECTED_MSG_CB
()
);
quit_actor
(
mirror
,
exit_reason
::
user_defined
);
receive
(
on
(
atom
(
"DOWN"
),
exit_reason
::
user_defined
)
>>
CPPA_CHECKPOINT_CB
(),
others
()
>>
CPPA_UNEXPECTED_MSG_CB
()
);
await_all_others_done
();
CPPA_CHECKPOINT
();
}
CPPA_PRINT
(
"test mirror"
);
CPPA_PRINT
(
"test detached mirror"
);
{
auto
mirror
=
spawn
<
simple_mirror
,
monitored
+
detached
>
();
send
(
mirror
,
"hello mirror"
);
receive
(
on
(
"hello mirror"
)
>>
CPPA_CHECKPOINT_CB
(),
...
...
@@ -317,6 +332,7 @@ int main() {
);
await_all_others_done
();
CPPA_CHECKPOINT
();
}
CPPA_PRINT
(
"test echo actor"
);
auto
mecho
=
spawn
(
echo_actor
);
...
...
@@ -461,7 +477,7 @@ int main() {
self
->
become
(
on
(
"hi"
)
>>
[
&
]()
{
auto
handle
=
sync_send
(
self
->
last_sender
(),
"whassup?"
);
self
->
handle_response
(
handle
)
(
handle_response
(
handle
)
(
on_arg_match
>>
[
&
](
const
string
&
str
)
{
CPPA_CHECK
(
self
->
last_sender
()
!=
nullptr
);
CPPA_CHECK_EQUAL
(
str
,
"nothing"
);
...
...
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