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
b749cc1f
Commit
b749cc1f
authored
Aug 31, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prepare type system for streams plus cleanup
parent
bc9c2f75
Changes
37
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
942 additions
and
1350 deletions
+942
-1350
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+0
-1
libcaf_core/caf/actor.hpp
libcaf_core/caf/actor.hpp
+0
-8
libcaf_core/caf/actor_pool.hpp
libcaf_core/caf/actor_pool.hpp
+1
-0
libcaf_core/caf/actor_system.hpp
libcaf_core/caf/actor_system.hpp
+1
-1
libcaf_core/caf/all.hpp
libcaf_core/caf/all.hpp
+0
-1
libcaf_core/caf/check_typed_input.hpp
libcaf_core/caf/check_typed_input.hpp
+3
-30
libcaf_core/caf/composable_behavior.hpp
libcaf_core/caf/composable_behavior.hpp
+1
-1
libcaf_core/caf/composed_type.hpp
libcaf_core/caf/composed_type.hpp
+139
-0
libcaf_core/caf/decorator/adapter.hpp
libcaf_core/caf/decorator/adapter.hpp
+0
-57
libcaf_core/caf/deduce_mpi.hpp
libcaf_core/caf/deduce_mpi.hpp
+121
-0
libcaf_core/caf/detail/ctm.hpp
libcaf_core/caf/detail/ctm.hpp
+0
-113
libcaf_core/caf/detail/disablable_delete.hpp
libcaf_core/caf/detail/disablable_delete.hpp
+0
-50
libcaf_core/caf/detail/implicit_conversions.hpp
libcaf_core/caf/detail/implicit_conversions.hpp
+72
-28
libcaf_core/caf/detail/left_or_right.hpp
libcaf_core/caf/detail/left_or_right.hpp
+0
-63
libcaf_core/caf/detail/mpi_bind.hpp
libcaf_core/caf/detail/mpi_bind.hpp
+0
-159
libcaf_core/caf/detail/purge_refs.hpp
libcaf_core/caf/detail/purge_refs.hpp
+0
-57
libcaf_core/caf/detail/typed_actor_util.hpp
libcaf_core/caf/detail/typed_actor_util.hpp
+22
-149
libcaf_core/caf/detail/unboxed.hpp
libcaf_core/caf/detail/unboxed.hpp
+0
-65
libcaf_core/caf/detail/wrapped.hpp
libcaf_core/caf/detail/wrapped.hpp
+0
-45
libcaf_core/caf/function_view.hpp
libcaf_core/caf/function_view.hpp
+12
-9
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+3
-0
libcaf_core/caf/interface_mismatch.hpp
libcaf_core/caf/interface_mismatch.hpp
+131
-0
libcaf_core/caf/local_actor.hpp
libcaf_core/caf/local_actor.hpp
+5
-10
libcaf_core/caf/match_case.hpp
libcaf_core/caf/match_case.hpp
+0
-1
libcaf_core/caf/mixin/requester.hpp
libcaf_core/caf/mixin/requester.hpp
+7
-8
libcaf_core/caf/mixin/sender.hpp
libcaf_core/caf/mixin/sender.hpp
+35
-42
libcaf_core/caf/replies_to.hpp
libcaf_core/caf/replies_to.hpp
+19
-8
libcaf_core/caf/response_type.hpp
libcaf_core/caf/response_type.hpp
+94
-0
libcaf_core/caf/send.hpp
libcaf_core/caf/send.hpp
+18
-27
libcaf_core/caf/typed_actor.hpp
libcaf_core/caf/typed_actor.hpp
+5
-29
libcaf_core/caf/typed_behavior.hpp
libcaf_core/caf/typed_behavior.hpp
+31
-19
libcaf_core/src/actor.cpp
libcaf_core/src/actor.cpp
+0
-7
libcaf_core/src/adapter.cpp
libcaf_core/src/adapter.cpp
+0
-78
libcaf_core/test/adapter.cpp
libcaf_core/test/adapter.cpp
+0
-255
libcaf_core/test/metaprogramming.cpp
libcaf_core/test/metaprogramming.cpp
+206
-21
libcaf_core/test/splitter.cpp
libcaf_core/test/splitter.cpp
+15
-7
libcaf_core/test/typed_spawn.cpp
libcaf_core/test/typed_spawn.cpp
+1
-1
No files found.
libcaf_core/CMakeLists.txt
View file @
b749cc1f
...
...
@@ -27,7 +27,6 @@ set (LIBCAF_CORE_SRCS
src/actor_registry.cpp
src/actor_system.cpp
src/actor_system_config.cpp
src/adapter.cpp
src/atom.cpp
src/attachable.cpp
src/behavior.cpp
...
...
libcaf_core/caf/actor.hpp
View file @
b749cc1f
...
...
@@ -135,12 +135,6 @@ public:
/// Exchange content of `*this` and `other`.
void
swap
(
actor
&
other
)
noexcept
;
/// Create a new actor decorator that presets or reorders inputs.
template
<
class
...
Ts
>
actor
bind
(
Ts
&&
...
xs
)
const
{
return
bind_impl
(
make_message
(
std
::
forward
<
Ts
>
(
xs
)...));
}
/// Queries whether this object was constructed using
/// `unsafe_actor_handle_init` or is in moved-from state.
bool
unsafe
()
const
{
...
...
@@ -180,8 +174,6 @@ public:
private:
actor
()
=
default
;
actor
bind_impl
(
message
msg
)
const
;
inline
actor_control_block
*
get
()
const
noexcept
{
return
ptr_
.
get
();
}
...
...
libcaf_core/caf/actor_pool.hpp
View file @
b749cc1f
...
...
@@ -54,6 +54,7 @@ namespace caf {
/// during the enqueue operation. Any user-defined policy thus has to dispatch
/// messages with as little overhead as possible, because the dispatching
/// runs in the context of the sender.
/// @experimental
class
actor_pool
:
public
monitorable_actor
{
public:
using
uplock
=
upgrade_lock
<
detail
::
shared_spinlock
>
;
...
...
libcaf_core/caf/actor_system.hpp
View file @
b749cc1f
...
...
@@ -97,7 +97,7 @@ struct typed_mpi_access;
template
<
class
...
Is
,
class
...
Ls
>
struct
typed_mpi_access
<
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
detail
::
type_list
<
Ls
...
>>>
{
output_tuple
<
Ls
...
>>>
{
std
::
string
operator
()(
const
uniform_type_info_map
&
types
)
const
{
static_assert
(
sizeof
...(
Is
)
>
0
,
"typed MPI without inputs"
);
static_assert
(
sizeof
...(
Ls
)
>
0
,
"typed MPI without outputs"
);
...
...
libcaf_core/caf/all.hpp
View file @
b749cc1f
...
...
@@ -97,7 +97,6 @@
#include "caf/typed_event_based_actor.hpp"
#include "caf/abstract_composable_behavior.hpp"
#include "caf/decorator/adapter.hpp"
#include "caf/decorator/sequencer.hpp"
#include "caf/meta/type_name.hpp"
...
...
libcaf_core/caf/check_typed_input.hpp
View file @
b749cc1f
...
...
@@ -43,6 +43,9 @@ struct signatures_of {
using
type
=
typename
std
::
remove_pointer
<
T
>::
type
::
signatures
;
};
template
<
class
T
>
using
signatures_of_t
=
typename
signatures_of
<
T
>::
type
;
template
<
class
T
>
constexpr
bool
statically_typed
()
{
return
!
std
::
is_same
<
...
...
@@ -51,36 +54,6 @@ constexpr bool statically_typed() {
>::
value
;
}
template
<
class
Signatures
,
class
Input
>
struct
actor_accepts_message
;
template
<
class
Input
>
struct
actor_accepts_message
<
none_t
,
Input
>
:
std
::
true_type
{};
template
<
class
...
Ts
,
class
Input
>
struct
actor_accepts_message
<
detail
::
type_list
<
Ts
...
>
,
Input
>
:
detail
::
tl_exists
<
detail
::
type_list
<
Ts
...
>
,
detail
::
input_is
<
Input
>::
template
eval
>
{};
template
<
class
Signatures
,
class
Input
>
struct
response_to
;
template
<
class
Input
>
struct
response_to
<
none_t
,
Input
>
{
using
type
=
none_t
;
};
template
<
class
...
Ts
,
class
Input
>
struct
response_to
<
detail
::
type_list
<
Ts
...
>
,
Input
>
{
using
type
=
typename
output_types_of
<
typename
detail
::
tl_find
<
detail
::
type_list
<
Ts
...
>
,
detail
::
input_is
<
Input
>::
template
eval
>
::
type
>::
type
;
};
template
<
class
T
>
struct
is_void_response
:
std
::
false_type
{};
...
...
libcaf_core/caf/composable_behavior.hpp
View file @
b749cc1f
...
...
@@ -37,7 +37,7 @@ class composable_behavior_base;
template
<
class
...
Xs
,
class
...
Ys
>
class
composable_behavior_base
<
typed_mpi
<
detail
::
type_list
<
Xs
...
>
,
detail
::
type_list
<
Ys
...
>>>
{
output_tuple
<
Ys
...
>>>
{
public:
virtual
~
composable_behavior_base
()
noexcept
{
// nop
...
...
libcaf_core/caf/composed_type.hpp
0 → 100644
View file @
b749cc1f
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_COMPOSED_TYPE_HPP
#define CAF_COMPOSED_TYPE_HPP
#include "caf/fwd.hpp"
#include "caf/replies_to.hpp"
#include "caf/detail/type_list.hpp"
namespace
caf
{
/// Computes the type for f*g (actor composition).
///
/// ~~~
/// let output_type x = case x of Stream y -> y ; Single y -> y
///
/// let propagate_stream from to = case from of
/// Stream _ -> Stream (output_type to)
/// Single _ -> to
/// let composed_type f g =
/// [(fst x, propagate_stream (snd x) (snd y)) | x <- g, y <- f,
/// output_type (snd x) == fst y]
/// ~~~
///
/// This class implements the list comprehension above in a
/// single shot with worst case n*m template instantiations using an
/// inner and outer loop, where n is the size
/// of Xs and m the size of Ys. Zs is a helper that models the
/// "inner loop variable" for generating the cross product of Xs and Ys.
/// The helper function propagate_stream is integrated into the loop with
/// four cases for the matching case. Rs collects the results.
template
<
class
Xs
,
class
Ys
,
class
Zs
,
class
Rs
>
struct
composed_type
;
// end of outer loop over Xs
template
<
class
Ys
,
class
Zs
,
class
...
Rs
>
struct
composed_type
<
detail
::
type_list
<>
,
Ys
,
Zs
,
detail
::
type_list
<
Rs
...
>>
{
using
type
=
typed_actor
<
Rs
...
>
;
};
// end of inner loop Ys (Zs)
template
<
class
X
,
class
...
Xs
,
class
Ys
,
class
Rs
>
struct
composed_type
<
detail
::
type_list
<
X
,
Xs
...
>
,
Ys
,
detail
::
type_list
<>
,
Rs
>
:
composed_type
<
detail
::
type_list
<
Xs
...
>
,
Ys
,
Ys
,
Rs
>
{};
// case #1
template
<
class
...
In
,
class
...
Out
,
class
...
Xs
,
class
Ys
,
class
...
MapsTo
,
class
...
Zs
,
class
...
Rs
>
struct
composed_type
<
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_tuple
<
Out
...
>>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
Out
...
>
,
output_tuple
<
MapsTo
...
>>
,
Zs
...
>
,
detail
::
type_list
<
Rs
...
>>
:
composed_type
<
detail
::
type_list
<
Xs
...
>
,
Ys
,
Ys
,
detail
::
type_list
<
Rs
...,
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_tuple
<
MapsTo
...
>>>>
{};
// case #2
template
<
class
...
In
,
class
...
Out
,
class
...
Xs
,
class
Ys
,
class
...
MapsTo
,
class
...
Zs
,
class
...
Rs
>
struct
composed_type
<
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_tuple
<
Out
...
>>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
Out
...
>
,
output_stream
<
MapsTo
...
>>
,
Zs
...
>
,
detail
::
type_list
<
Rs
...
>>
:
composed_type
<
detail
::
type_list
<
Xs
...
>
,
Ys
,
Ys
,
detail
::
type_list
<
Rs
...,
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_stream
<
MapsTo
...
>>>>
{};
// case #3
template
<
class
...
In
,
class
...
Out
,
class
...
Xs
,
class
Ys
,
class
...
MapsTo
,
class
...
Zs
,
class
...
Rs
>
struct
composed_type
<
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_stream
<
Out
...
>>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
Out
...
>
,
output_tuple
<
MapsTo
...
>>
,
Zs
...
>
,
detail
::
type_list
<
Rs
...
>>
:
composed_type
<
detail
::
type_list
<
Xs
...
>
,
Ys
,
Ys
,
detail
::
type_list
<
Rs
...,
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_stream
<
MapsTo
...
>>>>
{};
// case #4
template
<
class
...
In
,
class
...
Out
,
class
...
Xs
,
class
Ys
,
class
...
MapsTo
,
class
...
Zs
,
class
...
Rs
>
struct
composed_type
<
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_stream
<
Out
...
>>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
Out
...
>
,
output_stream
<
MapsTo
...
>>
,
Zs
...
>
,
detail
::
type_list
<
Rs
...
>>
:
composed_type
<
detail
::
type_list
<
Xs
...
>
,
Ys
,
Ys
,
detail
::
type_list
<
Rs
...,
typed_mpi
<
detail
::
type_list
<
In
...
>
,
output_stream
<
MapsTo
...
>>>>
{};
// default case (recurse over Zs)
template
<
class
In
,
class
Out
,
class
...
Xs
,
class
Ys
,
class
Unrelated
,
class
MapsTo
,
class
...
Zs
,
class
Rs
>
struct
composed_type
<
detail
::
type_list
<
typed_mpi
<
In
,
Out
>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
typed_mpi
<
Unrelated
,
MapsTo
>
,
Zs
...
>
,
Rs
>
:
composed_type
<
detail
::
type_list
<
typed_mpi
<
In
,
Out
>
,
Xs
...
>
,
Ys
,
detail
::
type_list
<
Zs
...
>
,
Rs
>
{};
/// Convenience type alias.
/// @relates composed_type
template
<
class
F
,
class
G
>
using
composed_type_t
=
typename
composed_type
<
G
,
F
,
F
,
detail
::
type_list
<>>::
type
;
}
// namespace caf
#endif // CAF_COMPOSED_TYPE_HPP
libcaf_core/caf/decorator/adapter.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DECORATOR_ADAPTER_HPP
#define CAF_DECORATOR_ADAPTER_HPP
#include "caf/actor.hpp"
#include "caf/message.hpp"
#include "caf/attachable.hpp"
#include "caf/monitorable_actor.hpp"
namespace
caf
{
namespace
decorator
{
/// An actor decorator implementing `std::bind`-like compositions.
/// Bound actors are hidden actors. A bound actor exits when its
/// decorated actor exits. The decorated actor has no dependency
/// on the bound actor by default, and exit of a bound actor has
/// no effect on the decorated actor. Bound actors are hosted on
/// the same actor system and node as decorated actors.
class
adapter
:
public
monitorable_actor
{
public:
adapter
(
strong_actor_ptr
decorated
,
message
msg
);
// non-system messages are processed and then forwarded;
// system messages are handled and consumed on the spot;
// in either case, the processing is done synchronously
void
enqueue
(
mailbox_element_ptr
what
,
execution_unit
*
host
)
override
;
protected:
void
on_cleanup
()
override
;
private:
strong_actor_ptr
decorated_
;
message
merger_
;
};
}
// namespace decorator
}
// namespace caf
#endif // CAF_DECORATOR_ADAPTER_HPP
libcaf_core/caf/de
tail/boxed
.hpp
→
libcaf_core/caf/de
duce_mpi
.hpp
View file @
b749cc1f
...
...
@@ -17,56 +17,105 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DE
TAIL_BOXED
_HPP
#define CAF_DE
TAIL_BOXED
_HPP
#ifndef CAF_DE
DUCE_MPI
_HPP
#define CAF_DE
DUCE_MPI
_HPP
#include "caf/detail/wrapped.hpp"
#include <type_traits>
#include "caf/fwd.hpp"
#include "caf/expected.hpp"
#include "caf/optional.hpp"
#include "caf/replies_to.hpp"
#include "caf/detail/implicit_conversions.hpp"
namespace
caf
{
namespace
detail
{
// dmi = deduce_mpi_implementation
template
<
class
T
>
struct
boxed
{
constexpr
boxed
()
{
// nop
}
using
type
=
detail
::
wrapped
<
T
>
;
struct
dmi
;
// case #1: function returning a single value
template
<
class
Y
,
class
...
Xs
>
struct
dmi
<
Y
(
Xs
...)
>
{
using
type
=
typed_mpi
<
type_list
<
typename
std
::
decay
<
Xs
>::
type
...
>
,
output_tuple
<
implicit_conversions_t
<
Y
>>>
;
};
template
<
class
T
>
struct
boxed
<
detail
::
wrapped
<
T
>>
{
constexpr
boxed
()
{
// nop
}
using
type
=
detail
::
wrapped
<
T
>
;
// case #2a: function returning a result<...>
template
<
class
...
Ys
,
class
...
Xs
>
struct
dmi
<
result
<
Ys
...
>
(
Xs
...)
>
{
using
type
=
typed_mpi
<
type_list
<
typename
std
::
decay
<
Xs
>::
type
...
>
,
output_tuple
<
implicit_conversions_t
<
Ys
>
...
>>
;
};
template
<
class
T
>
struct
is_boxed
{
static
constexpr
bool
value
=
false
;
// case #2b: function returning a std::tuple<...>
template
<
class
...
Ys
,
class
...
Xs
>
struct
dmi
<
std
::
tuple
<
Ys
...
>
(
Xs
...)
>
{
using
type
=
typed_mpi
<
type_list
<
typename
std
::
decay
<
Xs
>::
type
...
>
,
output_tuple
<
implicit_conversions_t
<
Ys
>
...
>>
;
};
template
<
class
T
>
struct
is_boxed
<
detail
::
wrapped
<
T
>>
{
static
constexpr
bool
value
=
true
;
// case #2c: function returning a std::tuple<...>
template
<
class
...
Ys
,
class
...
Xs
>
struct
dmi
<
delegated
<
Ys
...
>
(
Xs
...)
>
{
using
type
=
typed_mpi
<
type_list
<
typename
std
::
decay
<
Xs
>::
type
...
>
,
output_tuple
<
implicit_conversions_t
<
Ys
>
...
>>
;
};
template
<
class
T
>
struct
is_boxed
<
detail
::
wrapped
<
T
>
()
>
{
static
constexpr
bool
value
=
true
;
// case #2d: function returning a typed_response_promise<...>
template
<
class
...
Ys
,
class
...
Xs
>
struct
dmi
<
typed_response_promise
<
Ys
...
>
(
Xs
...)
>
{
using
type
=
typed_mpi
<
type_list
<
typename
std
::
decay
<
Xs
>::
type
...
>
,
output_tuple
<
implicit_conversions_t
<
Ys
>
...
>>
;
};
// case #3: function returning an optional<>
template
<
class
Y
,
class
...
Xs
>
struct
dmi
<
optional
<
Y
>
(
Xs
...)
>
:
dmi
<
Y
(
Xs
...)
>
{};
// case #4: function returning an expected<>
template
<
class
Y
,
class
...
Xs
>
struct
dmi
<
expected
<
Y
>
(
Xs
...)
>
:
dmi
<
Y
(
Xs
...)
>
{};
// -- dmfou = deduce_mpi_function_object_unboxing
template
<
class
T
,
bool
isClass
=
std
::
is_class
<
T
>
::
value
>
struct
dmfou
;
// case #1: const member function pointer
template
<
class
C
,
class
Result
,
class
...
Ts
>
struct
dmfou
<
Result
(
C
::*
)(
Ts
...)
const
,
false
>
:
dmi
<
Result
(
Ts
...)
>
{};
// case #2: member function pointer
template
<
class
C
,
class
Result
,
class
...
Ts
>
struct
dmfou
<
Result
(
C
::*
)(
Ts
...),
false
>
:
dmi
<
Result
(
Ts
...)
>
{};
// case #3: good ol' function
template
<
class
Result
,
class
...
Ts
>
struct
dmfou
<
Result
(
Ts
...),
false
>
:
dmi
<
Result
(
Ts
...)
>
{};
template
<
class
T
>
struct
is_boxed
<
detail
::
wrapped
<
T
>
(
&
)()
>
{
static
constexpr
bool
value
=
true
;
};
struct
dmfou
<
T
,
true
>
:
dmfou
<
decltype
(
&
T
::
operator
()),
false
>
{};
// this specialization leaves timeout definitions untouched,
// later stages such as interface_mismatch need to deal with them later
template
<
class
T
>
struct
is_boxed
<
detail
::
wrapped
<
T
>
(
*
)()
>
{
static
constexpr
bool
value
=
true
;
struct
dmfou
<
timeout_definition
<
T
>
,
true
>
{
using
type
=
timeout_definition
<
T
>
;
};
template
<
class
T
>
struct
dmfou
<
trivial_match_case
<
T
>
,
true
>
:
dmfou
<
T
>
{};
}
// namespace detail
/// Deduces the message passing interface from a function object.
template
<
class
T
>
using
deduce_mpi_t
=
typename
detail
::
dmfou
<
typename
std
::
decay
<
T
>::
type
>::
type
;
}
// namespace caf
#endif // CAF_DE
TAIL_BOXED
_HPP
#endif // CAF_DE
DUCE_MPI
_HPP
libcaf_core/caf/detail/ctm.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_CTM_HPP
#define CAF_DETAIL_CTM_HPP
#include <tuple>
#include "caf/optional.hpp"
#include "caf/delegated.hpp"
#include "caf/replies_to.hpp"
#include "caf/typed_response_promise.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/typed_actor_util.hpp"
namespace
caf
{
namespace
detail
{
// CTM: Compile-Time Match
// left hand side is the MPI we are comparing to, this is *not* commutative
template
<
class
A
,
class
B
>
struct
ctm_cmp
:
std
::
false_type
{
};
template
<
class
In
,
class
Out
>
struct
ctm_cmp
<
typed_mpi
<
In
,
Out
>
,
typed_mpi
<
In
,
Out
>>
{
static
constexpr
bool
value
=
true
;
};
template
<
class
In
,
class
OutList
>
struct
ctm_cmp
<
typed_mpi
<
In
,
OutList
>
,
typed_mpi
<
In
,
type_list
<
typed_continue_helper
<
OutList
>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
Out
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
Out
>>
,
typed_mpi
<
In
,
type_list
<
optional
<
Out
>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
...
Ts
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
Ts
...
>>
,
typed_mpi
<
In
,
type_list
<
typed_response_promise
<
Ts
...
>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
...
Ts
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
Ts
...
>>
,
typed_mpi
<
In
,
type_list
<
optional
<
std
::
tuple
<
Ts
...
>>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
...
Ts
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
Ts
...
>>
,
typed_mpi
<
In
,
type_list
<
result
<
Ts
...
>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
T
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
T
>>
,
typed_mpi
<
In
,
type_list
<
expected
<
T
>>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
Out
>
struct
ctm_cmp
<
typed_mpi
<
In
,
Out
>
,
typed_mpi
<
In
,
type_list
<
skip_t
>>>
:
std
::
true_type
{
};
template
<
class
In
,
class
...
Ts
>
struct
ctm_cmp
<
typed_mpi
<
In
,
type_list
<
Ts
...
>>
,
typed_mpi
<
In
,
type_list
<
delegated
<
Ts
...
>>>>
:
std
::
true_type
{
};
template
<
class
Xs
,
class
Ys
>
constexpr
int
ctm_impl
(
int
pos
)
{
return
tl_empty
<
Xs
>::
value
?
-
1
// consumed each X
:
(
tl_exists
<
Ys
,
tbind
<
ctm_cmp
,
typename
tl_head
<
Xs
>::
type
>::
template
type
>
::
value
?
ctm_impl
<
typename
tl_tail
<
Xs
>::
type
,
Ys
>
(
pos
+
1
)
:
pos
);
}
template
<
class
Xs
,
class
Ys
>
struct
ctm
{
// -3 means too many handler, -2 means too few, -1 means OK, everything else
// mismatch at that position
static
constexpr
size_t
num_xs
=
tl_size
<
Xs
>::
value
;
static
constexpr
size_t
num_ys
=
tl_size
<
Ys
>::
value
;
static
constexpr
int
value
=
num_xs
==
num_ys
?
ctm_impl
<
Xs
,
Ys
>
(
0
)
:
(
num_xs
<
num_ys
?
-
2
:
-
3
);
};
template
<
class
Xs
,
class
Ys
>
constexpr
int
ctm
<
Xs
,
Ys
>::
value
;
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_CTM_HPP
libcaf_core/caf/detail/disablable_delete.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_DISABLABLE_DELETE_HPP
#define CAF_DETAIL_DISABLABLE_DELETE_HPP
namespace
caf
{
namespace
detail
{
class
disablable_delete
{
public:
constexpr
disablable_delete
()
:
enabled_
(
true
)
{}
inline
void
disable
()
{
enabled_
=
false
;
}
inline
void
enable
()
{
enabled_
=
true
;
}
template
<
class
T
>
inline
void
operator
()(
T
*
ptr
)
{
if
(
enabled_
)
delete
ptr
;
}
private:
bool
enabled_
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_DISABLABLE_DELETE_HPP
libcaf_core/caf/detail/implicit_conversions.hpp
View file @
b749cc1f
...
...
@@ -31,42 +31,83 @@ namespace detail {
template
<
class
T
>
struct
implicit_conversions
{
// convert C strings to std::string if possible
using
step1
=
using
type
=
typename
std
::
conditional
<
std
::
is_convertible
<
T
,
std
::
string
>::
value
,
std
::
string
,
std
::
is_convertible
<
T
,
error
>::
value
,
error
,
T
>::
type
;
// convert C strings to std::u16string if possible
using
step2
=
typename
std
::
conditional
<
std
::
is_convertible
<
step1
,
std
::
u16string
>::
value
,
std
::
u16string
,
step1
>::
type
;
// convert C strings to std::u32string if possible
using
step3
=
typename
std
::
conditional
<
std
::
is_convertible
<
step2
,
std
::
u32string
>::
value
,
std
::
u32string
,
step2
>::
type
;
using
step4
=
typename
std
::
conditional
<
std
::
is_convertible
<
step3
,
abstract_actor
*>::
value
||
std
::
is_same
<
scoped_actor
,
step3
>::
value
,
actor
,
step3
>::
type
;
};
template
<
class
T
>
struct
implicit_conversions
<
T
*>
{
using
type
=
typename
std
::
conditional
<
std
::
is_
convertible
<
step4
,
error
>::
value
,
err
or
,
step4
std
::
is_
base_of
<
abstract_actor
,
T
>::
value
,
act
or
,
T
*
>::
type
;
};
template
<
>
struct
implicit_conversions
<
char
*>
{
using
type
=
std
::
string
;
};
template
<
size_t
N
>
struct
implicit_conversions
<
char
[
N
]
>
:
implicit_conversions
<
char
*>
{};
template
<
>
struct
implicit_conversions
<
const
char
*>
:
implicit_conversions
<
char
*>
{};
template
<
size_t
N
>
struct
implicit_conversions
<
const
char
[
N
]
>
:
implicit_conversions
<
char
*>
{};
template
<
>
struct
implicit_conversions
<
char16_t
*>
{
using
type
=
std
::
u16string
;
};
template
<
size_t
N
>
struct
implicit_conversions
<
char16_t
[
N
]
>
:
implicit_conversions
<
char16_t
*>
{};
template
<
>
struct
implicit_conversions
<
const
char16_t
*>
:
implicit_conversions
<
char16_t
*>
{};
template
<
size_t
N
>
struct
implicit_conversions
<
const
char16_t
[
N
]
>
:
implicit_conversions
<
char16_t
*>
{};
template
<
>
struct
implicit_conversions
<
char32_t
*>
{
using
type
=
std
::
u16string
;
};
template
<
size_t
N
>
struct
implicit_conversions
<
char32_t
[
N
]
>
:
implicit_conversions
<
char32_t
*>
{};
template
<
>
struct
implicit_conversions
<
const
char32_t
*>
:
implicit_conversions
<
char32_t
*>
{};
template
<
size_t
N
>
struct
implicit_conversions
<
const
char32_t
[
N
]
>
:
implicit_conversions
<
char32_t
*>
{};
template
<
>
struct
implicit_conversions
<
scoped_actor
>
{
using
type
=
actor
;
};
template
<
class
T
>
using
implicit_conversions_t
=
typename
implicit_conversions
<
T
>::
type
;
template
<
class
T
>
struct
strip_and_convert
{
using
type
=
...
...
@@ -79,6 +120,9 @@ struct strip_and_convert {
>::
type
;
};
template
<
class
T
>
using
strip_and_convert_t
=
typename
strip_and_convert
<
T
>::
type
;
}
// namespace detail
}
// namespace caf
...
...
libcaf_core/caf/detail/left_or_right.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_LEFT_OR_RIGHT_HPP
#define CAF_DETAIL_LEFT_OR_RIGHT_HPP
#include "caf/unit.hpp"
namespace
caf
{
namespace
detail
{
/// Evaluates to `Right` if `Left` == unit_t, `Left` otherwise.
template
<
class
Left
,
typename
Right
>
struct
left_or_right
{
using
type
=
Left
;
};
template
<
class
Right
>
struct
left_or_right
<
unit_t
,
Right
>
{
using
type
=
Right
;
};
template
<
class
Right
>
struct
left_or_right
<
unit_t
&
,
Right
>
{
using
type
=
Right
;
};
template
<
class
Right
>
struct
left_or_right
<
const
unit_t
&
,
Right
>
{
using
type
=
Right
;
};
/// Evaluates to `Right` if `Left` != unit_t, `unit_t` otherwise.
template
<
class
Left
,
typename
Right
>
struct
if_not_left
{
using
type
=
unit_t
;
};
template
<
class
Right
>
struct
if_not_left
<
unit_t
,
Right
>
{
using
type
=
Right
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_LEFT_OR_RIGHT_HPP
libcaf_core/caf/detail/mpi_bind.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_MPI_BIND_HPP
#define CAF_DETAIL_MPI_BIND_HPP
#include <functional>
#include "caf/none.hpp"
#include "caf/replies_to.hpp"
#include "caf/detail/type_list.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
T
,
size_t
Pos
>
class
mpi_bind_sig_arg_t
{
// nop
};
template
<
class
T
,
int
PlaceholderValue
,
size_t
Pos
,
size_t
Size
,
bool
InRange
=
PlaceholderValue
<=
static_cast
<
int
>(
Size
)
>
struct
mpi_bind_sig_single
{
using
type
=
mpi_bind_sig_arg_t
<
typename
detail
::
tl_at
<
T
,
Pos
>::
type
,
PlaceholderValue
-
1
>
;
};
template
<
class
T
,
size_t
Pos
,
size_t
Size
>
struct
mpi_bind_sig_single
<
T
,
0
,
Pos
,
Size
,
true
>
{
using
type
=
void
;
};
template
<
class
T
,
int
PlaceholderValue
,
size_t
Pos
,
size_t
Size
>
struct
mpi_bind_sig_single
<
T
,
PlaceholderValue
,
Pos
,
Size
,
false
>
{
using
type
=
none_t
;
};
template
<
size_t
I
,
size_t
Size
,
class
Args
,
class
In
,
class
...
Ts
>
struct
mpi_bind_sig_impl
{
using
sub
=
typename
mpi_bind_sig_single
<
In
,
std
::
is_placeholder
<
typename
detail
::
tl_at
<
Args
,
I
>::
type
>::
value
,
I
,
Size
>::
type
;
using
type
=
typename
std
::
conditional
<
std
::
is_same
<
sub
,
none_t
>::
value
,
void
,
typename
std
::
conditional
<
std
::
is_same
<
sub
,
void
>::
value
,
typename
mpi_bind_sig_impl
<
I
+
1
,
Size
,
Args
,
In
,
Ts
...
>::
type
,
typename
mpi_bind_sig_impl
<
I
+
1
,
Size
,
Args
,
In
,
Ts
...,
sub
>::
type
>::
type
>::
type
;
};
template
<
size_t
Size
,
class
Args
,
class
In
>
struct
mpi_bind_sig_impl
<
Size
,
Size
,
Args
,
In
>
{
using
type
=
void
;
};
template
<
size_t
Size
,
class
Args
,
class
In
,
class
T
,
class
...
Ts
>
struct
mpi_bind_sig_impl
<
Size
,
Size
,
Args
,
In
,
T
,
Ts
...
>
{
using
type
=
detail
::
type_list
<
T
,
Ts
...
>
;
};
template
<
size_t
I
,
class
In
,
class
Out
,
class
...
Ts
>
struct
mpi_bind_sort
;
template
<
size_t
I
,
class
Out
,
class
...
Ts
>
struct
mpi_bind_sort
<
I
,
detail
::
type_list
<>
,
Out
,
Ts
...
>
{
using
type
=
typed_mpi
<
detail
::
type_list
<
Ts
...
>
,
Out
>
;
};
template
<
size_t
I
,
size_t
X
,
class
Arg
,
class
...
Args
,
class
Out
,
class
...
Ts
>
struct
mpi_bind_sort
<
I
,
detail
::
type_list
<
mpi_bind_sig_arg_t
<
Arg
,
X
>
,
Args
...
>
,
Out
,
Ts
...
>
{
using
type
=
typename
mpi_bind_sort
<
I
,
detail
::
type_list
<
Args
...,
mpi_bind_sig_arg_t
<
Arg
,
X
>>
,
Out
,
Ts
...
>::
type
;
};
template
<
size_t
I
,
class
Arg
,
class
...
Args
,
class
Out
,
class
...
Ts
>
struct
mpi_bind_sort
<
I
,
detail
::
type_list
<
mpi_bind_sig_arg_t
<
Arg
,
I
>
,
Args
...
>
,
Out
,
Ts
...
>
{
using
type
=
typename
mpi_bind_sort
<
I
+
1
,
detail
::
type_list
<
Args
...
>
,
Out
,
Ts
...,
Arg
>::
type
;
};
template
<
class
Sig
,
class
Args
>
struct
mpi_bind_sig
{
static
constexpr
size_t
num_args
=
detail
::
tl_size
<
Args
>::
value
;
using
type
=
typename
mpi_bind_sort
<
0
,
typename
mpi_bind_sig_impl
<
0
,
num_args
,
Args
,
typename
Sig
::
input_types
>::
type
,
typename
Sig
::
output_types
>::
type
;
};
template
<
template
<
class
...
>
class
Target
,
class
Sigs
,
class
...
Args
>
struct
mpi_bind
;
template
<
template
<
class
...
>
class
Target
,
class
...
Sigs
,
class
...
Ts
>
struct
mpi_bind
<
Target
,
detail
::
type_list
<
Sigs
...
>
,
Ts
...
>
{
using
args
=
detail
::
type_list
<
Ts
...
>
;
using
bound_sigs
=
detail
::
type_list
<
typename
mpi_bind_sig
<
Sigs
,
args
>::
type
...
>
;
// drop any mismatch (void) and rebuild typed actor handle
using
type
=
typename
detail
::
tl_apply
<
typename
detail
::
tl_filter_not_type
<
bound_sigs
,
void
>::
type
,
Target
>::
type
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_MPI_BIND_HPP
libcaf_core/caf/detail/purge_refs.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_PURGE_REFS_HPP
#define CAF_DETAIL_PURGE_REFS_HPP
#include <functional>
#include "caf/detail/type_traits.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
T
>
struct
purge_refs_impl
{
using
type
=
T
;
};
template
<
class
T
>
struct
purge_refs_impl
<
std
::
reference_wrapper
<
T
>>
{
using
type
=
T
;
};
template
<
class
T
>
struct
purge_refs_impl
<
std
::
reference_wrapper
<
const
T
>>
{
using
type
=
T
;
};
/// Removes references and reference wrappers.
template
<
class
T
>
struct
purge_refs
{
using
type
=
typename
purge_refs_impl
<
typename
std
::
decay
<
T
>::
type
>::
type
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_PURGE_REFS_HPP
libcaf_core/caf/detail/typed_actor_util.hpp
View file @
b749cc1f
...
...
@@ -41,34 +41,6 @@ class typed_continue_helper;
namespace
caf
{
namespace
detail
{
template
<
class
T
>
struct
unwrap_std_tuple
{
using
type
=
type_list
<
T
>
;
};
template
<
class
...
Ts
>
struct
unwrap_std_tuple
<
std
::
tuple
<
Ts
...
>>
{
using
type
=
type_list
<
Ts
...
>
;
};
template
<
class
T
>
struct
deduce_lhs_result
{
using
type
=
typename
unwrap_std_tuple
<
T
>::
type
;
};
template
<
class
T
>
struct
deduce_rhs_result
{
using
type
=
type_list
<>
;
};
template
<
class
T
>
struct
deduce_mpi
{
using
result
=
typename
implicit_conversions
<
typename
T
::
result_type
>::
type
;
using
arg_t
=
typename
tl_map
<
typename
T
::
arg_types
,
std
::
decay
>::
type
;
using
type
=
typed_mpi
<
arg_t
,
typename
deduce_lhs_result
<
result
>::
type
>
;
};
template
<
class
Arguments
,
class
Signature
>
struct
input_is_eval_impl
:
std
::
false_type
{};
...
...
@@ -104,30 +76,35 @@ struct type_checker<message, F> {
}
};
template
<
int
X
,
int
Pos
,
class
A
>
/// Generates an error using static_assert on an interface mismatch.
/// @tparam NumMessageHandlers The number of message handlers
/// provided by the user.
/// @tparam Pos The index at which an error was detected or a negative value
/// if too many or too few handlers were provided.
/// @tparam RemainingXs The remaining deduced messaging interfaces of the
/// provided message handlers at the time of the error.
/// @tparam RemainingYs The remaining unimplemented message handler
/// signatures at the time of the error.
template
<
int
NumMessageHandlers
,
int
Pos
,
class
RemainingXs
,
class
RemainingYs
>
struct
static_error_printer
{
static_assert
(
X
!=
Pos
,
"unexpected handler some position > 20"
);
static_assert
(
NumMessageHandlers
==
Pos
,
"unexpected handler some index > 20"
);
};
template
<
int
X
,
class
A
>
struct
static_error_printer
<
X
,
-
3
,
A
>
{
static_assert
(
X
==
-
1
,
"too few message handlers defined
"
);
template
<
int
N
,
class
Xs
,
class
Ys
>
struct
static_error_printer
<
N
,
-
2
,
Xs
,
Ys
>
{
static_assert
(
N
==
-
1
,
"too many message handlers
"
);
};
template
<
int
X
,
class
A
>
struct
static_error_printer
<
X
,
-
2
,
A
>
{
static_assert
(
X
==
-
1
,
"too many message handlers defined
"
);
template
<
int
N
,
class
Xs
,
class
Ys
>
struct
static_error_printer
<
N
,
-
1
,
Xs
,
Ys
>
{
static_assert
(
N
==
-
1
,
"not enough message handlers
"
);
};
template
<
int
X
,
class
A
>
struct
static_error_printer
<
X
,
-
1
,
A
>
{
// everything' fine
};
#define CAF_STATICERR(Pos) \
template <int X, class A> \
struct static_error_printer< X, Pos, A > { \
static_assert(X == -1, "unexpected handler at position " #Pos ); \
#define CAF_STATICERR(x) \
template <int N, class Xs, class Ys> \
struct static_error_printer<N, x, Xs, Ys> { \
static_assert(N == x, "unexpected handler at index " #x ); \
}
CAF_STATICERR
(
0
);
CAF_STATICERR
(
1
);
CAF_STATICERR
(
2
);
...
...
@@ -138,110 +115,6 @@ CAF_STATICERR(12); CAF_STATICERR(13); CAF_STATICERR(14);
CAF_STATICERR
(
15
);
CAF_STATICERR
(
16
);
CAF_STATICERR
(
17
);
CAF_STATICERR
(
18
);
CAF_STATICERR
(
19
);
CAF_STATICERR
(
20
);
template
<
class
A
,
class
B
,
template
<
class
,
class
>
class
Predicate
>
struct
static_asserter
{
static
void
verify_match
()
{
static
constexpr
int
x
=
Predicate
<
A
,
B
>::
value
;
using
type_x
=
typename
tl_at
<
B
,
(
x
<
0
?
0
:
x
)
>::
type
;
static_error_printer
<
x
,
x
,
type_x
>
dummy
;
static_cast
<
void
>
(
dummy
);
}
};
template
<
class
T
>
struct
lifted_result_type
{
using
type
=
type_list
<
typename
implicit_conversions
<
T
>::
type
>
;
};
template
<
class
...
Ts
>
struct
lifted_result_type
<
std
::
tuple
<
Ts
...
>>
{
using
type
=
type_list
<
Ts
...
>
;
};
template
<
class
T
>
struct
deduce_lifted_output_type
{
using
type
=
T
;
};
template
<
class
R
>
struct
deduce_lifted_output_type
<
type_list
<
typed_continue_helper
<
R
>>>
{
using
type
=
typename
lifted_result_type
<
R
>::
type
;
};
template
<
class
Signatures
,
class
InputTypes
>
struct
deduce_output_type_impl
{
using
signature
=
typename
tl_find
<
Signatures
,
input_is
<
InputTypes
>::
template
eval
>
::
type
;
static_assert
(
!
std
::
is_same
<
signature
,
none_t
>::
value
,
"typed actor does not support given input"
);
using
type
=
typename
signature
::
output_types
;
// generates the appropriate `delegated<...>` type from given signatures
using
delegated_type
=
typename
detail
::
tl_apply
<
type
,
delegated
>::
type
;
// generates the appropriate `std::tuple<...>` type from given signature
using
tuple_type
=
typename
detail
::
tl_apply
<
type
,
std
::
tuple
>::
type
;
};
template
<
class
InputTypes
>
struct
deduce_output_type_impl
<
none_t
,
InputTypes
>
{
using
type
=
message
;
using
delegated_type
=
delegated
<
message
>
;
using
tuple_type
=
std
::
tuple
<
message
>
;
};
template
<
class
Handle
,
class
InputTypes
>
struct
deduce_output_type
:
deduce_output_type_impl
<
typename
Handle
::
signatures
,
InputTypes
>
{
// nop
};
template
<
class
T
,
class
InputTypes
>
struct
deduce_output_type
<
T
*
,
InputTypes
>
:
deduce_output_type_impl
<
typename
T
::
signatures
,
InputTypes
>
{
// nop
};
template
<
class
...
Ts
>
struct
common_result_type
;
template
<
class
T
>
struct
common_result_type
<
T
>
{
using
type
=
T
;
};
template
<
class
T
,
class
...
Us
>
struct
common_result_type
<
T
,
T
,
Us
...
>
{
using
type
=
typename
common_result_type
<
T
,
Us
...
>::
type
;
};
template
<
class
T1
,
class
T2
,
class
...
Us
>
struct
common_result_type
<
T1
,
T2
,
Us
...
>
{
using
type
=
void
;
};
template
<
class
OrigSigs
,
class
DestSigs
,
class
ArgTypes
>
struct
sender_signature_checker
{
static
void
check
()
{
using
dest_output_types
=
typename
deduce_output_type
<
DestSigs
,
ArgTypes
>::
type
;
sender_signature_checker
<
DestSigs
,
OrigSigs
,
dest_output_types
>::
check
();
}
};
template
<
class
OrigSigs
,
class
DestSigs
>
struct
sender_signature_checker
<
OrigSigs
,
DestSigs
,
detail
::
type_list
<
void
>>
{
static
void
check
()
{}
};
template
<
class
OrigSigs
,
class
DestSigs
>
struct
sender_signature_checker
<
OrigSigs
,
DestSigs
,
detail
::
type_list
<>>
{
static
void
check
()
{}
};
template
<
class
...
Ts
>
struct
extend_with_helper
;
...
...
libcaf_core/caf/detail/unboxed.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_UNBOXED_HPP
#define CAF_DETAIL_UNBOXED_HPP
#include <memory>
#include "caf/atom.hpp"
#include "caf/detail/wrapped.hpp"
namespace
caf
{
namespace
detail
{
// strips `wrapped` and converts `atom_constant` to `atom_value`
template
<
class
T
>
struct
unboxed
{
using
type
=
T
;
};
template
<
class
T
>
struct
unboxed
<
detail
::
wrapped
<
T
>>
{
using
type
=
typename
detail
::
wrapped
<
T
>::
type
;
};
template
<
class
T
>
struct
unboxed
<
detail
::
wrapped
<
T
>
(
&
)()
>
{
using
type
=
typename
detail
::
wrapped
<
T
>::
type
;
};
template
<
class
T
>
struct
unboxed
<
detail
::
wrapped
<
T
>
()
>
{
using
type
=
typename
detail
::
wrapped
<
T
>::
type
;
};
template
<
class
T
>
struct
unboxed
<
detail
::
wrapped
<
T
>
(
*
)()
>
{
using
type
=
typename
detail
::
wrapped
<
T
>::
type
;
};
template
<
atom_value
V
>
struct
unboxed
<
atom_constant
<
V
>>
{
using
type
=
atom_value
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_UNBOXED_HPP
libcaf_core/caf/detail/wrapped.hpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_WRAPPED_HPP
#define CAF_DETAIL_WRAPPED_HPP
namespace
caf
{
namespace
detail
{
template
<
class
T
>
struct
wrapped
{
constexpr
wrapped
()
{
// nop
}
using
type
=
T
;
};
template
<
class
T
>
struct
wrapped
<
wrapped
<
T
>>
{
constexpr
wrapped
()
{
// nop
}
using
type
=
typename
wrapped
<
T
>::
type
;
};
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_WRAPPED_HPP
libcaf_core/caf/function_view.hpp
View file @
b749cc1f
...
...
@@ -26,6 +26,7 @@
#include "caf/expected.hpp"
#include "caf/typed_actor.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/response_type.hpp"
namespace
caf
{
...
...
@@ -111,6 +112,10 @@ struct function_view_flattened_result<std::tuple<void>> {
using
type
=
unit_t
;
};
template
<
class
T
>
using
function_view_flattened_result_t
=
typename
function_view_flattened_result
<
T
>::
type
;
template
<
class
T
>
struct
function_view_result
{
T
value
;
...
...
@@ -171,15 +176,13 @@ public:
/// Sends a request message to the assigned actor and returns the result.
template
<
class
...
Ts
,
class
R
=
typename
function_view_flattened_result
<
typename
detail
::
deduce_output_type
<
type
,
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
function_view_flattened_result_t
<
typename
response_type
<
typename
type
::
signatures
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>
::
type
>::
type
...
>
>::
tuple_type
>::
type
>
>
...
>::
tuple_type
>>
expected
<
R
>
operator
()(
Ts
&&
...
xs
)
{
if
(
impl_
.
unsafe
())
return
sec
::
bad_function_call
;
...
...
libcaf_core/caf/fwd.hpp
View file @
b749cc1f
...
...
@@ -32,9 +32,12 @@ template <class> class optional;
template
<
class
>
class
expected
;
template
<
class
>
class
intrusive_ptr
;
template
<
class
>
class
behavior_type_of
;
template
<
class
>
class
trivial_match_case
;
template
<
class
>
class
weak_intrusive_ptr
;
template
<
class
>
class
typed_continue_helper
;
template
<
class
>
struct
timeout_definition
;
// -- 3 param templates --------------------------------------------------------
template
<
class
,
class
,
int
>
class
actor_cast_access
;
...
...
libcaf_core/caf/interface_mismatch.hpp
0 → 100644
View file @
b749cc1f
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_INTERFACE_MISMATCH_HPP
#define CAF_INTERFACE_MISMATCH_HPP
#include "caf/fwd.hpp"
#include "caf/replies_to.hpp"
#include "caf/detail/type_list.hpp"
namespace
caf
{
namespace
detail
{
// imi = interface_mismatch_implementation
// Precondition: Pos == 0 && len(Xs) == len(Ys) && len(Zs) == 0
// Iterate over Xs to find a match in Ys; Zs is used as temporary storage
// to iterate over Ys. On a match, the element is removed from Xs and Ys and
// Zs are prepended to Ys again for next iteration.
// Evaluates to:
// * len(Xs) if interface check succeeds
// * Pos on a mismatch (incremented per iteration to reflect position in Xs)
template
<
int
Pos
,
class
Xs
,
class
Ys
,
class
Zs
>
struct
imi
;
// end of recursion: success (consumed both lists)
template
<
int
Pos
>
struct
imi
<
Pos
,
type_list
<>
,
type_list
<>
,
type_list
<>>
{
static
constexpr
int
value
=
Pos
;
using
xs
=
type_list
<>
;
using
ys
=
type_list
<>
;
};
// end of recursion: success (consumed both lists, except the timeout)
template
<
int
Pos
,
class
X
>
struct
imi
<
Pos
,
type_list
<
timeout_definition
<
X
>>
,
type_list
<>
,
type_list
<>>
{
static
constexpr
int
value
=
Pos
+
1
;
// count timeout def. as consumed
using
xs
=
type_list
<>
;
using
ys
=
type_list
<>
;
};
// end of recursion: failure (consumed all Xs but not all Ys)
template
<
int
Pos
,
class
Yin
,
class
Yout
,
class
...
Ys
>
struct
imi
<
Pos
,
type_list
<>
,
type_list
<
typed_mpi
<
Yin
,
Yout
>
,
Ys
...
>
,
type_list
<>>
{
static
constexpr
int
value
=
-
1
;
using
xs
=
type_list
<>
;
using
ys
=
type_list
<
typed_mpi
<
Yin
,
Yout
>
,
Ys
...
>
;
};
// end of recursion: failure (consumed all Ys but not all Xs)
template
<
int
Pos
,
class
Xin
,
class
Xout
,
class
...
Xs
>
struct
imi
<
Pos
,
type_list
<
typed_mpi
<
Xin
,
Xout
>
,
Xs
...
>
,
type_list
<>
,
type_list
<>>
{
static
constexpr
int
value
=
-
2
;
using
xs
=
type_list
<
typed_mpi
<
Xin
,
Xout
>
,
Xs
...
>
;
using
ys
=
type_list
<>
;
};
// end of recursion: failure (consumed all Ys except timeout but not all Xs)
template
<
int
Pos
,
class
X
,
class
Y
,
class
...
Ys
>
struct
imi
<
Pos
,
type_list
<
timeout_definition
<
X
>>
,
type_list
<
Y
,
Ys
...
>
,
type_list
<>>
{
static
constexpr
int
value
=
-
2
;
using
xs
=
type_list
<>
;
using
ys
=
type_list
<
Y
,
Ys
...
>
;
};
// case #1: exact match
template
<
int
Pos
,
class
In
,
class
Out
,
class
...
Xs
,
class
...
Ys
,
class
...
Zs
>
struct
imi
<
Pos
,
type_list
<
typed_mpi
<
In
,
Out
>
,
Xs
...
>
,
type_list
<
typed_mpi
<
In
,
Out
>
,
Ys
...
>
,
type_list
<
Zs
...
>>
:
imi
<
Pos
+
1
,
type_list
<
Xs
...
>
,
type_list
<
Zs
...,
Ys
...
>
,
type_list
<>>
{};
// case #2: match with skip_t
template
<
int
Pos
,
class
In
,
class
...
Xs
,
class
Out
,
class
...
Ys
,
class
...
Zs
>
struct
imi
<
Pos
,
type_list
<
typed_mpi
<
In
,
output_tuple
<
skip_t
>>
,
Xs
...
>
,
type_list
<
typed_mpi
<
In
,
Out
>
,
Ys
...
>
,
type_list
<
Zs
...
>>
:
imi
<
Pos
+
1
,
type_list
<
Xs
...
>
,
type_list
<
Zs
...,
Ys
...
>
,
type_list
<>>
{};
// case #3: no match at position
template
<
int
Pos
,
class
Xin
,
class
Xout
,
class
...
Xs
,
class
Yin
,
class
Yout
,
class
...
Ys
,
class
...
Zs
>
struct
imi
<
Pos
,
type_list
<
typed_mpi
<
Xin
,
Xout
>
,
Xs
...
>
,
type_list
<
typed_mpi
<
Yin
,
Yout
>
,
Ys
...
>
,
type_list
<
Zs
...
>>
:
imi
<
Pos
,
type_list
<
typed_mpi
<
Xin
,
Xout
>
,
Xs
...
>
,
type_list
<
Ys
...
>
,
type_list
<
Zs
...,
typed_mpi
<
Yin
,
Yout
>>>
{};
// case #4: no match (error)
template
<
int
Pos
,
class
X
,
class
...
Xs
,
class
...
Zs
>
struct
imi
<
Pos
,
type_list
<
X
,
Xs
...
>
,
type_list
<>
,
type_list
<
Zs
...
>>
{
static
constexpr
int
value
=
Pos
;
using
xs
=
type_list
<
X
,
Xs
...
>
;
using
ys
=
type_list
<
Zs
...
>
;
};
}
// namespace detail
/// Scans two typed MPI lists for compatibility, returning the index of the
/// first mismatch. Returns the number of elements on a match.
/// @pre len(Found) == len(Expected)
template
<
class
Found
,
class
Expected
>
using
interface_mismatch_t
=
detail
::
imi
<
0
,
Found
,
Expected
,
detail
::
type_list
<>>
;
}
// namespace caf
#endif // CAF_INTERFACE_MISMATCH_HPP
libcaf_core/caf/local_actor.hpp
View file @
b749cc1f
...
...
@@ -46,6 +46,7 @@
#include "caf/typed_actor.hpp"
#include "caf/actor_config.hpp"
#include "caf/actor_system.hpp"
#include "caf/response_type.hpp"
#include "caf/spawn_options.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/abstract_group.hpp"
...
...
@@ -311,13 +312,9 @@ public:
template
<
message_priority
P
=
message_priority
::
normal
,
class
Handle
=
actor
,
class
...
Ts
>
typename
detail
::
deduce_output_type
<
Handle
,
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
typename
response_type
<
typename
Handle
::
signatures
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>::
delegated_type
delegate
(
const
Handle
&
dest
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"nothing to delegate"
);
...
...
@@ -326,9 +323,7 @@ public:
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Handle
>::
type
,
token
>::
value
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Handle
>
,
token
>::
valid
,
"receiver does not accept given message"
);
auto
mid
=
current_element_
->
mid
;
current_element_
->
mid
=
P
==
message_priority
::
high
...
...
libcaf_core/caf/match_case.hpp
View file @
b749cc1f
...
...
@@ -35,7 +35,6 @@
#include "caf/detail/apply_args.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/pseudo_tuple.hpp"
#include "caf/detail/left_or_right.hpp"
#include "caf/detail/invoke_result_visitor.hpp"
namespace
caf
{
...
...
libcaf_core/caf/mixin/requester.hpp
View file @
b749cc1f
...
...
@@ -27,6 +27,7 @@
#include "caf/actor.hpp"
#include "caf/message.hpp"
#include "caf/duration.hpp"
#include "caf/response_type.hpp"
#include "caf/response_handle.hpp"
#include "caf/message_priority.hpp"
#include "caf/check_typed_input.hpp"
...
...
@@ -62,13 +63,11 @@ public:
template
<
message_priority
P
=
message_priority
::
normal
,
class
Handle
=
actor
,
class
...
Ts
>
response_handle
<
Subtype
,
typename
detail
::
deduce_output_type
<
Handle
,
detail
::
type_list
<
response_type_t
<
typename
Handle
::
signatures
,
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
>::
type
,
>::
type
...
>
,
is_blocking_requester
<
Subtype
>::
value
>
request
(
const
Handle
&
dest
,
const
duration
&
timeout
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
...
...
@@ -77,7 +76,7 @@ public:
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Handle
>::
type
,
token
>::
value
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Handle
>
,
token
>::
valid
,
"receiver does not accept given message"
);
auto
dptr
=
static_cast
<
Subtype
*>
(
this
);
auto
req_id
=
dptr
->
new_request_id
(
P
);
...
...
libcaf_core/caf/mixin/sender.hpp
View file @
b749cc1f
...
...
@@ -27,6 +27,7 @@
#include "caf/actor.hpp"
#include "caf/message.hpp"
#include "caf/duration.hpp"
#include "caf/response_type.hpp"
#include "caf/response_handle.hpp"
#include "caf/message_priority.hpp"
#include "caf/check_typed_input.hpp"
...
...
@@ -58,35 +59,23 @@ public:
template
<
message_priority
P
=
message_priority
::
normal
,
class
Dest
=
actor
,
class
...
Ts
>
void
send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
using
detail
::
type_list
;
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
token
=
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
using
res_t
=
response_type
<
signatures_of_t
<
Dest
>
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
>
...
>
;
static_assert
(
!
statically_typed
<
Subtype
>
()
||
statically_typed
<
Dest
>
(),
"statically typed actors can only send() to other "
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
value
,
"receiver does not accept given message"
);
// TODO: this only checks one way, we should check for loops
static_assert
(
is_void_response
<
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
type
>::
value
||
actor_accepts_message
<
typename
signatures_of
<
Subtype
>::
type
,
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
type
>::
value
,
static_assert
(
res_t
::
valid
,
"receiver does not accept given message"
);
static_assert
(
std
::
is_same
<
typename
res_t
::
type
,
type_list
<>>::
value
||
response_type_unbox
<
signatures_of_t
<
Subtype
>
,
typename
res_t
::
type
>::
valid
,
"this actor does not accept the response message"
);
dest
->
eq_impl
(
message_id
::
make
(
P
),
this
->
ctrl
(),
this
->
context
(),
std
::
forward
<
Ts
>
(
xs
)...);
...
...
@@ -101,10 +90,10 @@ public:
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
val
ue
,
>::
val
id
,
"receiver does not accept given message"
);
dest
->
eq_impl
(
message_id
::
make
(
P
),
nullptr
,
this
->
context
(),
std
::
forward
<
Ts
>
(
xs
)...);
...
...
@@ -122,25 +111,29 @@ public:
"statically typed actors are only allowed to send() to other "
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
val
ue
,
>::
val
id
,
"receiver does not accept given message"
);
// TODO: this only checks one way, we should check for loops
static_assert
(
is_void_response
<
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
typename
response_type
<
signatures_of_t
<
Dest
>
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>::
type
>::
value
||
actor_accepts_message
<
typename
signatures_of
<
Subtype
>::
type
,
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
||
response_type_unbox
<
signatures_of_t
<
Subtype
>
,
typename
response_type
<
signatures_of_t
<
Dest
>
,
detail
::
implicit_conversions_t
<
typename
std
::
decay
<
Ts
>::
type
>
...
>::
type
>::
val
ue
,
>::
val
id
,
"this actor does not accept the response message"
);
dptr
()
->
system
().
scheduler
().
delayed_send
(
rtime
,
dptr
()
->
ctrl
(),
actor_cast
<
strong_actor_ptr
>
(
dest
),
...
...
@@ -156,10 +149,10 @@ public:
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
val
ue
,
>::
val
id
,
"receiver does not accept given message"
);
dptr
()
->
system
().
scheduler
().
delayed_send
(
rtime
,
nullptr
,
actor_cast
<
strong_actor_ptr
>
(
dest
),
...
...
libcaf_core/caf/replies_to.hpp
View file @
b749cc1f
...
...
@@ -37,16 +37,22 @@ std::string replies_to_type_name(size_t input_size,
const
std
::
string
*
output_opt1
);
/// @endcond
template
<
class
InputTypes
,
class
OutputTypes
>
struct
typed_mpi
;
template
<
class
...
>
struct
output_stream
{}
;
template
<
class
...
Is
,
class
...
Ls
>
struct
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
template
<
class
...
>
struct
output_tuple
{};
template
<
class
Input
,
class
Output
>
struct
typed_mpi
{};
/*
<detail::type_list<Is...>,
detail::type_list<Ls...>> {
static_assert(sizeof...(Is) > 0, "template parameter pack Is empty");
static_assert(sizeof...(Ls) > 0, "template parameter pack Ls empty");
using
input
_types
=
detail
::
type_list
<
Is
...
>
;
using
output
_types
=
detail
::
type_list
<
Ls
...
>
;
using input = detail::type_list<Is...>;
using output = detail::type_list<Ls...>;
static_assert(!detail::tl_exists<
input_types,
is_illegal_message_element
...
...
@@ -57,15 +63,20 @@ struct typed_mpi<detail::type_list<Is...>,
>::value,
"interface definition contains an illegal message type");
};
*/
template
<
class
...
Is
>
struct
replies_to
{
template
<
class
...
Os
>
using
with
=
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
detail
::
type_list
<
Os
...
>>
;
using
with
=
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
output_tuple
<
Os
...
>>
;
/// @private
template
<
class
...
Os
>
using
with_stream
=
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
output_stream
<
Os
...
>>
;
};
template
<
class
...
Is
>
using
reacts_to
=
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
detail
::
type_list
<
void
>>
;
using
reacts_to
=
typed_mpi
<
detail
::
type_list
<
Is
...
>
,
output_tuple
<
void
>>
;
}
// namespace caf
...
...
libcaf_core/caf/
detail/mpi_sequencer
.hpp
→
libcaf_core/caf/
response_type
.hpp
View file @
b749cc1f
...
...
@@ -17,53 +17,78 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_
DETAIL_MPI_SEQUENCER
_HPP
#define CAF_
DETAIL_MPI_SEQUENCER
_HPP
#ifndef CAF_
RESPONSE_TYPE
_HPP
#define CAF_
RESPONSE_TYPE
_HPP
#include "caf/replies_to.hpp"
#include <tuple>
#include "caf/fwd.hpp"
#include "caf/detail/type_list.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
X
,
class
Y
>
struct
mpi_sequencer_one
{
using
type
=
void
;
/// Defines:
/// - `valid` if typedefs are set, can be used to check if actors accept input
/// - `type` list of output types or `message` for dynamically typed actors
/// - `delegated_type` type above wrapped in a `delegated`
/// - `tuple_type` output types wrapped in a `std::tuple` or `message`
template
<
class
Ts
,
class
...
Xs
>
struct
response_type
;
// short-circuit for dynamically typed messaging
template
<
class
...
Xs
>
struct
response_type
<
none_t
,
Xs
...
>
{
static
constexpr
bool
valid
=
true
;
using
type
=
message
;
using
delegated_type
=
delegated
<
message
>
;
using
tuple_type
=
message
;
};
template
<
class
...
Xs
,
class
...
Ys
,
class
...
Zs
>
struct
mpi_sequencer_one
<
typed_mpi
<
type_list
<
Xs
...
>
,
type_list
<
Ys
...
>>
,
typed_mpi
<
type_list
<
Ys
...
>
,
type_list
<
Zs
...
>>
>
{
using
type
=
typed_mpi
<
type_list
<
Xs
...
>
,
type_list
<
Zs
...
>>
;
// end of recursion (suppress type definitions for enabling SFINAE)
template
<
class
...
Xs
>
struct
response_type
<
detail
::
type_list
<>
,
Xs
...
>
{
static
constexpr
bool
valid
=
false
;
};
template
<
class
X
,
class
Y
>
struct
mpi_sequencer_all
;
// case #1: no match
template
<
class
In
,
class
Out
,
class
...
Ts
,
class
...
Xs
>
struct
response_type
<
detail
::
type_list
<
typed_mpi
<
In
,
Out
>
,
Ts
...
>
,
Xs
...
>
:
response_type
<
detail
::
type_list
<
Ts
...
>
,
Xs
...
>
{};
template
<
class
X
,
class
...
Ys
>
struct
mpi_sequencer_all
<
X
,
type_list
<
Ys
...
>>
{
using
type
=
type_list
<
typename
mpi_sequencer_one
<
X
,
Ys
>::
type
...
>
;
// case #2: match
template
<
class
...
Out
,
class
...
Ts
,
class
...
Xs
>
struct
response_type
<
detail
::
type_list
<
typed_mpi
<
detail
::
type_list
<
Xs
...
>
,
output_tuple
<
Out
...
>>
,
Ts
...
>
,
Xs
...
>
{
static
constexpr
bool
valid
=
true
;
using
type
=
detail
::
type_list
<
Out
...
>
;
using
tuple_type
=
std
::
tuple
<
Out
...
>
;
using
delegated_type
=
delegated
<
Out
...
>
;
};
template
<
template
<
class
...
>
class
Target
,
class
Ys
,
class
...
Xs
>
struct
mpi_sequencer
{
// combine each X with all Ys
using
all
=
typename
tl_concat
<
typename
mpi_sequencer_all
<
Xs
,
Ys
>::
type
...
>::
type
;
// drop all mismatches (void results)
using
filtered
=
typename
tl_filter_not_type
<
all
,
void
>::
type
;
// raise error if we don't have a single match
static_assert
(
tl_size
<
filtered
>::
value
>
0
,
"Left-hand actor type does not produce a single result which "
"is valid as input to the right-hand actor type."
);
// compute final actor type
using
type
=
typename
tl_apply
<
filtered
,
Target
>::
type
;
};
/// Computes the response message for input `Xs...` from the list
/// of message passing interfaces `Ts`.
template
<
class
Ts
,
class
...
Xs
>
using
response_type_t
=
typename
response_type
<
Ts
,
Xs
...
>::
type
;
/// Unboxes `Xs` and calls `response_type`.
template
<
class
Ts
,
class
Xs
>
struct
response_type_unbox
;
template
<
class
Ts
,
class
...
Xs
>
struct
response_type_unbox
<
Ts
,
detail
::
type_list
<
Xs
...
>>
:
response_type
<
Ts
,
Xs
...
>
{};
template
<
class
Ts
>
struct
response_type_unbox
<
Ts
,
message
>
:
response_type
<
Ts
,
message
>
{};
/// Computes the response message for input `Xs` from the list
/// of message passing interfaces `Ts`.
template
<
class
Ts
,
class
Xs
>
using
response_type_unbox_t
=
typename
response_type_unbox
<
Ts
,
Xs
>::
type
;
}
// namespace detail
}
// namespace caf
#endif // CAF_
DETAIL_MPI_SEQUENCER
_HPP
#endif // CAF_
RESPONSE_TYPE
_HPP
libcaf_core/caf/send.hpp
View file @
b749cc1f
...
...
@@ -26,9 +26,10 @@
#include "caf/actor_addr.hpp"
#include "caf/message_id.hpp"
#include "caf/typed_actor.hpp"
#include "caf/response_type.hpp"
#include "caf/system_messages.hpp"
#include "caf/is_message_sink.hpp"
#include "caf/message_priority.hpp"
#include "caf/system_messages.hpp"
#include "caf/check_typed_input.hpp"
namespace
caf
{
...
...
@@ -38,31 +39,28 @@ template <message_priority P = message_priority::normal,
class
Source
=
actor
,
class
Dest
=
actor
,
class
...
Ts
>
void
send_as
(
const
Source
&
src
,
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
token
=
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
using
token
=
detail
::
type_list
<
detail
::
strip_and_convert_t
<
Ts
>
...
>
;
static_assert
(
!
statically_typed
<
Source
>
()
||
statically_typed
<
Dest
>
(),
"statically typed actors can only send() to other "
"statically typed actors; use anon_send() or request() when "
"communicating with dynamically typed actors"
);
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
value
,
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
valid
,
"receiver does not accept given message"
);
// TODO: this only checks one way, we should check for loops
static_assert
(
is_void_response
<
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
type
response_type_unbox_t
<
signatures_of_t
<
Dest
>
,
token
>
>::
value
||
actor_accepts_message
<
typename
signatures_of
<
Source
>::
type
,
typename
response_to
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
type
>::
value
,
||
response_type_unbox
<
signatures_of_t
<
Source
>
,
response_type_unbox_t
<
signatures_of_t
<
Dest
>
,
token
>
>::
valid
,
"this actor does not accept the response message"
);
dest
->
eq_impl
(
message_id
::
make
(
P
),
actor_cast
<
strong_actor_ptr
>
(
src
),
nullptr
,
std
::
forward
<
Ts
>
(
xs
)...);
...
...
@@ -73,15 +71,8 @@ template <message_priority P = message_priority::normal,
class
Dest
=
actor
,
class
...
Ts
>
void
anon_send
(
const
Dest
&
dest
,
Ts
&&
...
xs
)
{
static_assert
(
sizeof
...(
Ts
)
>
0
,
"no message to send"
);
using
token
=
detail
::
type_list
<
typename
detail
::
implicit_conversions
<
typename
std
::
decay
<
Ts
>::
type
>::
type
...
>
;
static_assert
(
actor_accepts_message
<
typename
signatures_of
<
Dest
>::
type
,
token
>::
value
,
using
token
=
detail
::
type_list
<
detail
::
strip_and_convert_t
<
Ts
>
...
>
;
static_assert
(
response_type_unbox
<
signatures_of_t
<
Dest
>
,
token
>::
valid
,
"receiver does not accept given message"
);
dest
->
eq_impl
(
message_id
::
make
(
P
),
nullptr
,
nullptr
,
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
libcaf_core/caf/typed_actor.hpp
View file @
b749cc1f
...
...
@@ -26,20 +26,17 @@
#include "caf/actor_cast.hpp"
#include "caf/replies_to.hpp"
#include "caf/actor_system.hpp"
#include "caf/composed_type.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/typed_response_promise.hpp"
#include "caf/unsafe_actor_handle_init.hpp"
#include "caf/de
corator/adapter
.hpp"
#include "caf/de
tail/mpi_splice
.hpp"
#include "caf/decorator/splitter.hpp"
#include "caf/decorator/sequencer.hpp"
#include "caf/detail/mpi_bind.hpp"
#include "caf/detail/mpi_splice.hpp"
#include "caf/detail/mpi_sequencer.hpp"
namespace
caf
{
template
<
class
...
Sigs
>
...
...
@@ -196,19 +193,6 @@ class typed_actor : detail::comparable<typed_actor<Sigs...>>,
ptr_
.
swap
(
other
.
ptr_
);
}
template
<
class
...
Ts
>
typename
detail
::
mpi_bind
<
caf
::
typed_actor
,
detail
::
type_list
<
Sigs
...
>
,
typename
std
::
decay
<
Ts
>::
type
...
>::
type
bind
(
Ts
&&
...
xs
)
const
{
auto
&
sys
=
*
(
ptr_
->
home_system
);
auto
ptr
=
make_actor
<
decorator
::
adapter
,
strong_actor_ptr
>
(
sys
.
next_actor_id
(),
sys
.
node
(),
&
sys
,
ptr_
,
make_message
(
xs
...));
return
{
ptr
.
release
(),
false
};
}
/// Queries whether this object was constructed using
/// `unsafe_actor_handle_init` or is in moved-from state.
bool
unsafe
()
const
{
...
...
@@ -290,18 +274,10 @@ bool operator!=(const typed_actor<Xs...>& x,
/// Returns a new actor that implements the composition `f.g(x) = f(g(x))`.
/// @relates typed_actor
template
<
class
...
Xs
,
class
...
Ys
>
typename
detail
::
mpi_sequencer
<
typed_actor
,
detail
::
type_list
<
Xs
...
>
,
Ys
...
>::
type
composed_type_t
<
detail
::
type_list
<
Xs
...
>
,
detail
::
type_list
<
Ys
...
>>
operator
*
(
typed_actor
<
Xs
...
>
f
,
typed_actor
<
Ys
...
>
g
)
{
using
result
=
typename
detail
::
mpi_sequencer
<
typed_actor
,
detail
::
type_list
<
Xs
...
>
,
Ys
...
>::
type
;
using
result
=
composed_type_t
<
detail
::
type_list
<
Xs
...
>
,
detail
::
type_list
<
Ys
...
>>
;
auto
&
sys
=
g
->
home_system
();
auto
mts
=
sys
.
message_types
(
detail
::
type_list
<
result
>
{});
return
make_actor
<
decorator
::
sequencer
,
result
>
(
...
...
libcaf_core/caf/typed_behavior.hpp
View file @
b749cc1f
...
...
@@ -21,11 +21,12 @@
#define CAF_TYPED_BEHAVIOR_HPP
#include "caf/behavior.hpp"
#include "caf/deduce_mpi.hpp"
#include "caf/message_handler.hpp"
#include "caf/system_messages.hpp"
#include "caf/interface_mismatch.hpp"
#include "caf/typed_continue_helper.hpp"
#include "caf/detail/ctm.hpp"
#include "caf/detail/typed_actor_util.hpp"
namespace
caf
{
...
...
@@ -150,26 +151,34 @@ class behavior_stack_based_impl;
template
<
class
...
Sigs
>
class
typed_behavior
{
public:
// -- friends ----------------------------------------------------------------
template
<
class
...
OtherSigs
>
friend
class
typed_actor
;
template
<
class
,
class
,
class
>
friend
class
mixin
::
behavior_stack_based_impl
;
// -- member types -----------------------------------------------------------
/// Stores the template parameter pack in a type list.
using
signatures
=
detail
::
type_list
<
Sigs
...
>
;
/// Empty struct tag for constructing from an untyped behavior.
struct
unsafe_init
{
};
// -- constructors, destructors, and assignment operators --------------------
typed_behavior
(
typed_behavior
&&
)
=
default
;
typed_behavior
(
const
typed_behavior
&
)
=
default
;
typed_behavior
&
operator
=
(
typed_behavior
&&
)
=
default
;
typed_behavior
&
operator
=
(
const
typed_behavior
&
)
=
default
;
using
signatures
=
detail
::
type_list
<
Sigs
...
>
;
template
<
class
T
,
class
...
Ts
>
typed_behavior
(
T
x
,
Ts
...
xs
)
{
set
(
detail
::
make_behavior
(
std
::
move
(
x
),
std
::
move
(
xs
)...));
}
struct
unsafe_init
{
};
typed_behavior
(
unsafe_init
,
behavior
x
)
:
bhvr_
(
std
::
move
(
x
))
{
// nop
}
...
...
@@ -178,19 +187,25 @@ public:
// nop
}
// -- modifiers --------------------------------------------------------------
/// Exchanges the contents of this and other.
inline
void
swap
(
typed_behavior
&
other
)
{
bhvr_
.
swap
(
other
.
bhvr_
);
}
explicit
operator
bool
()
const
{
return
static_cast
<
bool
>
(
bhvr_
);
}
/// Invokes the timeout callback.
void
handle_timeout
()
{
bhvr_
.
handle_timeout
();
}
// -- observers --------------------------------------------------------------
/// Returns whether this behavior contains any callbacks.
explicit
operator
bool
()
const
{
return
static_cast
<
bool
>
(
bhvr_
);
}
/// Returns the duration after which receives using
/// this behavior should time out.
const
duration
&
timeout
()
const
{
...
...
@@ -214,15 +229,12 @@ private:
template
<
class
...
Ts
>
void
set
(
intrusive_ptr
<
detail
::
default_behavior_impl
<
std
::
tuple
<
Ts
...
>>>
bp
)
{
using
impl
=
detail
::
default_behavior_impl
<
std
::
tuple
<
Ts
...
>>
;
using
mpi
=
typename
detail
::
tl_map
<
typename
impl
::
cases
,
detail
::
deduce_mpi
>::
type
;
static_assert
(
detail
::
tl_is_distinct
<
mpi
>::
value
,
"multiple handler defintions found"
);
detail
::
static_asserter
<
signatures
,
mpi
,
detail
::
ctm
>::
verify_match
();
using
found_signatures
=
detail
::
type_list
<
deduce_mpi_t
<
Ts
>
...
>
;
using
m
=
interface_mismatch_t
<
found_signatures
,
signatures
>
;
// trigger static assert on mismatch
detail
::
static_error_printer
<
sizeof
...(
Ts
),
m
::
value
,
typename
m
::
xs
,
typename
m
::
ys
>
guard
;
CAF_IGNORE_UNUSED
(
guard
);
// final (type-erasure) step
intrusive_ptr
<
detail
::
behavior_impl
>
ptr
=
std
::
move
(
bp
);
bhvr_
.
assign
(
std
::
move
(
ptr
));
...
...
libcaf_core/src/actor.cpp
View file @
b749cc1f
...
...
@@ -30,7 +30,6 @@
#include "caf/scoped_actor.hpp"
#include "caf/event_based_actor.hpp"
#include "caf/decorator/adapter.hpp"
#include "caf/decorator/splitter.hpp"
#include "caf/decorator/sequencer.hpp"
...
...
@@ -77,12 +76,6 @@ actor_addr actor::address() const noexcept {
return
actor_cast
<
actor_addr
>
(
ptr_
);
}
actor
actor
::
bind_impl
(
message
msg
)
const
{
auto
&
sys
=
*
(
ptr_
->
home_system
);
return
make_actor
<
decorator
::
adapter
,
actor
>
(
sys
.
next_actor_id
(),
sys
.
node
(),
&
sys
,
ptr_
,
std
::
move
(
msg
));
}
actor
operator
*
(
actor
f
,
actor
g
)
{
auto
&
sys
=
f
->
home_system
();
return
make_actor
<
decorator
::
sequencer
,
actor
>
(
...
...
libcaf_core/src/adapter.cpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/decorator/adapter.hpp"
#include "caf/sec.hpp"
#include "caf/actor_cast.hpp"
#include "caf/actor_system.hpp"
#include "caf/mailbox_element.hpp"
#include "caf/system_messages.hpp"
#include "caf/default_attachable.hpp"
#include "caf/detail/disposer.hpp"
#include "caf/detail/merged_tuple.hpp"
#include "caf/detail/sync_request_bouncer.hpp"
namespace
caf
{
namespace
decorator
{
adapter
::
adapter
(
strong_actor_ptr
decorated
,
message
msg
)
:
monitorable_actor
(
actor_config
{}.
add_flag
(
is_actor_bind_decorator_flag
)),
decorated_
(
std
::
move
(
decorated
)),
merger_
(
std
::
move
(
msg
))
{
// bound actor has dependency on the decorated actor by default;
// if the decorated actor is already dead upon establishing the
// dependency, the actor is spawned dead
decorated_
->
get
()
->
attach
(
default_attachable
::
make_monitor
(
decorated_
->
get
()
->
address
(),
address
()));
}
void
adapter
::
enqueue
(
mailbox_element_ptr
x
,
execution_unit
*
context
)
{
CAF_ASSERT
(
x
);
auto
down_msg_handler
=
[
&
](
down_msg
&
dm
)
{
cleanup
(
std
::
move
(
dm
.
reason
),
context
);
};
if
(
handle_system_message
(
*
x
,
context
,
false
,
down_msg_handler
))
return
;
strong_actor_ptr
decorated
;
message
merger
;
error
fail_state
;
shared_critical_section
([
&
]
{
decorated
=
decorated_
;
merger
=
merger_
;
fail_state
=
fail_state_
;
});
if
(
!
decorated
)
{
bounce
(
x
,
fail_state
);
return
;
}
message
tmp
{
detail
::
merged_tuple
::
make
(
merger
,
x
->
move_content_to_message
())};
decorated
->
enqueue
(
make_mailbox_element
(
std
::
move
(
x
->
sender
),
x
->
mid
,
std
::
move
(
x
->
stages
),
std
::
move
(
tmp
)),
context
);
}
void
adapter
::
on_cleanup
()
{
decorated_
.
reset
();
merger_
.
reset
();
}
}
// namespace decorator
}
// namespace caf
libcaf_core/test/adapter.cpp
deleted
100644 → 0
View file @
bc9c2f75
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE adapter
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp"
using
namespace
caf
;
namespace
{
behavior
testee
(
event_based_actor
*
self
)
{
return
{
[](
int
v
)
{
return
2
*
v
;
},
[
=
]
{
self
->
quit
();
}
};
}
struct
fixture
{
template
<
class
Actor
>
static
bool
exited
(
const
Actor
&
handle
)
{
auto
ptr
=
actor_cast
<
abstract_actor
*>
(
handle
);
auto
dptr
=
dynamic_cast
<
monitorable_actor
*>
(
ptr
);
CAF_REQUIRE
(
dptr
!=
nullptr
);
return
dptr
->
getf
(
abstract_actor
::
is_terminated_flag
);
}
fixture
()
:
system
(
cfg
)
{
// nop
}
actor_system_config
cfg
;
actor_system
system
;
scoped_actor
self
{
system
,
true
};
};
void
handle_err
(
const
error
&
err
)
{
throw
std
::
runtime_error
(
"AUT responded with an error: "
+
to_string
(
err
));
}
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
adapter_tests
,
fixture
)
CAF_TEST
(
identity
)
{
auto
dbl
=
system
.
spawn
(
testee
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
auto
bound
=
dbl
.
bind
(
1
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
CAF_CHECK_EQUAL
(
&
bound
->
home_system
(),
&
dbl
->
home_system
());
CAF_CHECK_EQUAL
(
bound
->
node
(),
dbl
->
node
());
CAF_CHECK_NOT_EQUAL
(
bound
,
dbl
);
CAF_CHECK_NOT_EQUAL
(
bound
->
id
(),
dbl
->
id
());
//anon_send_exit(bound, exit_reason::kill);
anon_send_exit
(
dbl
,
exit_reason
::
kill
);
// killing dbl triggers a down message to bound, which becomes unreachable
// when it no longer monitors dbl as a result and goes out of scope here
}
// bound actor spawned dead if decorated
// actor is already dead upon spawning
CAF_TEST
(
lifetime_1
)
{
auto
dbl
=
system
.
spawn
(
testee
);
self
->
monitor
(
dbl
);
anon_send_exit
(
dbl
,
exit_reason
::
kill
);
self
->
wait_for
(
dbl
);
auto
bound
=
dbl
.
bind
(
1
);
CAF_CHECK
(
exited
(
bound
));
}
// bound actor exits when decorated actor exits
CAF_TEST
(
lifetime_2
)
{
auto
dbl
=
system
.
spawn
(
testee
);
auto
bound
=
dbl
.
bind
(
1
);
self
->
monitor
(
bound
);
anon_send
(
dbl
,
message
{});
self
->
wait_for
(
dbl
);
}
CAF_TEST
(
request_response_promise
)
{
auto
dbl
=
system
.
spawn
(
testee
);
auto
bound
=
dbl
.
bind
(
1
);
anon_send_exit
(
bound
,
exit_reason
::
kill
);
CAF_CHECK
(
exited
(
bound
));
self
->
request
(
bound
,
infinite
,
message
{}).
receive
(
[](
int
)
{
throw
std
::
runtime_error
(
"received unexpected integer"
);
},
[](
error
err
)
{
CAF_CHECK_EQUAL
(
err
.
code
(),
static_cast
<
uint8_t
>
(
sec
::
request_receiver_down
));
}
);
anon_send_exit
(
dbl
,
exit_reason
::
kill
);
}
CAF_TEST
(
partial_currying
)
{
using
namespace
std
::
placeholders
;
auto
impl
=
[]()
->
behavior
{
return
{
[](
ok_atom
,
int
x
)
{
return
x
;
},
[](
ok_atom
,
double
x
)
{
return
x
;
}
};
};
auto
aut
=
system
.
spawn
(
impl
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
auto
bound
=
aut
.
bind
(
ok_atom
::
value
,
_1
);
CAF_CHECK_NOT_EQUAL
(
aut
.
id
(),
bound
.
id
());
CAF_CHECK_NOT_EQUAL
(
aut
,
bound
);
CAF_CHECK_EQUAL
(
aut
.
node
(),
bound
.
node
());
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
self
->
request
(
bound
,
infinite
,
2.0
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
2.0
);
},
handle_err
);
self
->
request
(
bound
,
infinite
,
10
).
receive
(
[](
int
y
)
{
CAF_CHECK_EQUAL
(
y
,
10
);
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
CAF_TEST
(
full_currying
)
{
auto
dbl_actor
=
system
.
spawn
(
testee
);
auto
bound
=
dbl_actor
.
bind
(
1
);
self
->
request
(
bound
,
infinite
,
message
{}).
receive
(
[](
int
v
)
{
CAF_CHECK_EQUAL
(
v
,
2
);
},
handle_err
);
anon_send_exit
(
bound
,
exit_reason
::
kill
);
anon_send_exit
(
dbl_actor
,
exit_reason
::
kill
);
}
CAF_TEST
(
type_safe_currying
)
{
using
namespace
std
::
placeholders
;
using
testee
=
typed_actor
<
replies_to
<
ok_atom
,
int
>::
with
<
int
>
,
replies_to
<
ok_atom
,
double
>::
with
<
double
>>
;
auto
impl
=
[]()
->
testee
::
behavior_type
{
return
{
[](
ok_atom
,
int
x
)
{
return
x
;
},
[](
ok_atom
,
double
x
)
{
return
x
;
}
};
};
auto
aut
=
system
.
spawn
(
impl
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
using
curried_signature
=
typed_actor
<
replies_to
<
int
>::
with
<
int
>
,
replies_to
<
double
>::
with
<
double
>>
;
auto
bound
=
aut
.
bind
(
ok_atom
::
value
,
_1
);
CAF_CHECK_NOT_EQUAL
(
aut
.
address
(),
bound
.
address
());
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
static_assert
(
std
::
is_same
<
decltype
(
bound
),
curried_signature
>::
value
,
"bind returned wrong actor handle"
);
self
->
request
(
bound
,
infinite
,
2.0
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
2.0
);
},
handle_err
);
self
->
request
(
bound
,
infinite
,
10
).
receive
(
[](
int
y
)
{
CAF_CHECK_EQUAL
(
y
,
10
);
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
CAF_TEST
(
reordering
)
{
auto
impl
=
[]()
->
behavior
{
return
{
[](
int
x
,
double
y
)
{
return
x
*
y
;
}
};
};
auto
aut
=
system
.
spawn
(
impl
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
using
namespace
std
::
placeholders
;
auto
bound
=
aut
.
bind
(
_2
,
_1
);
CAF_CHECK_NOT_EQUAL
(
aut
,
bound
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
self
->
request
(
bound
,
infinite
,
2.0
,
10
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
20.0
);
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
CAF_TEST
(
type_safe_reordering
)
{
using
testee
=
typed_actor
<
replies_to
<
int
,
double
>::
with
<
double
>>
;
auto
impl
=
[]()
->
testee
::
behavior_type
{
return
{
[](
int
x
,
double
y
)
{
return
x
*
y
;
}
};
};
auto
aut
=
system
.
spawn
(
impl
);
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
using
namespace
std
::
placeholders
;
using
swapped_signature
=
typed_actor
<
replies_to
<
double
,
int
>::
with
<
double
>>
;
auto
bound
=
aut
.
bind
(
_2
,
_1
);
CAF_CHECK_NOT_EQUAL
(
aut
.
address
(),
bound
.
address
());
CAF_CHECK_EQUAL
(
system
.
registry
().
running
(),
1u
);
static_assert
(
std
::
is_same
<
decltype
(
bound
),
swapped_signature
>::
value
,
"bind returned wrong actor handle"
);
self
->
request
(
bound
,
infinite
,
2.0
,
10
).
receive
(
[](
double
y
)
{
CAF_CHECK_EQUAL
(
y
,
20.0
);
},
handle_err
);
self
->
send_exit
(
aut
,
exit_reason
::
kill
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/metaprogramming.cpp
View file @
b749cc1f
This diff is collapsed.
Click to expand it.
libcaf_core/test/splitter.cpp
View file @
b749cc1f
...
...
@@ -32,7 +32,8 @@ using namespace caf;
namespace
{
using
first_stage
=
typed_actor
<
replies_to
<
double
>::
with
<
double
,
double
>>
;
using
second_stage
=
typed_actor
<
replies_to
<
double
,
double
>::
with
<
double
>>
;
using
second_stage
=
typed_actor
<
replies_to
<
double
,
double
>::
with
<
double
>
,
replies_to
<
double
>::
with
<
double
>>
;
first_stage
::
behavior_type
typed_first_stage
()
{
return
[](
double
x
)
{
...
...
@@ -41,8 +42,13 @@ first_stage::behavior_type typed_first_stage() {
}
second_stage
::
behavior_type
typed_second_stage
()
{
return
[](
double
x
,
double
y
)
{
return
{
[](
double
x
,
double
y
)
{
return
x
*
y
;
},
[](
double
x
)
{
return
23.0
f
*
x
;
}
};
}
...
...
@@ -75,7 +81,7 @@ struct fixture {
using
namespace
std
::
placeholders
;
first
=
system
.
spawn
(
untyped_first_stage
);
second
=
system
.
spawn
(
untyped_second_stage
);
first_and_second
=
splice
(
first
,
second
.
bind
(
23.0
,
_1
)
);
first_and_second
=
splice
(
first
,
second
);
}
};
...
...
@@ -114,11 +120,12 @@ CAF_TEST(untyped_splicing) {
);
}
/*
CAF_TEST(typed_splicing) {
using namespace std::placeholders;
auto stage0 = system.spawn(typed_first_stage);
auto
stage
1
=
system
.
spawn
(
typed_second_stage
);
auto
stages
=
splice
(
stage0
,
stage
1
.
bind
(
23.0
,
_1
)
);
auto stage
2
= system.spawn(typed_second_stage);
auto stages = splice(stage0, stage
2
);
using expected_type = typed_actor<replies_to<double>
::with<double, double, double>>;
static_assert(std::is_same<decltype(stages), expected_type>::value,
...
...
@@ -131,8 +138,9 @@ CAF_TEST(typed_splicing) {
},
ERROR_HANDLER
);
// stage0 and stage
1
go out of scope, leaving only the references
// stage0 and stage
2
go out of scope, leaving only the references
// in stages, which will also go out of scope
}
*/
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/typed_spawn.cpp
View file @
b749cc1f
...
...
@@ -211,7 +211,7 @@ using string_actor = typed_actor<replies_to<string>::with<string>>;
string_actor
::
behavior_type
string_reverter
()
{
return
{
[](
string
&
str
)
{
[](
string
&
str
)
->
string
{
std
::
reverse
(
str
.
begin
(),
str
.
end
());
return
std
::
move
(
str
);
}
...
...
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