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
71c043cc
Commit
71c043cc
authored
Feb 24, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate to the new messaging API
parent
77569942
Changes
46
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
404 additions
and
299 deletions
+404
-299
CMakeLists.txt
CMakeLists.txt
+9
-45
examples/curl/curl_fuse.cpp
examples/curl/curl_fuse.cpp
+13
-11
examples/custom_type/custom_types_1.cpp
examples/custom_type/custom_types_1.cpp
+19
-9
examples/custom_type/custom_types_2.cpp
examples/custom_type/custom_types_2.cpp
+9
-5
examples/custom_type/custom_types_3.cpp
examples/custom_type/custom_types_3.cpp
+34
-33
examples/dynamic_behavior/dining_philosophers.cpp
examples/dynamic_behavior/dining_philosophers.cpp
+10
-8
examples/message_passing/fan_out_request.cpp
examples/message_passing/fan_out_request.cpp
+10
-6
examples/message_passing/fixed_stack.cpp
examples/message_passing/fixed_stack.cpp
+13
-11
examples/remoting/distributed_calculator.cpp
examples/remoting/distributed_calculator.cpp
+2
-1
examples/remoting/group_chat.cpp
examples/remoting/group_chat.cpp
+56
-55
examples/remoting/remote_spawn.cpp
examples/remoting/remote_spawn.cpp
+15
-10
examples/streaming/integer_stream.cpp
examples/streaming/integer_stream.cpp
+26
-12
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+1
-0
libcaf_core/caf/binary_deserializer.hpp
libcaf_core/caf/binary_deserializer.hpp
+1
-1
libcaf_core/caf/binary_serializer.hpp
libcaf_core/caf/binary_serializer.hpp
+1
-1
libcaf_core/caf/deserializer.hpp
libcaf_core/caf/deserializer.hpp
+1
-2
libcaf_core/caf/detail/append_hex.hpp
libcaf_core/caf/detail/append_hex.hpp
+4
-4
libcaf_core/caf/detail/make_meta_object.hpp
libcaf_core/caf/detail/make_meta_object.hpp
+5
-0
libcaf_core/caf/detail/message_builder_element.hpp
libcaf_core/caf/detail/message_builder_element.hpp
+1
-1
libcaf_core/caf/detail/message_data.hpp
libcaf_core/caf/detail/message_data.hpp
+1
-1
libcaf_core/caf/detail/meta_object.hpp
libcaf_core/caf/detail/meta_object.hpp
+4
-1
libcaf_core/caf/detail/serialized_size.hpp
libcaf_core/caf/detail/serialized_size.hpp
+1
-1
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+1
-1
libcaf_core/caf/detail/type_id_list_builder.hpp
libcaf_core/caf/detail/type_id_list_builder.hpp
+2
-1
libcaf_core/caf/intrusive_ptr.hpp
libcaf_core/caf/intrusive_ptr.hpp
+1
-1
libcaf_core/caf/message.hpp
libcaf_core/caf/message.hpp
+4
-3
libcaf_core/caf/message_builder.hpp
libcaf_core/caf/message_builder.hpp
+3
-2
libcaf_core/caf/serializer.hpp
libcaf_core/caf/serializer.hpp
+1
-1
libcaf_core/caf/type_id.hpp
libcaf_core/caf/type_id.hpp
+28
-1
libcaf_core/caf/type_id_list.hpp
libcaf_core/caf/type_id_list.hpp
+8
-5
libcaf_core/src/binary_deserializer.cpp
libcaf_core/src/binary_deserializer.cpp
+2
-8
libcaf_core/src/binary_serializer.cpp
libcaf_core/src/binary_serializer.cpp
+2
-4
libcaf_core/src/detail/append_hex.cpp
libcaf_core/src/detail/append_hex.cpp
+3
-3
libcaf_core/src/detail/append_percent_encoded.cpp
libcaf_core/src/detail/append_percent_encoded.cpp
+3
-2
libcaf_core/src/detail/meta_object.cpp
libcaf_core/src/detail/meta_object.cpp
+3
-2
libcaf_core/src/detail/serialized_size.cpp
libcaf_core/src/detail/serialized_size.cpp
+2
-5
libcaf_core/src/inbound_path.cpp
libcaf_core/src/inbound_path.cpp
+1
-1
libcaf_core/src/message.cpp
libcaf_core/src/message.cpp
+22
-3
libcaf_core/src/type_id_list.cpp
libcaf_core/src/type_id_list.cpp
+2
-2
libcaf_core/test/detail/meta_object.cpp
libcaf_core/test/detail/meta_object.cpp
+3
-3
libcaf_core/test/message.cpp
libcaf_core/test/message.cpp
+21
-2
manual/ConfiguringActorApplications.rst
manual/ConfiguringActorApplications.rst
+27
-20
manual/RemoteSpawn.rst
manual/RemoteSpawn.rst
+2
-1
manual/Streaming.rst
manual/Streaming.rst
+8
-4
manual/TypeInspection.rst
manual/TypeInspection.rst
+7
-6
tools/caf-vec.cpp
tools/caf-vec.cpp
+12
-0
No files found.
CMakeLists.txt
View file @
71c043cc
...
...
@@ -403,50 +403,29 @@ if(NOT APPLE AND NOT WIN32)
endif
()
# -fPIC generates warnings on MinGW and Cygwin plus extra setup steps needed on MinGW
if
(
MINGW
)
add_definitions
(
-D_WIN32_WINNT=0x0600
)
add_definitions
(
-DWIN32
)
add_definitions
(
-D_WIN32_WINNT=0x0600 -DWIN32
)
list
(
APPEND CAF_EXTRA_LDFLAGS -lws2_32 -liphlpapi -lpsapi
)
# build static to avoid runtime dependencies to GCC libraries
build_string
(
"EXTRA_FLAGS"
"-static"
)
add_compile_options
(
-static
)
elseif
(
CYGWIN
)
build_string
(
"EXTRA_FLAGS"
"-U__STRICT_ANSI__"
)
add_compile_options
(
-U__STRICT_ANSI__
)
endif
()
if
(
WIN32
)
list
(
APPEND CAF_EXTRA_LDFLAGS ws2_32 iphlpapi
)
endif
()
# iOS support
if
(
CAF_OSX_SYSROOT
)
set
(
CMAKE_OSX_SYSROOT
"
${
CAF_OSX_SYSROOT
}
"
)
endif
()
if
(
CAF_IOS_DEPLOYMENT_TARGET
)
if
(
CAF_OSX_SYSROOT STREQUAL
"iphonesimulator"
)
build_string
(
"EXTRA_FLAGS"
"-mios-simulator-version-min=
${
CAF_IOS_DEPLOYMENT_TARGET
}
"
)
add_compile_options
(
"-mios-simulator-version-min=
${
CAF_IOS_DEPLOYMENT_TARGET
}
"
)
else
()
build_string
(
"EXTRA_FLAGS"
"-miphoneos-version-min=
${
CAF_IOS_DEPLOYMENT_TARGET
}
"
)
add_compile_options
(
"-miphoneos-version-min=
${
CAF_IOS_DEPLOYMENT_TARGET
}
"
)
endif
()
endif
()
# check if the user provided CXXFLAGS, set defaults otherwise
if
(
NOT CMAKE_CXX_FLAGS
)
set
(
CMAKE_CXX_FLAGS
"-Wextra -Wall -pedantic
${
EXTRA_FLAGS
}
"
)
endif
()
if
(
NOT CMAKE_CXX_FLAGS_DEBUG
)
set
(
CMAKE_CXX_FLAGS_DEBUG
"-O0 -g"
)
endif
()
if
(
NOT CMAKE_CXX_FLAGS_MINSIZEREL
)
set
(
CMAKE_CXX_FLAGS_MINSIZEREL
"-Os"
)
endif
()
if
(
NOT CMAKE_CXX_FLAGS_RELEASE
)
set
(
CMAKE_CXX_FLAGS_RELEASE
"-O3 -DNDEBUG"
)
endif
()
if
(
NOT CMAKE_CXX_FLAGS_RELWITHDEBINFO
)
set
(
CMAKE_CXX_FLAGS_RELWITHDEBINFO
"-O2 -g -fno-omit-frame-pointer"
)
endif
()
# set build default build type to RelWithDebInfo if not set
if
(
NOT CMAKE_BUILD_TYPE
)
set
(
CMAKE_BUILD_TYPE RelWithDebInfo
)
endif
()
# needed by subprojects
if
(
DEFINED CMAKE_LD_LIBS
)
list
(
APPEND
${
CMAKE_LD_LIBS
}
)
...
...
@@ -616,17 +595,6 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CAFConfig.cmake"
"
${
CMAKE_CURRENT_BINARY_DIR
}
/CAFConfigVersion.cmake"
DESTINATION
"
${
INSTALL_CAF_CMAKEDIR
}
"
)
# -- Fetch branch name and SHA if available ------------------------------------
if
(
EXISTS
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/release.txt"
)
file
(
READ
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/release.txt"
CAF_RELEASE
)
string
(
REGEX REPLACE
"
\n
"
""
CAF_RELEASE
"
${
CAF_RELEASE
}
"
)
else
()
set
(
CAF_RELEASE
"
${
CAF_VERSION
}
"
)
endif
()
message
(
STATUS
"Set release version for all documentation to
${
CAF_RELEASE
}
."
)
# -- Setup for building manual and API documentation ---------------------------
if
(
NOT WIN32
)
...
...
@@ -661,11 +629,7 @@ invertYesNo(CAF_NO_EXCEPTIONS CAF_BUILD_WITH_EXCEPTIONS)
invertYesNo
(
CAF_NO_MEM_MANAGEMENT CAF_BUILD_MEM_MANAGEMENT
)
invertYesNo
(
CAF_NO_OPENSSL CAF_BUILD_OPENSSL
)
invertYesNo
(
CAF_NO_PYTHON CAF_BUILD_PYTHON
)
# collect all compiler flags
string
(
TOUPPER
"
${
CMAKE_BUILD_TYPE
}
"
UPPER_BUILD_TYPE
)
set
(
ALL_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
${
CMAKE_CXX_FLAGS_
${
UPPER_BUILD_TYPE
}}
"
)
set
(
ALL_LD_FLAGS
"
${
CMAKE_SHARED_LINKER_FLAGS
}
${
CAF_EXTRA_LDFLAGS
}
"
)
string
(
STRIP
"
${
ALL_LD_FLAGS
}
"
ALL_LD_FLAGS
)
get_property
(
all_cxx_flags DIRECTORY PROPERTY COMPILE_OPTIONS
)
# done
if
(
NOT CAF_NO_SUMMARY
)
message
(
STATUS
...
...
@@ -689,7 +653,7 @@ if(NOT CAF_NO_SUMMARY)
"
\n
Build Python:
${
CAF_BUILD_PYTHON
}
"
"
\n
"
"
\n
CXX:
${
CMAKE_CXX_COMPILER
}
"
"
\n
CXXFLAGS:
${
ALL_CXX_FLAGS
}
"
"
\n
CXXFLAGS:
${
all_cxx_flags
}
"
"
\n
LINKER_FLAGS (shared)
${
ALL_LD_FLAGS
}
"
"
\n
"
"
\n
Source directory:
${
CMAKE_CURRENT_SOURCE_DIR
}
"
...
...
examples/curl/curl_fuse.cpp
View file @
71c043cc
...
...
@@ -56,16 +56,22 @@ CAF_POP_WARNINGS
# pragma clang diagnostic ignored "-Wunused-const-variable"
#endif // __clang__
CAF_BEGIN_TYPE_ID_BLOCK
(
curl_fuse
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
curl_fuse
,
std
::
vector
<
char
>
)
CAF_ADD_ATOM
(
curl_fuse
,
read_atom
);
CAF_ADD_ATOM
(
curl_fuse
,
fail_atom
);
CAF_ADD_ATOM
(
curl_fuse
,
next_atom
);
CAF_ADD_ATOM
(
curl_fuse
,
reply_atom
);
CAF_ADD_ATOM
(
curl_fuse
,
finished_atom
);
CAF_END_TYPE_ID_BLOCK
(
curl_fuse
)
using
namespace
caf
;
using
buffer_type
=
std
::
vector
<
char
>
;
CAF_MSG_TYPE_ADD_ATOM
(
read_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
fail_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
next_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
reply_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
finished_atom
);
namespace
color
{
// UNIX terminal color codes
...
...
@@ -320,11 +326,7 @@ std::atomic<bool> shutdown_flag{false};
struct
config
:
actor_system_config
{
config
()
{
add_message_type
<
read_atom
>
(
"read_atom"
);
add_message_type
<
fail_atom
>
(
"fail_atom"
);
add_message_type
<
next_atom
>
(
"next_atom"
);
add_message_type
<
reply_atom
>
(
"reply_atom"
);
add_message_type
<
finished_atom
>
(
"finished_atom"
);
init_global_meta_objects
<
curl_fuse_type_ids
>
();
}
};
...
...
examples/custom_type/custom_types_1.cpp
View file @
71c043cc
...
...
@@ -11,6 +11,20 @@
#include "caf/all.hpp"
// --(rst-type-id-block-begin)--
struct
foo
;
struct
foo2
;
CAF_BEGIN_TYPE_ID_BLOCK
(
custom_types_1
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
custom_types_1
,
foo
)
CAF_ADD_TYPE_ID
(
custom_types_1
,
foo2
)
CAF_ADD_TYPE_ID
(
custom_types_1
,
std
::
pair
<
int32_t
CAF_PP_COMMA
int32_t
>
)
CAF_END_TYPE_ID_BLOCK
(
custom_types_1
)
// --(rst-type-id-block-end)--
using
std
::
cout
;
using
std
::
cerr
;
using
std
::
endl
;
...
...
@@ -18,19 +32,17 @@ using std::vector;
using
namespace
caf
;
namespace
{
// POD struct foo
// --(rst-foo-begin)--
struct
foo
{
std
::
vector
<
int
>
a
;
int
b
;
};
// foo needs to be serializable
template
<
class
Inspector
>
typename
Inspector
::
result_type
inspect
(
Inspector
&
f
,
foo
&
x
)
{
return
f
(
meta
::
type_name
(
"foo"
),
x
.
a
,
x
.
b
);
}
// --(rst-foo-end)--
// a pair of two ints
using
foo_pair
=
std
::
pair
<
int
,
int
>
;
...
...
@@ -72,14 +84,14 @@ void testee(event_based_actor* self, size_t remaining) {
);
}
// --(rst-config-begin)--
class
config
:
public
actor_system_config
{
public:
config
()
{
add_message_type
<
foo
>
(
"foo"
);
add_message_type
<
foo2
>
(
"foo2"
);
add_message_type
<
foo_pair
>
(
"foo_pair"
);
init_global_meta_objects
<
custom_types_1_type_ids
>
();
}
};
// --(rst-config-end)--
void
caf_main
(
actor_system
&
system
,
const
config
&
)
{
// two variables for testing serialization
...
...
@@ -118,6 +130,4 @@ void caf_main(actor_system& system, const config&) {
self
->
send
(
t
,
foo_pair2
{
3
,
4
});
}
}
// namespace
CAF_MAIN
()
examples/custom_type/custom_types_2.cpp
View file @
71c043cc
...
...
@@ -6,14 +6,20 @@
#include "caf/all.hpp"
class
foo
;
CAF_BEGIN_TYPE_ID_BLOCK
(
custom_types_2
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
custom_types_2
,
foo
)
CAF_END_TYPE_ID_BLOCK
(
custom_types_2
)
using
std
::
cout
;
using
std
::
endl
;
using
std
::
make_pair
;
using
namespace
caf
;
namespace
{
// a simple class using getter and setter member functions
class
foo
{
public:
...
...
@@ -61,7 +67,7 @@ behavior testee(event_based_actor* self) {
class
config
:
public
actor_system_config
{
public:
config
()
{
add_message_type
<
foo
>
(
"foo"
);
init_global_meta_objects
<
custom_types_2_type_ids
>
(
);
}
};
...
...
@@ -69,6 +75,4 @@ void caf_main(actor_system& system, const config&) {
anon_send
(
system
.
spawn
(
testee
),
foo
{
1
,
2
});
}
}
// namespace
CAF_MAIN
()
examples/custom_type/custom_types_3.cpp
View file @
71c043cc
// Showcases custom message types that cannot provide
// friend access to the inspect() function.
// Manual refs: 20-49, 76-103 (TypeInspection)
#include <utility>
#include <iostream>
#include <utility>
#include "caf/all.hpp"
class
foo
;
CAF_BEGIN_TYPE_ID_BLOCK
(
custom_types_3
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
custom_types_3
,
foo
)
CAF_END_TYPE_ID_BLOCK
(
custom_types_3
)
using
std
::
cout
;
using
std
::
endl
;
using
std
::
make_pair
;
using
namespace
caf
;
namespace
{
// identical to our second custom type example, but
// no friend access for `inspect`
// Identical to our second custom type example, but no friend access for
// `inspect`.
// --(rst-foo-begin)--
class
foo
{
public:
foo
(
int
a0
=
0
,
int
b0
=
0
)
:
a_
(
a0
),
b_
(
b0
)
{
...
...
@@ -47,19 +52,22 @@ private:
int
a_
;
int
b_
;
};
// --(rst-foo-end)--
// A lightweight scope guard implementation.
template
<
class
Fun
>
class
scope_guard
{
public:
scope_guard
(
Fun
f
)
:
fun_
(
std
::
move
(
f
)),
enabled_
(
true
)
{
}
scope_guard
(
Fun
f
)
:
fun_
(
std
::
move
(
f
)),
enabled_
(
true
)
{
}
scope_guard
(
scope_guard
&&
x
)
:
fun_
(
std
::
move
(
x
.
fun_
)),
enabled_
(
x
.
enabled_
)
{
x
.
enabled_
=
false
;
}
~
scope_guard
()
{
if
(
enabled_
)
fun_
();
if
(
enabled_
)
fun_
();
}
private:
...
...
@@ -73,17 +81,12 @@ scope_guard<Fun> make_scope_guard(Fun f) {
return
{
std
::
move
(
f
)};
}
// --(rst-inspect-begin)--
template
<
class
Inspector
>
typename
std
::
enable_if
<
Inspector
::
reads_state
,
typename
Inspector
::
result_type
>::
type
inspect
(
Inspector
&
f
,
foo
&
x
)
{
typename
Inspector
::
result_type
inspect
(
Inspector
&
f
,
foo
&
x
)
{
if
constexpr
(
Inspector
::
reads_state
)
{
return
f
(
meta
::
type_name
(
"foo"
),
x
.
a
(),
x
.
b
());
}
template
<
class
Inspector
>
typename
std
::
enable_if
<
Inspector
::
writes_state
,
typename
Inspector
::
result_type
>::
type
inspect
(
Inspector
&
f
,
foo
&
x
)
{
}
else
{
int
a
;
int
b
;
// write back to x at scope exit
...
...
@@ -92,20 +95,20 @@ inspect(Inspector& f, foo& x) {
x
.
set_b
(
b
);
});
return
f
(
meta
::
type_name
(
"foo"
),
a
,
b
);
}
}
// --(rst-inspect-end)--
behavior
testee
(
event_based_actor
*
self
)
{
return
{
[
=
](
const
foo
&
x
)
{
aout
(
self
)
<<
to_string
(
x
)
<<
endl
;
}
[
=
](
const
foo
&
x
)
{
aout
(
self
)
<<
to_string
(
x
)
<<
endl
;
},
};
}
class
config
:
public
actor_system_config
{
public:
config
()
{
add_message_type
<
foo
>
(
"foo"
);
init_global_meta_objects
<
custom_types_3_type_ids
>
(
);
}
};
...
...
@@ -113,6 +116,4 @@ void caf_main(actor_system& system, const config&) {
anon_send
(
system
.
spawn
(
testee
),
foo
{
1
,
2
});
}
}
// namespace
CAF_MAIN
()
examples/dynamic_behavior/dining_philosophers.cpp
View file @
71c043cc
...
...
@@ -13,6 +13,15 @@
#include "caf/all.hpp"
CAF_BEGIN_TYPE_ID_BLOCK
(
dining_philosophers
,
first_custom_type_id
)
CAF_ADD_ATOM
(
dining_philosophers
,
take_atom
);
CAF_ADD_ATOM
(
dining_philosophers
,
taken_atom
);
CAF_ADD_ATOM
(
dining_philosophers
,
eat_atom
);
CAF_ADD_ATOM
(
dining_philosophers
,
think_atom
);
CAF_END_TYPE_ID_BLOCK
(
dining_philosophers
)
using
std
::
cerr
;
using
std
::
cout
;
using
std
::
endl
;
...
...
@@ -23,10 +32,6 @@ using namespace caf;
namespace
{
// atoms for chopstick and philosopher interfaces
CAF_MSG_TYPE_ADD_ATOM
(
take_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
taken_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
eat_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
think_atom
);
// a chopstick
using
chopstick
=
typed_actor
<
replies_to
<
take_atom
>::
with
<
taken_atom
,
bool
>
,
...
...
@@ -172,10 +177,7 @@ private:
struct
config
:
actor_system_config
{
config
()
{
add_message_type
<
take_atom
>
(
"take_atom"
);
add_message_type
<
taken_atom
>
(
"taken_atom"
);
add_message_type
<
eat_atom
>
(
"eat_atom"
);
add_message_type
<
think_atom
>
(
"think_atom"
);
init_global_meta_objects
<
dining_philosophers_type_ids
>
();
}
};
...
...
examples/message_passing/fan_out_request.cpp
View file @
71c043cc
...
...
@@ -14,19 +14,25 @@
#include "caf/event_based_actor.hpp"
#include "caf/exec_main.hpp"
#include "caf/function_view.hpp"
#include "caf/init_global_meta_objects.hpp"
#include "caf/policy/select_all.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/stateful_actor.hpp"
#include "caf/typed_actor.hpp"
#include "caf/typed_event_based_actor.hpp"
CAF_BEGIN_TYPE_ID_BLOCK
(
fan_out_request
,
first_custom_type_id
)
CAF_ADD_ATOM
(
fan_out_request
,
row_atom
);
CAF_ADD_ATOM
(
fan_out_request
,
column_atom
);
CAF_ADD_ATOM
(
fan_out_request
,
average_atom
);
CAF_END_TYPE_ID_BLOCK
(
fan_out_request
)
using
std
::
endl
;
using
std
::
chrono
::
seconds
;
using
namespace
caf
;
CAF_MSG_TYPE_ADD_ATOM
(
row_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
column_atom
);
CAF_MSG_TYPE_ADD_ATOM
(
average_atom
);
/// A simple actor for storing an integer value.
using
cell
=
typed_actor
<
...
...
@@ -124,9 +130,7 @@ std::ostream& operator<<(std::ostream& out, const expected<int>& x) {
struct
config
:
actor_system_config
{
config
()
{
add_message_type
<
row_atom
>
(
"row_atom"
);
add_message_type
<
column_atom
>
(
"column_atom"
);
add_message_type
<
average_atom
>
(
"average_atom"
);
init_global_meta_objects
<
fan_out_request_type_ids
>
();
}
};
...
...
examples/message_passing/fixed_stack.cpp
View file @
71c043cc
...
...
@@ -3,21 +3,21 @@
#include <cstdint>
#include <iostream>
using
std
::
endl
;
using
namespace
caf
;
CAF_BEGIN_TYPE_ID_BLOCK
(
fixed_stack
,
first_custom_type_id
)
CAF_ADD_ATOM
(
fixed_stack
,
pop_atom
);
CAF_ADD_ATOM
(
fixed_stack
,
push_atom
);
namespace
{
CAF_END_TYPE_ID_BLOCK
(
fixed_stack
)
CAF_MSG_TYPE_ADD_ATOM
(
pop_atom
)
;
CAF_MSG_TYPE_ADD_ATOM
(
push_atom
)
;
using
std
::
endl
;
using
namespace
caf
;
enum
class
fixed_stack_errc
:
uint8_t
{
push_to_full
=
1
,
pop_from_empty
,
};
}
// namespace
namespace
caf
{
template
<
>
...
...
@@ -27,8 +27,6 @@ struct error_category<fixed_stack_errc> {
}
// namespace caf
namespace
{
class
fixed_stack
:
public
event_based_actor
{
public:
fixed_stack
(
actor_config
&
cfg
,
size_t
stack_size
)
...
...
@@ -75,6 +73,12 @@ private:
behavior
empty_
;
};
struct
config
:
actor_system_config
{
config
()
{
init_global_meta_objects
<
fixed_stack_type_ids
>
();
}
};
void
caf_main
(
actor_system
&
system
)
{
scoped_actor
self
{
system
};
auto
st
=
self
->
spawn
<
fixed_stack
>
(
5u
);
...
...
@@ -93,6 +97,4 @@ void caf_main(actor_system& system) {
self
->
send_exit
(
st
,
exit_reason
::
user_shutdown
);
}
}
// namespace
CAF_MAIN
()
examples/remoting/distributed_calculator.cpp
View file @
71c043cc
...
...
@@ -274,7 +274,8 @@ void client_repl(actor_system& system, const config& cfg) {
line
=
trim
(
std
::
move
(
line
));
// ignore leading and trailing whitespaces
std
::
vector
<
string
>
words
;
split
(
words
,
line
,
is_any_of
(
" "
),
token_compress_on
);
if
(
!
message_builder
(
words
.
begin
(),
words
.
end
()).
apply
(
eval
))
auto
msg
=
message_builder
(
words
.
begin
(),
words
.
end
()).
move_to_message
();
if
(
!
eval
(
msg
))
usage
();
}
}
...
...
examples/remoting/group_chat.cpp
View file @
71c043cc
...
...
@@ -20,46 +20,47 @@
#include "caf/string_algorithms.hpp"
using
namespace
std
;
using
namespace
caf
;
CAF_BEGIN_TYPE_ID_BLOCK
(
group_chat
,
first_custom_type_id
)
CAF_ADD_ATOM
(
group_chat
,
broadcast_atom
);
namespace
{
CAF_END_TYPE_ID_BLOCK
(
group_chat
)
CAF_MSG_TYPE_ADD_ATOM
(
broadcast_atom
)
;
using
namespace
caf
;
struct
line
{
string
str
;
st
d
::
st
ring
str
;
};
istream
&
operator
>>
(
istream
&
is
,
line
&
l
)
{
getline
(
is
,
l
.
str
);
std
::
istream
&
operator
>>
(
std
::
istream
&
is
,
line
&
l
)
{
std
::
getline
(
is
,
l
.
str
);
return
is
;
}
behavior
client
(
event_based_actor
*
self
,
const
string
&
name
)
{
behavior
client
(
event_based_actor
*
self
,
const
st
d
::
st
ring
&
name
)
{
return
{
[
=
](
broadcast_atom
,
const
string
&
message
)
{
[
=
](
broadcast_atom
,
const
st
d
::
st
ring
&
message
)
{
for
(
auto
&
dest
:
self
->
joined_groups
())
{
self
->
send
(
dest
,
name
+
": "
+
message
);
}
},
[
=
](
join_atom
,
const
group
&
what
)
{
for
(
const
auto
&
g
:
self
->
joined_groups
())
{
cout
<<
"*** leave "
<<
to_string
(
g
)
<<
endl
;
std
::
cout
<<
"*** leave "
<<
to_string
(
g
)
<<
std
::
endl
;
self
->
send
(
g
,
name
+
" has left the chatroom"
);
self
->
leave
(
g
);
}
cout
<<
"*** join "
<<
to_string
(
what
)
<<
endl
;
std
::
cout
<<
"*** join "
<<
to_string
(
what
)
<<
std
::
endl
;
self
->
join
(
what
);
self
->
send
(
what
,
name
+
" has entered the chatroom"
);
},
[
=
](
const
string
&
txt
)
{
[
=
](
const
st
d
::
st
ring
&
txt
)
{
// don't print own messages
if
(
self
->
current_sender
()
!=
self
)
cout
<<
txt
<<
endl
;
std
::
cout
<<
txt
<<
std
::
endl
;
},
[
=
](
const
group_down_msg
&
g
)
{
cout
<<
"*** chatroom offline: "
<<
to_string
(
g
.
source
)
<<
endl
;
std
::
cout
<<
"*** chatroom offline: "
<<
to_string
(
g
.
source
)
<<
std
::
endl
;
},
};
}
...
...
@@ -72,6 +73,7 @@ public:
bool
server_mode
=
false
;
config
()
{
init_global_meta_objects
<
group_chat_type_ids
>
();
opt_group
{
custom_options_
,
"global"
}
.
add
(
name
,
"name,n"
,
"set name"
)
.
add
(
group_uris
,
"group,g"
,
"join group"
)
...
...
@@ -84,48 +86,47 @@ void run_server(actor_system& system, const config& cfg) {
auto
res
=
system
.
middleman
().
publish_local_groups
(
cfg
.
port
);
if
(
!
res
)
{
std
::
cerr
<<
"*** publishing local groups failed: "
<<
system
.
render
(
res
.
error
())
<<
endl
;
<<
system
.
render
(
res
.
error
())
<<
std
::
endl
;
return
;
}
cout
<<
"*** listening at port "
<<
*
res
<<
endl
<<
"*** press [enter] to quit"
<<
endl
;
string
dummy
;
std
::
cout
<<
"*** listening at port "
<<
*
res
<<
std
::
endl
<<
"*** press [enter] to quit"
<<
std
::
endl
;
st
d
::
st
ring
dummy
;
std
::
getline
(
std
::
cin
,
dummy
);
cout
<<
"... cya"
<<
endl
;
std
::
cout
<<
"... cya"
<<
std
::
endl
;
}
void
run_client
(
actor_system
&
system
,
const
config
&
cfg
)
{
auto
name
=
cfg
.
name
;
while
(
name
.
empty
())
{
cout
<<
"please enter your name: "
<<
flush
;
if
(
!
getline
(
cin
,
name
))
{
cerr
<<
"*** no name given... terminating"
<<
endl
;
std
::
cout
<<
"please enter your name: "
<<
std
::
flush
;
if
(
!
std
::
getline
(
std
::
cin
,
name
))
{
std
::
cerr
<<
"*** no name given... terminating"
<<
std
::
endl
;
return
;
}
}
cout
<<
"*** starting client, type '/help' for a list of commands"
<<
endl
;
std
::
cout
<<
"*** starting client, type '/help' for a list of commands
\n
"
;
auto
client_actor
=
system
.
spawn
(
client
,
name
);
for
(
auto
&
uri
:
cfg
.
group_uris
)
{
auto
tmp
=
system
.
groups
().
get
(
uri
);
if
(
tmp
)
anon_send
(
client_actor
,
join_atom_v
,
std
::
move
(
*
tmp
));
else
cerr
<<
R"(*** failed to parse ")"
<<
uri
<<
R"(" as group URI: )"
<<
system
.
render
(
tmp
.
error
())
<<
endl
;
std
::
cerr
<<
R"(*** failed to parse ")"
<<
uri
<<
R"(" as group URI: )"
<<
system
.
render
(
tmp
.
error
())
<<
std
::
endl
;
}
istream_iterator
<
line
>
eof
;
vector
<
string
>
words
;
for
(
istream_iterator
<
line
>
i
(
cin
)
;
i
!=
eof
;
++
i
)
{
std
::
istream_iterator
<
line
>
eof
;
std
::
vector
<
std
::
string
>
words
;
for
(
std
::
istream_iterator
<
line
>
i
{
std
::
cin
}
;
i
!=
eof
;
++
i
)
{
auto
send_input
=
[
&
]
{
if
(
!
i
->
str
.
empty
())
anon_send
(
client_actor
,
broadcast_atom_v
,
i
->
str
);
};
words
.
clear
();
split
(
words
,
i
->
str
,
is_any_of
(
" "
));
auto
res
=
message_builder
(
words
.
begin
(),
words
.
end
())
.
apply
(
{[
&
](
const
string
&
cmd
,
const
string
&
mod
,
const
string
&
id
)
{
message_handler
f
{
[
&
](
const
std
::
string
&
cmd
,
const
std
::
string
&
mod
,
const
std
::
string
&
id
)
{
if
(
cmd
==
"/join"
)
{
auto
grp
=
system
.
groups
().
get
(
mod
,
id
);
if
(
grp
)
...
...
@@ -134,19 +135,21 @@ void run_client(actor_system& system, const config& cfg) {
send_input
();
}
},
[
&
](
const
string
&
cmd
)
{
[
&
](
const
std
::
string
&
cmd
)
{
if
(
cmd
==
"/quit"
)
{
cin
.
setstate
(
ios_base
::
eofbit
);
std
::
cin
.
setstate
(
std
::
ios_base
::
eofbit
);
}
else
if
(
cmd
[
0
]
==
'/'
)
{
cout
<<
"*** available commands:
\n
"
std
::
cout
<<
"*** available commands:
\n
"
" /join <module> <group> join a new chat channel
\n
"
" /quit quit the program
\n
"
" /help print this text
\n
"
<<
flush
;
" /help print this text
\n
"
;
}
else
{
send_input
();
}
}});
},
};
auto
msg
=
message_builder
(
words
.
begin
(),
words
.
end
()).
move_to_message
();
auto
res
=
f
(
msg
);
if
(
!
res
)
send_input
();
}
...
...
@@ -159,6 +162,4 @@ void caf_main(actor_system& system, const config& cfg) {
f
(
system
,
cfg
);
}
}
// namespace
CAF_MAIN
(
io
::
middleman
)
examples/remoting/remote_spawn.cpp
View file @
71c043cc
...
...
@@ -7,9 +7,6 @@
// Run client at the same host:
// - remote_spawn -H localhost -p 4242
// Manual refs: 33-34, 98-109 (ConfiguringActorApplications)
// 123-137 (RemoteSpawn)
#include <array>
#include <cassert>
#include <functional>
...
...
@@ -21,6 +18,18 @@
#include "caf/all.hpp"
#include "caf/io/all.hpp"
// --(rst-calculator-begin)--
using
calculator
=
caf
::
typed_actor
<
caf
::
replies_to
<
caf
::
add_atom
,
int
,
int
>::
with
<
int
>
,
caf
::
replies_to
<
caf
::
sub_atom
,
int
,
int
>::
with
<
int
>>
;
// --(rst-calculator-end)--
CAF_BEGIN_TYPE_ID_BLOCK
(
remote_spawn
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
remote_spawn
,
calculator
)
CAF_END_TYPE_ID_BLOCK
(
remote_spawn
)
using
std
::
cerr
;
using
std
::
cout
;
using
std
::
endl
;
...
...
@@ -28,11 +37,6 @@ using std::string;
using
namespace
caf
;
namespace
{
using
calculator
=
typed_actor
<
replies_to
<
add_atom
,
int
,
int
>::
with
<
int
>
,
replies_to
<
sub_atom
,
int
,
int
>::
with
<
int
>>
;
calculator
::
behavior_type
calculator_fun
(
calculator
::
pointer
self
)
{
return
{
[
=
](
add_atom
,
int
a
,
int
b
)
->
int
{
...
...
@@ -98,6 +102,7 @@ void client_repl(function_view<calculator> f) {
struct
config
:
actor_system_config
{
config
()
{
add_actor_type
(
"calculator"
,
calculator_fun
);
init_global_meta_objects
<
remote_spawn_type_ids
>
();
opt_group
{
custom_options_
,
"global"
}
.
add
(
port
,
"port,p"
,
"set port"
)
.
add
(
host
,
"host,H"
,
"set node (ignored in server mode)"
)
...
...
@@ -119,6 +124,7 @@ void server(actor_system& system, const config& cfg) {
getchar
();
}
// --(rst-client-begin)--
void
client
(
actor_system
&
system
,
const
config
&
cfg
)
{
auto
node
=
system
.
middleman
().
connect
(
cfg
.
host
,
cfg
.
port
);
if
(
!
node
)
{
...
...
@@ -140,12 +146,11 @@ void client(actor_system& system, const config& cfg) {
// be a good citizen and terminate remotely spawned actor before exiting
anon_send_exit
(
*
worker
,
exit_reason
::
kill
);
}
// --(rst-client-end)--
void
caf_main
(
actor_system
&
system
,
const
config
&
cfg
)
{
auto
f
=
cfg
.
server_mode
?
server
:
client
;
f
(
system
,
cfg
);
}
}
// namespace
CAF_MAIN
(
io
::
middleman
)
examples/streaming/integer_stream.cpp
View file @
71c043cc
...
...
@@ -2,22 +2,28 @@
* Basic, non-interactive streaming example for processing integers. *
******************************************************************************/
// Manual refs: lines 17-48, 50-83, 85-114, 128-132 (Streaming)
#include <iostream>
#include <vector>
#include "caf/all.hpp"
CAF_BEGIN_TYPE_ID_BLOCK
(
integer_stream
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
integer_stream
,
caf
::
stream
<
int32_t
>
)
CAF_ADD_TYPE_ID
(
integer_stream
,
std
::
vector
<
int32_t
>
)
CAF_END_TYPE_ID_BLOCK
(
integer_stream
)
using
std
::
endl
;
using
namespace
caf
;
namespace
{
// --(rst-source-begin)--
// Simple source for generating a stream of integers from [0, n).
behavior
int_source
(
event_based_actor
*
self
)
{
return
{
[
=
](
open_atom
,
int
n
)
{
[
=
](
open_atom
,
int
32_t
n
)
{
// Produce at least one value.
if
(
n
<=
0
)
n
=
1
;
...
...
@@ -28,7 +34,7 @@ behavior int_source(event_based_actor* self) {
self
,
// Initializer. The type of the first argument (state) is freely
// chosen. If no state is required, `caf::unit_t` can be used here.
[](
int
&
x
)
{
x
=
0
;
},
[](
int
32_t
&
x
)
{
x
=
0
;
},
// Generator. This function is called by CAF to produce new stream
// elements for downstream actors. The `x` argument is our state again
// (with our freely chosen type). The second argument `out` points to
...
...
@@ -36,21 +42,23 @@ behavior int_source(event_based_actor* self) {
// elements downstream actors receive in this stream. Finally, `num` is
// a hint from CAF how many elements we should ideally insert into
// `out`. We can always insert fewer or more items.
[
n
](
int
&
x
,
downstream
<
in
t
>&
out
,
size_t
num
)
{
[
n
](
int
32_t
&
x
,
downstream
<
int32_
t
>&
out
,
size_t
num
)
{
auto
max_x
=
std
::
min
(
x
+
static_cast
<
int
>
(
num
),
n
);
for
(;
x
<
max_x
;
++
x
)
out
.
push
(
x
);
},
// Predicate. This function tells CAF when we reached the end.
[
n
](
const
int
&
x
)
{
return
x
==
n
;
});
[
n
](
const
int
32_t
&
x
)
{
return
x
==
n
;
});
},
};
}
// --(rst-source-end)--
// --(rst-stage-begin)--
// Simple stage that only selects even numbers.
behavior
int_selector
(
event_based_actor
*
self
)
{
return
{
[
=
](
stream
<
int
>
in
)
{
[
=
](
stream
<
int
32_t
>
in
)
{
// Create a stream manager for implementing a stream stage. Similar to
// `make_source`, we need three functions: initialzer, processor, and
// finalizer.
...
...
@@ -64,7 +72,7 @@ behavior int_selector(event_based_actor* self) {
},
// Processor. This function takes individual input elements as `val`
// and forwards even integers to `out`.
[](
unit_t
&
,
downstream
<
int
>&
out
,
in
t
val
)
{
[](
unit_t
&
,
downstream
<
int
32_t
>&
out
,
int32_
t
val
)
{
if
(
val
%
2
==
0
)
out
.
push
(
val
);
},
...
...
@@ -81,10 +89,12 @@ behavior int_selector(event_based_actor* self) {
},
};
}
// --(rst-stage-end)--
// --(rst-sink-begin)--
behavior
int_sink
(
event_based_actor
*
self
)
{
return
{
[
=
](
stream
<
int
>
in
)
{
[
=
](
stream
<
int
32_t
>
in
)
{
// Create a stream manager for implementing a stream sink. Once more, we
// have to provide three functions: Initializer, Consumer, Finalizer.
return
attach_stream_sink
(
...
...
@@ -99,9 +109,9 @@ behavior int_sink(event_based_actor* self) {
},
// Consumer. Takes individual input elements as `val` and stores them
// in our history.
[](
std
::
vector
<
int
>&
xs
,
in
t
val
)
{
xs
.
emplace_back
(
val
);
},
[](
std
::
vector
<
int
32_t
>&
xs
,
int32_
t
val
)
{
xs
.
emplace_back
(
val
);
},
// Finalizer. Allows us to run cleanup code once the stream terminates.
[
=
](
std
::
vector
<
int
>&
xs
,
const
error
&
err
)
{
[
=
](
std
::
vector
<
int
32_t
>&
xs
,
const
error
&
err
)
{
if
(
err
)
{
aout
(
self
)
<<
"int_sink aborted with error: "
<<
err
<<
std
::
endl
;
}
else
{
...
...
@@ -112,18 +122,21 @@ behavior int_sink(event_based_actor* self) {
},
};
}
// --(rst-sink-end)--
struct
config
:
actor_system_config
{
config
()
{
init_global_meta_objects
<
integer_stream_type_ids
>
();
opt_group
{
custom_options_
,
"global"
}
.
add
(
with_stage
,
"with-stage,s"
,
"use a stage for filtering odd numbers"
)
.
add
(
n
,
"num-values,n"
,
"number of values produced by the source"
);
}
bool
with_stage
=
false
;
int
n
=
100
;
int
32_t
n
=
100
;
};
// --(rst-main-begin)--
void
caf_main
(
actor_system
&
sys
,
const
config
&
cfg
)
{
auto
src
=
sys
.
spawn
(
int_source
);
auto
snk
=
sys
.
spawn
(
int_sink
);
...
...
@@ -131,6 +144,7 @@ void caf_main(actor_system& sys, const config& cfg) {
:
snk
*
src
;
anon_send
(
pipeline
,
open_atom_v
,
cfg
.
n
);
}
// --(rst-main-end)--
}
// namespace
...
...
libcaf_core/CMakeLists.txt
View file @
71c043cc
...
...
@@ -69,6 +69,7 @@ set(CAF_CORE_SOURCES
src/detail/get_root_uuid.cpp
src/detail/ini_consumer.cpp
src/detail/invoke_result_visitor.cpp
src/detail/message_builder_element.cpp
src/detail/message_data.cpp
src/detail/meta_object.cpp
src/detail/parse.cpp
...
...
libcaf_core/caf/binary_deserializer.hpp
View file @
71c043cc
...
...
@@ -104,7 +104,7 @@ public:
// -- overridden member functions --------------------------------------------
result_type
begin_object
(
uint16_t
&
typenr
,
std
::
string
&
nam
e
);
result_type
begin_object
(
type_id_t
&
typ
e
);
result_type
end_object
()
noexcept
;
...
...
libcaf_core/caf/binary_serializer.hpp
View file @
71c043cc
...
...
@@ -95,7 +95,7 @@ public:
// -- interface functions ----------------------------------------------------
error_code
<
sec
>
begin_object
(
uint16_t
nr
,
string_view
nam
e
);
error_code
<
sec
>
begin_object
(
type_id_t
typ
e
);
error_code
<
sec
>
end_object
();
...
...
libcaf_core/caf/deserializer.hpp
View file @
71c043cc
...
...
@@ -57,8 +57,7 @@ public:
// -- interface functions ----------------------------------------------------
/// Begins processing of an object.
virtual
result_type
begin_object
(
uint16_t
&
typenr
,
std
::
string
&
type_name
)
=
0
;
virtual
result_type
begin_object
(
type_id_t
&
type
)
=
0
;
/// Ends processing of an object.
virtual
result_type
end_object
()
=
0
;
...
...
libcaf_core/caf/detail/append_hex.hpp
View file @
71c043cc
...
...
@@ -21,25 +21,25 @@
#include <string>
#include <type_traits>
#include "caf/byte.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/type_traits.hpp"
namespace
caf
::
detail
{
CAF_CORE_EXPORT
void
append_hex
(
std
::
string
&
result
,
const
uint8_t
*
xs
,
size_t
n
);
append_hex
(
std
::
string
&
result
,
const
byte
*
xs
,
size_t
n
);
template
<
class
T
>
enable_if_t
<
has_data_member
<
T
>::
value
>
append_hex
(
std
::
string
&
result
,
const
T
&
x
)
{
return
append_hex
(
result
,
reinterpret_cast
<
const
uint8_t
*>
(
x
.
data
()),
x
.
size
());
return
append_hex
(
result
,
reinterpret_cast
<
const
byte
*>
(
x
.
data
()),
x
.
size
());
}
template
<
class
T
>
enable_if_t
<
std
::
is_integral
<
T
>::
value
>
append_hex
(
std
::
string
&
result
,
const
T
&
x
)
{
return
append_hex
(
result
,
reinterpret_cast
<
const
uint8_t
*>
(
&
x
),
sizeof
(
T
));
return
append_hex
(
result
,
reinterpret_cast
<
const
byte
*>
(
&
x
),
sizeof
(
T
));
}
}
// namespace caf::detail
libcaf_core/caf/detail/make_meta_object.hpp
View file @
71c043cc
...
...
@@ -27,6 +27,7 @@
#include "caf/deserializer.hpp"
#include "caf/detail/meta_object.hpp"
#include "caf/detail/padded_size.hpp"
#include "caf/detail/stringification_inspector.hpp"
#include "caf/error.hpp"
#include "caf/serializer.hpp"
...
...
@@ -54,6 +55,10 @@ meta_object make_meta_object(const char* type_name) {
[](
caf
::
deserializer
&
source
,
void
*
ptr
)
{
return
source
(
*
reinterpret_cast
<
T
*>
(
ptr
));
},
[](
std
::
string
&
buf
,
const
void
*
ptr
)
{
stringification_inspector
f
{
buf
};
f
(
*
reinterpret_cast
<
const
T
*>
(
ptr
));
},
};
}
...
...
libcaf_core/caf/detail/message_builder_element.hpp
View file @
71c043cc
...
...
@@ -31,7 +31,7 @@ namespace caf::detail {
/// later.
class
CAF_CORE_EXPORT
message_builder_element
{
public:
virtual
~
message_builder_element
()
noexcept
;
virtual
~
message_builder_element
();
/// Uses placement new to create a copy of the wrapped value at given memory
/// region.
...
...
libcaf_core/caf/detail/message_data.hpp
View file @
71c043cc
...
...
@@ -147,7 +147,7 @@ void message_data_init(byte* storage, T&& x, Ts&&... xs) {
// TODO: exception safety: if any constructor throws, we need to unwind the
// stack here and call destructors.
using
type
=
strip_and_convert_t
<
T
>
;
new
(
storage
)
strip_and_convert_t
<
T
>
(
std
::
forward
<
T
>
(
x
));
new
(
storage
)
type
(
std
::
forward
<
T
>
(
x
));
message_data_init
(
storage
+
padded_size_v
<
type
>
,
std
::
forward
<
Ts
>
(
xs
)...);
}
...
...
libcaf_core/caf/detail/meta_object.hpp
View file @
71c043cc
...
...
@@ -58,6 +58,9 @@ struct meta_object {
/// Applies an object to a generic deserializer.
caf
::
error
(
*
load
)(
caf
::
deserializer
&
,
void
*
);
/// Appends a string representation of an object to a buffer.
void
(
*
stringify
)(
std
::
string
&
,
const
void
*
);
};
/// Convenience function for calling `meta.save(sink, obj)`.
...
...
@@ -81,7 +84,7 @@ load(const meta_object& meta, caf::binary_deserializer& source, void* obj);
CAF_CORE_EXPORT
span
<
const
meta_object
>
global_meta_objects
();
/// Returns the global meta object for given type ID.
CAF_CORE_EXPORT
meta_object
&
global_meta_object
(
type_id_t
id
);
CAF_CORE_EXPORT
const
meta_object
*
global_meta_object
(
type_id_t
id
);
/// Clears the array for storing global meta objects.
/// @warning intended for unit testing only!
...
...
libcaf_core/caf/detail/serialized_size.hpp
View file @
71c043cc
...
...
@@ -33,7 +33,7 @@ public:
return
result_
;
}
result_type
begin_object
(
uint16_t
typenr
,
string_view
type_name
)
override
;
result_type
begin_object
(
type_id_t
)
override
;
result_type
end_object
()
override
;
...
...
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
71c043cc
...
...
@@ -60,7 +60,7 @@ public:
// -- serializer interface ---------------------------------------------------
void
begin_object
(
uint16_t
,
string_view
)
{
void
begin_object
(
type_id_t
)
{
// nop
}
...
...
libcaf_core/caf/detail/type_id_list_builder.hpp
View file @
71c043cc
...
...
@@ -20,12 +20,13 @@
#include <cstdlib>
#include "caf/detail/core_export.hpp"
#include "caf/fwd.hpp"
#include "caf/type_id.hpp"
namespace
caf
::
detail
{
class
type_id_list_builder
{
class
CAF_CORE_EXPORT
type_id_list_builder
{
public:
static
constexpr
size_t
block_size
=
8
;
...
...
libcaf_core/caf/intrusive_ptr.hpp
View file @
71c043cc
...
...
@@ -268,7 +268,7 @@ template <class T>
std
::
string
to_string
(
const
intrusive_ptr
<
T
>&
x
)
{
std
::
string
result
;
auto
v
=
reinterpret_cast
<
uintptr_t
>
(
x
.
get
());
detail
::
append_hex
(
result
,
reinterpret_cast
<
uint8_t
*>
(
&
v
),
sizeof
(
v
));
detail
::
append_hex
(
result
,
reinterpret_cast
<
byte
*>
(
&
v
),
sizeof
(
v
));
return
result
;
}
...
...
libcaf_core/caf/message.hpp
View file @
71c043cc
...
...
@@ -182,14 +182,15 @@ template <class... Ts>
message
make_message
(
Ts
&&
...
xs
)
{
using
namespace
detail
;
static_assert
((
!
std
::
is_pointer
<
strip_and_convert_t
<
Ts
>>::
value
&&
...));
static
constexpr
size_t
data_size
=
sizeof
(
message_data
)
+
(
padded_size_v
<
std
::
decay_t
<
Ts
>>
+
...);
static_assert
((
is_complete
<
type_id
<
strip_and_convert_t
<
Ts
>>>
&&
...));
static
constexpr
size_t
data_size
=
sizeof
(
message_data
)
+
(
padded_size_v
<
strip_and_convert_t
<
Ts
>>
+
...);
auto
types
=
make_type_id_list
<
strip_and_convert_t
<
Ts
>
...
>
();
auto
vptr
=
malloc
(
data_size
);
if
(
vptr
==
nullptr
)
throw
std
::
bad_alloc
();
auto
raw_ptr
=
new
(
vptr
)
message_data
(
types
);
intrusive_cow_ptr
<
message_data
>
ptr
{};
intrusive_cow_ptr
<
message_data
>
ptr
{
raw_ptr
,
false
};
message_data_init
(
raw_ptr
->
storage
(),
std
::
forward
<
Ts
>
(
xs
)...);
return
message
{
std
::
move
(
ptr
)};
}
...
...
libcaf_core/caf/message_builder.hpp
View file @
71c043cc
...
...
@@ -58,8 +58,9 @@ public:
/// Adds `x` to the elements of the buffer.
template
<
class
T
>
message_builder
&
append
(
T
&&
x
)
{
using
value_type
=
detail
::
strip_and_convert
<
T
>
;
static_assert
(
detail
::
sendable
<
value_type
>
);
using
namespace
detail
;
using
value_type
=
strip_and_convert_t
<
T
>
;
static_assert
(
sendable
<
value_type
>
);
types_
.
push_back
(
type_id_v
<
value_type
>
);
elements_
.
emplace_back
(
make_message_builder_element
(
std
::
forward
<
T
>
(
x
)));
return
*
this
;
...
...
libcaf_core/caf/serializer.hpp
View file @
71c043cc
...
...
@@ -62,7 +62,7 @@ public:
/// Begins processing of an object. Saves the type information
/// to the underlying storage.
virtual
result_type
begin_object
(
uint16_t
typenr
,
string_view
type_nam
e
)
=
0
;
virtual
result_type
begin_object
(
type_id_t
typ
e
)
=
0
;
/// Ends processing of an object.
virtual
result_type
end_object
()
=
0
;
...
...
libcaf_core/caf/type_id.hpp
View file @
71c043cc
...
...
@@ -24,6 +24,7 @@
#include <utility>
#include "caf/detail/core_export.hpp"
#include "caf/detail/pp.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp"
#include "caf/meta/type_name.hpp"
...
...
@@ -120,8 +121,25 @@ constexpr type_id_t first_custom_type_id = 200;
: type_name<fully_qualified_name> {}; \
}
/// Creates a new tag type (atom) in the global namespace and assigns the next
/// free type ID to it.
#define CAF_ADD_ATOM_2(project_name, atom_name) \
struct atom_name {}; \
static constexpr atom_name atom_name##_v = atom_name{}; \
[[maybe_unused]] constexpr bool operator==(atom_name, atom_name) { \
return true; \
} \
[[maybe_unused]] constexpr bool operator!=(atom_name, atom_name) { \
return false; \
} \
template <class Inspector> \
auto inspect(Inspector& f, atom_name&) { \
return f(caf::meta::type_name(#atom_name)); \
} \
CAF_ADD_TYPE_ID(project_name, atom_name)
/// Creates a new tag type (atom) and assigns the next free type ID to it.
#define CAF_ADD_ATOM
(project_name, atom_namespace, atom_name)
\
#define CAF_ADD_ATOM
_3(project_name, atom_namespace, atom_name)
\
namespace atom_namespace { \
struct atom_name {}; \
static constexpr atom_name atom_name##_v = atom_name{}; \
...
...
@@ -138,6 +156,15 @@ constexpr type_id_t first_custom_type_id = 200;
} \
CAF_ADD_TYPE_ID(project_name, atom_namespace ::atom_name)
#ifdef CAF_MSVC
# define CAF_ADD_ATOM(...) \
CAF_PP_CAT(CAF_PP_OVERLOAD(CAF_ADD_ATOM_, __VA_ARGS__)(__VA_ARGS__), \
CAF_PP_EMPTY())
#else
# define CAF_ADD_ATOM(...) \
CAF_PP_OVERLOAD(CAF_ADD_ATOM_, __VA_ARGS__)(__VA_ARGS__)
#endif
/// Finalizes a code block for registering custom types to CAF. Stores the last
/// type ID used by the project as `caf::${project_name}_last_type_id`.
#define CAF_END_TYPE_ID_BLOCK(project_name) \
...
...
libcaf_core/caf/type_id_list.hpp
View file @
71c043cc
...
...
@@ -53,13 +53,16 @@ public:
}
/// Returns the number of elements in the list.
/// @pre `data() != nullptr`
constexpr
size_t
size
()
const
noexcept
{
return
data_
[
0
];
}
/// Returns `size() == 0`.
constexpr
bool
empty
()
const
noexcept
{
return
size
()
==
0
;
}
/// Returns the type ID at `index`.
/// @pre `data() != nullptr`
constexpr
type_id_t
operator
[](
size_t
index
)
const
noexcept
{
return
data_
[
index
+
1
];
}
...
...
@@ -86,14 +89,14 @@ private:
/// @private
template
<
class
...
Ts
>
struct
make_type_id_list_helper
{
static
constexpr
inline
type_id_t
data
[]
=
{
static_cast
<
type_id_t
>
(
sizeof
...(
Ts
)),
type_id_v
<
Ts
>
...};
static
inline
type_id_t
data
[]
=
{
static_cast
<
type_id_t
>
(
sizeof
...(
Ts
)),
type_id_v
<
Ts
>
...};
};
/// Constructs a ::type_id_list from the template parameter pack `Ts`.
/// @relates type_id_list
template
<
class
...
Ts
>
constexpr
type_id_list
make_type_id_list
()
{
type_id_list
make_type_id_list
()
{
return
type_id_list
{
make_type_id_list_helper
<
Ts
...
>::
data
};
}
...
...
libcaf_core/src/binary_deserializer.cpp
View file @
71c043cc
...
...
@@ -68,14 +68,8 @@ binary_deserializer::binary_deserializer(actor_system& sys) noexcept
// nop
}
result_type
binary_deserializer
::
begin_object
(
uint16_t
&
nr
,
std
::
string
&
name
)
{
name
.
clear
();
if
(
auto
err
=
apply
(
nr
))
return
err
;
if
(
nr
==
0
)
if
(
auto
err
=
apply
(
name
))
return
err
;
return
none
;
result_type
binary_deserializer
::
begin_object
(
type_id_t
&
type
)
{
return
apply
(
type
);
}
result_type
binary_deserializer
::
end_object
()
noexcept
{
...
...
libcaf_core/src/binary_serializer.cpp
View file @
71c043cc
...
...
@@ -49,10 +49,8 @@ void binary_serializer::skip(size_t num_bytes) {
write_pos_
+=
num_bytes
;
}
error_code
<
sec
>
binary_serializer
::
begin_object
(
uint16_t
nr
,
string_view
name
)
{
apply
(
nr
);
if
(
nr
==
0
)
apply
(
name
);
error_code
<
sec
>
binary_serializer
::
begin_object
(
type_id_t
type
)
{
apply
(
type
);
return
none
;
}
...
...
libcaf_core/src/detail/append_hex.cpp
View file @
71c043cc
...
...
@@ -20,15 +20,15 @@
namespace
caf
::
detail
{
void
append_hex
(
std
::
string
&
result
,
const
uint8_t
*
xs
,
size_t
n
)
{
void
append_hex
(
std
::
string
&
result
,
const
byte
*
xs
,
size_t
n
)
{
if
(
n
==
0
)
{
result
+=
"
00
"
;
result
+=
"
<empty>
"
;
return
;
}
auto
tbl
=
"0123456789ABCDEF"
;
char
buf
[
3
]
=
{
0
,
0
,
0
};
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
{
auto
c
=
xs
[
i
]
;
auto
c
=
to_integer
<
uint8_t
>
(
xs
[
i
])
;
buf
[
0
]
=
tbl
[
c
>>
4
];
buf
[
1
]
=
tbl
[
c
&
0x0F
];
result
+=
buf
;
...
...
libcaf_core/src/detail/append_percent_encoded.cpp
View file @
71c043cc
...
...
@@ -18,6 +18,7 @@
#include "caf/detail/append_percent_encoded.hpp"
#include "caf/byte.hpp"
#include "caf/config.hpp"
#include "caf/detail/append_hex.hpp"
#include "caf/string_view.hpp"
...
...
@@ -33,7 +34,7 @@ void append_percent_encoded(std::string& str, string_view x, bool is_path) {
str
+=
ch
;
break
;
}
CAF_ANNOTATE_FALLTHROUGH
;
[[
fallthrough
]]
;
case
' '
:
case
'?'
:
case
'#'
:
...
...
@@ -53,7 +54,7 @@ void append_percent_encoded(std::string& str, string_view x, bool is_path) {
case
';'
:
case
'='
:
str
+=
'%'
;
append_hex
(
str
,
reinterpret_cast
<
uint8_t
*>
(
&
ch
),
1
);
append_hex
(
str
,
reinterpret_cast
<
byte
*>
(
&
ch
),
1
);
break
;
default:
str
+=
ch
;
...
...
libcaf_core/src/detail/meta_object.cpp
View file @
71c043cc
...
...
@@ -76,9 +76,10 @@ span<const meta_object> global_meta_objects() {
return
{
meta_objects
,
meta_objects_size
};
}
meta_object
&
global_meta_object
(
type_id_t
id
)
{
const
meta_object
*
global_meta_object
(
type_id_t
id
)
{
CAF_ASSERT
(
id
<
meta_objects_size
);
return
meta_objects
[
id
];
auto
&
meta
=
meta_objects
[
id
];
return
meta
.
type_name
!=
nullptr
?
&
meta
:
nullptr
;
}
void
clear_global_meta_objects
()
{
...
...
libcaf_core/src/detail/serialized_size.cpp
View file @
71c043cc
...
...
@@ -26,11 +26,8 @@
namespace
caf
::
detail
{
error
serialized_size_inspector
::
begin_object
(
uint16_t
nr
,
string_view
name
)
{
if
(
nr
!=
0
)
return
apply
(
nr
);
apply
(
nr
);
return
apply
(
name
);
error
serialized_size_inspector
::
begin_object
(
type_id_t
type
)
{
return
apply
(
type
);
}
error
serialized_size_inspector
::
end_object
()
{
...
...
libcaf_core/src/inbound_path.cpp
View file @
71c043cc
...
...
@@ -75,7 +75,7 @@ inbound_path::inbound_path(stream_manager_ptr mgr_ptr, stream_slots id,
mgr
->
register_input_path
(
this
);
CAF_STREAM_LOG_DEBUG
(
mgr
->
self
()
->
name
()
<<
"opens input stream with element type"
<<
detail
::
global_meta_object
(
in_type
)
.
type_name
<<
detail
::
global_meta_object
(
in_type
)
->
type_name
<<
"at slot"
<<
id
.
receiver
<<
"from"
<<
hdl
);
if
(
auto
str
=
get_if
<
std
::
string
>
(
&
self
()
->
system
().
config
(),
"stream.credit-policy"
))
{
...
...
libcaf_core/src/message.cpp
View file @
71c043cc
...
...
@@ -154,9 +154,28 @@ error_code<sec> inspect(binary_deserializer& source, message& msg) {
return
msg
.
load
(
source
);
}
std
::
string
to_string
(
const
message
&
)
{
// TODO: implement me
return
""
;
std
::
string
to_string
(
const
message
&
msg
)
{
if
(
msg
.
empty
())
return
"<empty-message>"
;
std
::
string
result
;
result
+=
'('
;
auto
types
=
msg
.
types
();
if
(
!
types
.
empty
())
{
auto
ptr
=
msg
.
cdata
().
storage
();
auto
meta
=
detail
::
global_meta_object
(
types
[
0
]);
CAF_ASSERT
(
meta
!=
nullptr
);
meta
->
stringify
(
result
,
ptr
);
ptr
+=
meta
->
padded_size
;
for
(
size_t
index
=
1
;
index
<
types
.
size
();
++
index
)
{
result
+=
", "
;
meta
=
detail
::
global_meta_object
(
types
[
index
]);
CAF_ASSERT
(
meta
!=
nullptr
);
meta
->
stringify
(
result
,
ptr
);
ptr
+=
meta
->
padded_size
;
}
}
result
+=
')'
;
return
result
;
}
}
// namespace caf
libcaf_core/src/type_id_list.cpp
View file @
71c043cc
...
...
@@ -27,10 +27,10 @@ std::string to_string(type_id_list xs) {
return
"[]"
;
std
::
string
result
;
result
+=
'['
;
result
+=
detail
::
global_meta_object
(
xs
[
0
])
.
type_name
;
result
+=
detail
::
global_meta_object
(
xs
[
0
])
->
type_name
;
for
(
size_t
index
=
1
;
index
<
xs
.
size
();
++
index
)
{
result
+=
", "
;
result
+=
detail
::
global_meta_object
(
xs
[
index
])
.
type_name
;
result
+=
detail
::
global_meta_object
(
xs
[
index
])
->
type_name
;
}
result
+=
']'
;
return
result
;
...
...
libcaf_core/test/detail/meta_object.cpp
View file @
71c043cc
...
...
@@ -160,7 +160,7 @@ CAF_TEST(resizing the global meta objects keeps entries) {
CAF_CHECK_EQUAL
(
xs2
.
size
(),
2u
);
CAF_CHECK
(
eq
(
xs2
[
0
],
meta_i32
));
resize_global_meta_objects
(
3
);
CAF_CHECK
(
eq
(
global_meta_object
(
0
),
meta_i32
));
CAF_CHECK
(
eq
(
*
global_meta_object
(
0
),
meta_i32
));
}
CAF_TEST
(
init_global_meta_objects
takes
care
of
creating
a
meta
object
table
)
{
...
...
@@ -180,11 +180,11 @@ CAF_TEST(init_global_meta_objects takes care of creating a meta object table) {
};
CAF_CHECK
(
std
::
equal
(
xs
.
begin
(),
xs
.
end
(),
ys
.
begin
(),
ys
.
end
(),
same
));
CAF_MESSAGE
(
"init_global_meta_objects can initialize allocated chunks"
);
CAF_CHECK_EQUAL
(
global_meta_object
(
type_id_v
<
float
>
)
.
type_name
,
nullptr
);
CAF_CHECK_EQUAL
(
global_meta_object
(
type_id_v
<
float
>
)
->
type_name
,
nullptr
);
init_global_meta_objects
<
builtin_type_ids
>
();
CAF_MESSAGE
(
"again, calling init_global_meta_objects again is a no-op"
);
init_global_meta_objects
<
builtin_type_ids
>
();
CAF_CHECK_EQUAL
(
global_meta_object
(
type_id_v
<
float
>
)
.
type_name
,
"float"
s
);
CAF_CHECK_EQUAL
(
global_meta_object
(
type_id_v
<
float
>
)
->
type_name
,
"float"
s
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/message.cpp
View file @
71c043cc
...
...
@@ -30,6 +30,7 @@
#include "caf/init_global_meta_objects.hpp"
#include "caf/message_handler.hpp"
#include "caf/type_id.hpp"
#include "caf/type_id_list.hpp"
namespace
{
...
...
@@ -118,6 +119,17 @@ struct config : actor_system_config {
CAF_TEST_FIXTURE_SCOPE
(
message_tests
,
test_coordinator_fixture
<
config
>
)
CAF_TEST
(
messages
allow
index
-
based
access
)
{
auto
msg
=
make_message
(
"abc"
,
uint32_t
{
10
},
20.0
);
CAF_CHECK_EQUAL
(
msg
.
size
(),
3u
);
CAF_CHECK_EQUAL
(
msg
.
types
(),
(
make_type_id_list
<
std
::
string
,
uint32_t
,
double
>
()));
CAF_CHECK_EQUAL
(
msg
.
get_as
<
std
::
string
>
(
0
),
"abc"
);
CAF_CHECK_EQUAL
(
msg
.
get_as
<
uint32_t
>
(
1
),
10u
);
CAF_CHECK_EQUAL
(
msg
.
get_as
<
double
>
(
2
),
20.0
);
CAF_CHECK_EQUAL
(
msg
.
cdata
().
get_reference_count
(),
1u
);
}
CAF_TEST
(
compare_custom_types
)
{
s2
tmp
;
tmp
.
value
[
0
][
1
]
=
100
;
...
...
@@ -127,15 +139,22 @@ CAF_TEST(compare_custom_types) {
CAF_TEST
(
empty_to_string
)
{
message
msg
;
CAF_CHECK
(
to_string
(
msg
),
"<empty-message>"
);
CAF_CHECK
_EQUAL
(
to_string
(
msg
),
"<empty-message>"
);
}
CAF_TEST
(
integers_to_string
)
{
using
ivec
=
vector
<
int
>
;
using
ivec
=
vector
<
int
32_t
>
;
CAF_CHECK_EQUAL
(
msg_as_string
(
1
,
2
,
3
),
"(1, 2, 3)"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
ivec
{
1
,
2
,
3
}),
"([1, 2, 3])"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
ivec
{
1
,
2
},
3
,
4
,
ivec
{
5
,
6
,
7
}),
"([1, 2], 3, 4, [5, 6, 7])"
);
auto
msg
=
make_message
(
ivec
{
1
,
2
,
3
});
CAF_MESSAGE
(
"s1: "
<<
type_id_v
<
s1
>
);
CAF_MESSAGE
(
"ivec: "
<<
type_id_v
<
ivec
>
);
CAF_MESSAGE
(
"msg.types: "
<<
msg
.
types
());
CAF_MESSAGE
(
"types #1: "
<<
make_type_id_list
<
s1
>
());
CAF_MESSAGE
(
"types #2: "
<<
make_type_id_list
<
ivec
>
());
CAF_CHECK_EQUAL
(
msg
.
get_as
<
ivec
>
(
0
),
ivec
({
1
,
2
,
3
}));
}
CAF_TEST
(
strings_to_string
)
{
...
...
manual/ConfiguringActorApplications.rst
View file @
71c043cc
...
...
@@ -187,29 +187,40 @@ Adding Custom Message Types
---------------------------
CAF requires serialization support for all of its message types (see
:ref:`type-inspection`). However, CAF also needs a mapping of unique type
names
to
user-defined types at runtime. This is required to deserialize arbitrary
:ref:`type-inspection`). However, CAF also needs a mapping of unique type
IDs to
user-defined types at runtime. This is required to deserialize arbitrary
messages from the network.
As an introductory example, we (again) use the following POD type
``foo``.
The type IDs are assigned by listing all custom types in a *type ID block*. CAF
assigns ascending IDs to each type by in the block as well as storing the type
name. In the following example, we forward-declare the types ``foo`` and
``foo2`` and register them to CAF in a *type ID block*. The name of the type ID
block is arbitrary, but it must be a valid C++ identifier.
.. literalinclude:: /examples/custom_type/custom_types_1.cpp
:language: C++
:lines: 24-27
:start-after: --(rst-type-id-block-begin)--
:end-before: --(rst-type-id-block-end)--
To make ``foo`` serializable, we make it inspectable:
Aside from a type ID, CAF also requires an ``inspect`` overload in order to be
able to serialize objects. As an introductory example, we (again) use the
following POD type ``foo``.
.. literalinclude:: /examples/custom_type/custom_types_1.cpp
:language: C++
:lines: 30-34
:start-after: --(rst-foo-begin)--
:end-before: --(rst-foo-end)--
Finally, we give ``foo`` a platform-neutral name and add it to the list
of serializable types by using a custom config class.
By assigning type IDs and providing ``inspect`` overloads, we provide static and
compile-time information for all our types. However, CAF also needs some
information at run-time for deserializing received data. The function
``init_global_meta_objects`` takes care fo registering all the state we need at
run-time.
.. literalinclude:: /examples/custom_type/custom_types_1.cpp
:language: C++
:lines: 75-78,81-84
:start-after: --(rst-config-begin)--
:end-before: --(rst-config-end)--
Adding Custom Error Types
-------------------------
...
...
@@ -231,18 +242,14 @@ simple ``calculator`` actor.
.. literalinclude:: /examples/remoting/remote_spawn.cpp
:language: C++
:lines: 33-34
:start-after: --(rst-calculator-begin)--
:end-before: --(rst-calculator-end)--
Adding the calculator actor type to our config is achieved by calling
``add_actor_type<T>``. Note that adding an actor type in this way
implicitly calls ``add_message_type<T>`` for typed actors
add-custom-message-type_. This makes our ``calculator`` actor type
serializable and also enables remote nodes to spawn calculators anywhere in the
distributed actor system (assuming all nodes use the same config).
.. literalinclude:: /examples/remoting/remote_spawn.cpp
:language: C++
:lines: 98-109
``add_actor_type``. After calling this in our config, we can spawn the
``calculator`` anywhere in the distributed actor system (assuming all nodes use
the same config). Note that the handle type still requires a type ID (see
add-custom-message-type_).
Our final example illustrates how to spawn a ``calculator`` locally by
using its type name. Because the dynamic type name lookup can fail and the
...
...
manual/RemoteSpawn.rst
View file @
71c043cc
...
...
@@ -10,7 +10,8 @@ named "calculator".
.. literalinclude:: /examples/remoting/remote_spawn.cpp
:language: C++
:lines: 123-137
:start-after: --(rst-client-begin)--
:end-before: --(rst-client-end)--
We first connect to a CAF node with ``middleman().connect(...)``. On success,
``connect`` returns the node ID we need for ``remote_spawn``. This requires the
...
...
manual/Streaming.rst
View file @
71c043cc
...
...
@@ -69,7 +69,8 @@ Defining Sources
.. literalinclude:: /examples/streaming/integer_stream.cpp
:language: C++
:lines: 17-48
:start-after: --(rst-source-begin)--
:end-before: --(rst-source-end)--
The simplest way to defining a source is to use the
``attach_stream_source`` function and pass it four arguments: a pointer
...
...
@@ -81,7 +82,8 @@ Defining Stages
.. literalinclude:: /examples/streaming/integer_stream.cpp
:language: C++
:lines: 50-83
:start-after: --(rst-stage-begin)--
:end-before: --(rst-stage-end)--
The function ``make_stage`` also takes three lambdas but additionally
the received input stream handshake as first argument. Instead of a predicate,
...
...
@@ -93,7 +95,8 @@ Defining Sinks
.. literalinclude:: /examples/streaming/integer_stream.cpp
:language: C++
:lines: 85-114
:start-after: --(rst-sink-begin)--
:end-before: --(rst-sink-end)--
The function ``make_sink`` is similar to ``make_stage``, except
that is does not produce outputs.
...
...
@@ -103,7 +106,8 @@ Initiating Streams
.. literalinclude:: /examples/streaming/integer_stream.cpp
:language: C++
:lines: 128-132
:start-after: --(rst-main-begin)--
:end-before: --(rst-main-end)--
In our example, we always have a source ``int_source`` and a sink
``int_sink`` with an optional stage ``int_selector``. Sending
...
...
manual/TypeInspection.rst
View file @
71c043cc
...
...
@@ -49,10 +49,9 @@ implementing a hash function.
Inspector {
using result_type = T;
if (inspector only requires read access to the state of T)
static constexpr bool reads_state = true;
else
static constexpr bool writes_state = true;
static constexpr bool reads_state = ...;
static constexpr bool writes_state = ...;
template <class... Ts>
result_type operator()(Ts&&...);
...
...
@@ -116,7 +115,8 @@ access to its members.
.. literalinclude:: /examples/custom_type/custom_types_3.cpp
:language: C++
:lines: 20-49
:start-after: --(rst-foo-begin)--
:end-before: --(rst-foo-end)--
Since there is no access to the data fields ``a_`` and ``b_``
(and assuming no changes to ``foo`` are possible), we need to split our
...
...
@@ -124,7 +124,8 @@ implementation of ``inspect`` as shown below.
.. literalinclude:: /examples/custom_type/custom_types_3.cpp
:language: C++
:lines: 76-103
:start-after: --(rst-inspect-begin)--
:end-before: --(rst-inspect-end)--
The purpose of the scope guard in the example above is to write the content of
the temporaries back to ``foo`` at scope exit automatically. Storing
...
...
tools/caf-vec.cpp
View file @
71c043cc
...
...
@@ -8,6 +8,17 @@
#include "caf/all.hpp"
struct
entity
;
struct
se_event
;
CAF_BEGIN_TYPE_ID_BLOCK
(
caf_vec
,
first_custom_type_id
)
CAF_ADD_TYPE_ID
(
caf_vec
,
entity
);
CAF_ADD_TYPE_ID
(
caf_vec
,
se_event
);
CAF_END_TYPE_ID_BLOCK
(
caf_vec
)
using
std
::
string
;
using
namespace
caf
;
...
...
@@ -739,6 +750,7 @@ struct config : public actor_system_config {
bool
include_hidden_actors
=
false
;
size_t
verbosity
=
0
;
config
()
{
init_global_meta_objects
<
caf_vec_type_ids
>
();
opt_group
{
custom_options_
,
"global"
}
.
add
(
output_file
,
"output-file,o"
,
"Path for the output file"
)
.
add
(
include_hidden_actors
,
"include-hidden-actors,i"
,
...
...
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