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
a3424580
Commit
a3424580
authored
Nov 26, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Port examples to new API
parent
c2a66286
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
525 additions
and
675 deletions
+525
-675
examples/CMakeLists.txt
examples/CMakeLists.txt
+3
-5
examples/aout.cpp
examples/aout.cpp
+3
-4
examples/brokers/protobuf_broker.cpp
examples/brokers/protobuf_broker.cpp
+19
-11
examples/brokers/simple_broker.cpp
examples/brokers/simple_broker.cpp
+26
-27
examples/brokers/simple_http_broker.cpp
examples/brokers/simple_http_broker.cpp
+7
-4
examples/caf-application.ini
examples/caf-application.ini
+24
-0
examples/curl/curl_fuse.cpp
examples/curl/curl_fuse.cpp
+19
-22
examples/custom_types/custom_types_1.cpp
examples/custom_types/custom_types_1.cpp
+129
-0
examples/custom_types/custom_types_2.cpp
examples/custom_types/custom_types_2.cpp
+80
-0
examples/custom_types/custom_types_3.cpp
examples/custom_types/custom_types_3.cpp
+92
-0
examples/hello_world.cpp
examples/hello_world.cpp
+4
-5
examples/message_passing/calculator.cpp
examples/message_passing/calculator.cpp
+7
-10
examples/message_passing/dancing_kirby.cpp
examples/message_passing/dancing_kirby.cpp
+3
-3
examples/message_passing/dining_philosophers.cpp
examples/message_passing/dining_philosophers.cpp
+29
-21
examples/message_passing/typed_calculator.cpp
examples/message_passing/typed_calculator.cpp
+9
-6
examples/remote_actors/distributed_calculator.cpp
examples/remote_actors/distributed_calculator.cpp
+37
-50
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_chat.cpp
+19
-22
examples/remote_actors/group_server.cpp
examples/remote_actors/group_server.cpp
+15
-42
examples/type_system/announce_3.cpp
examples/type_system/announce_3.cpp
+0
-90
examples/type_system/announce_4.cpp
examples/type_system/announce_4.cpp
+0
-136
examples/type_system/announce_5.cpp
examples/type_system/announce_5.cpp
+0
-217
No files found.
examples/CMakeLists.txt
View file @
a3424580
...
@@ -22,11 +22,9 @@ macro(add name folder)
...
@@ -22,11 +22,9 @@ macro(add name folder)
add_dependencies
(
${
name
}
all_examples
)
add_dependencies
(
${
name
}
all_examples
)
endmacro
()
endmacro
()
add
(
announce_1 type_system
)
add
(
custom_types_1 custom_types
)
add
(
announce_2 type_system
)
add
(
custom_types_2 custom_types
)
add
(
announce_3 type_system
)
add
(
custom_types_3 custom_types
)
add
(
announce_4 type_system
)
add
(
announce_5 type_system
)
add
(
dancing_kirby message_passing
)
add
(
dancing_kirby message_passing
)
add
(
dining_philosophers message_passing
)
add
(
dining_philosophers message_passing
)
add
(
hello_world .
)
add
(
hello_world .
)
...
...
examples/aout.cpp
View file @
a3424580
...
@@ -13,8 +13,9 @@ using namespace caf;
...
@@ -13,8 +13,9 @@ using namespace caf;
using
std
::
endl
;
using
std
::
endl
;
int
main
()
{
int
main
()
{
actor_system
system
;
for
(
int
i
=
1
;
i
<=
50
;
++
i
)
{
for
(
int
i
=
1
;
i
<=
50
;
++
i
)
{
spawn
<
blocking_api
>
([
i
](
blocking_actor
*
self
)
{
s
ystem
.
s
pawn
<
blocking_api
>
([
i
](
blocking_actor
*
self
)
{
aout
(
self
)
<<
"Hi there! This is actor nr. "
aout
(
self
)
<<
"Hi there! This is actor nr. "
<<
i
<<
"!"
<<
endl
;
<<
i
<<
"!"
<<
endl
;
std
::
random_device
rd
;
std
::
random_device
rd
;
...
@@ -30,7 +31,5 @@ int main() {
...
@@ -30,7 +31,5 @@ int main() {
});
});
}
}
// wait until all other actors we've spawned are done
// wait until all other actors we've spawned are done
await_all_actors_done
();
system
.
await_all_actors_done
();
// done
shutdown
();
}
}
examples/brokers/protobuf_broker.cpp
View file @
a3424580
...
@@ -144,20 +144,29 @@ maybe<uint16_t> as_u16(const std::string& str) {
...
@@ -144,20 +144,29 @@ maybe<uint16_t> as_u16(const std::string& str) {
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
actor_system_config
cfg
;
cfg
.
load
<
io
::
middleman
>
();
actor_system
system
{
cfg
};
message_builder
{
argv
+
1
,
argv
+
argc
}.
apply
({
message_builder
{
argv
+
1
,
argv
+
argc
}.
apply
({
on
(
"-s"
,
as_u16
)
>>
[
&
](
uint16_t
port
)
{
on
(
"-s"
,
as_u16
)
>>
[
&
](
uint16_t
port
)
{
cout
<<
"run in server mode"
<<
endl
;
cout
<<
"run in server mode"
<<
endl
;
auto
pong_actor
=
spawn
(
pong
);
auto
pong_actor
=
system
.
spawn
(
pong
);
auto
sever_actor
=
spawn_io_server
(
server
,
port
,
pong_actor
);
auto
server_actor
=
system
.
middleman
().
spawn_server
(
server
,
port
,
print_on_exit
(
sever_actor
,
"server"
);
pong_actor
);
print_on_exit
(
pong_actor
,
"pong"
);
if
(
server_actor
)
{
print_on_exit
(
*
server_actor
,
"server"
);
print_on_exit
(
pong_actor
,
"pong"
);
}
},
},
on
(
"-c"
,
val
<
string
>
,
as_u16
)
>>
[
&
](
const
string
&
host
,
uint16_t
port
)
{
on
(
"-c"
,
val
<
string
>
,
as_u16
)
>>
[
&
](
const
string
&
host
,
uint16_t
port
)
{
auto
ping_actor
=
spawn
(
ping
,
20
);
auto
ping_actor
=
system
.
spawn
(
ping
,
20
);
auto
io_actor
=
spawn_io_client
(
protobuf_io
,
host
,
port
,
ping_actor
);
auto
io_actor
=
system
.
middleman
().
spawn_client
(
protobuf_io
,
host
,
print_on_exit
(
io_actor
,
"protobuf_io"
);
port
,
ping_actor
);
print_on_exit
(
ping_actor
,
"ping"
);
if
(
io_actor
)
{
send_as
(
io_actor
,
ping_actor
,
atom
(
"kickoff"
),
io_actor
);
print_on_exit
(
ping_actor
,
"ping"
);
print_on_exit
(
*
io_actor
,
"protobuf_io"
);
send_as
(
*
io_actor
,
ping_actor
,
atom
(
"kickoff"
),
*
io_actor
);
}
},
},
others
>>
[]
{
others
>>
[]
{
cerr
<<
"use with eihter '-s PORT' as server or "
cerr
<<
"use with eihter '-s PORT' as server or "
...
@@ -165,6 +174,5 @@ int main(int argc, char** argv) {
...
@@ -165,6 +174,5 @@ int main(int argc, char** argv) {
<<
endl
;
<<
endl
;
}
}
});
});
await_all_actors_done
();
system
.
await_all_actors_done
();
shutdown
();
}
}
examples/brokers/simple_broker.cpp
View file @
a3424580
...
@@ -193,40 +193,39 @@ int main(int argc, char** argv) {
...
@@ -193,40 +193,39 @@ int main(int argc, char** argv) {
{
"port,p"
,
"set port"
,
port
},
{
"port,p"
,
"set port"
,
port
},
{
"host,H"
,
"set host (client mode only"
}
{
"host,H"
,
"set host (client mode only"
}
});
});
if
(
!
res
.
error
.
empty
())
{
if
(
!
res
.
error
.
empty
())
cerr
<<
res
.
error
<<
endl
;
return
cerr
<<
res
.
error
<<
endl
,
1
;
return
1
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
}
return
cout
<<
res
.
helptext
<<
endl
,
0
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
if
(
!
res
.
remainder
.
empty
())
cout
<<
res
.
helptext
<<
endl
;
return
0
;
}
if
(
!
res
.
remainder
.
empty
())
{
// not all CLI arguments could be consumed
// not all CLI arguments could be consumed
cerr
<<
"*** too many arguments"
<<
endl
<<
res
.
helptext
<<
endl
;
return
cerr
<<
"*** too many arguments"
<<
endl
<<
res
.
helptext
<<
endl
,
1
;
return
1
;
if
(
res
.
opts
.
count
(
"port"
)
==
0
)
}
return
cerr
<<
"*** no port given"
<<
endl
<<
res
.
helptext
<<
endl
,
1
;
if
(
res
.
opts
.
count
(
"port"
)
==
0
)
{
actor_system_config
cfg
;
cerr
<<
"*** no port given"
<<
endl
<<
res
.
helptext
<<
endl
;
cfg
.
load
<
io
::
middleman
>
();
return
1
;
actor_system
system
{
cfg
};
}
if
(
res
.
opts
.
count
(
"server"
)
>
0
)
{
if
(
res
.
opts
.
count
(
"server"
)
>
0
)
{
cout
<<
"run in server mode"
<<
endl
;
cout
<<
"run in server mode"
<<
endl
;
auto
pong_actor
=
spawn
(
pong
);
auto
pong_actor
=
system
.
spawn
(
pong
);
auto
server_actor
=
spawn_io_server
(
server
,
port
,
pong_actor
);
auto
server_actor
=
system
.
middleman
().
spawn_server
(
server
,
port
,
pong_actor
);
print_on_exit
(
server_actor
,
"server"
);
if
(
server_actor
)
{
print_on_exit
(
pong_actor
,
"pong"
);
print_on_exit
(
*
server_actor
,
"server"
);
print_on_exit
(
pong_actor
,
"pong"
);
}
}
else
if
(
res
.
opts
.
count
(
"client"
)
>
0
)
{
}
else
if
(
res
.
opts
.
count
(
"client"
)
>
0
)
{
auto
ping_actor
=
spawn
(
ping
,
size_t
{
20
});
auto
ping_actor
=
system
.
spawn
(
ping
,
size_t
{
20
});
auto
io_actor
=
spawn_io_client
(
broker_impl
,
host
,
port
,
ping_actor
);
auto
io_actor
=
system
.
middleman
().
spawn_client
(
broker_impl
,
host
,
print_on_exit
(
io_actor
,
"protobuf_io"
);
port
,
ping_actor
);
print_on_exit
(
ping_actor
,
"ping"
);
if
(
io_actor
)
{
send_as
(
io_actor
,
ping_actor
,
kickoff_atom
::
value
,
io_actor
);
print_on_exit
(
ping_actor
,
"ping"
);
print_on_exit
(
*
io_actor
,
"protobuf_io"
);
send_as
(
*
io_actor
,
ping_actor
,
kickoff_atom
::
value
,
*
io_actor
);
}
}
else
{
}
else
{
cerr
<<
"*** neither client nor server mode set"
<<
endl
cerr
<<
"*** neither client nor server mode set"
<<
endl
<<
res
.
helptext
<<
endl
;
<<
res
.
helptext
<<
endl
;
return
1
;
return
1
;
}
}
await_all_actors_done
();
system
.
await_all_actors_done
();
shutdown
();
}
}
examples/brokers/simple_http_broker.cpp
View file @
a3424580
...
@@ -95,12 +95,15 @@ int main(int argc, const char** argv) {
...
@@ -95,12 +95,15 @@ int main(int argc, const char** argv) {
}
}
cout
<<
"*** run in server mode listen on: "
<<
port
<<
endl
;
cout
<<
"*** run in server mode listen on: "
<<
port
<<
endl
;
cout
<<
"*** to quit the program, simply press <enter>"
<<
endl
;
cout
<<
"*** to quit the program, simply press <enter>"
<<
endl
;
auto
server_actor
=
spawn_io_server
(
server
,
port
);
actor_system
system
;
auto
server_actor
=
system
.
middleman
().
spawn_server
(
server
,
port
);
if
(
!
server_actor
)
return
cerr
<<
"*** spawn_server failed: "
<<
server_actor
.
error
().
message
()
<<
endl
,
1
;
// wait for any input
// wait for any input
std
::
string
dummy
;
std
::
string
dummy
;
std
::
getline
(
std
::
cin
,
dummy
);
std
::
getline
(
std
::
cin
,
dummy
);
// kill server
// kill server
anon_send_exit
(
server_actor
,
exit_reason
::
user_shutdown
);
anon_send_exit
(
*
server_actor
,
exit_reason
::
user_shutdown
);
await_all_actors_done
();
system
.
await_all_actors_done
();
shutdown
();
}
}
examples/caf-application.ini
0 → 100644
View file @
a3424580
; This file shows all possible parameters with defaults.
; Values enclosed in <> are detected at runtime per default.
; when using the default scheduler
[scheduler]
; accepted alternative: "work-sharing"
policy
=
"work-stealing"
; configures whether the scheduler generates profiling output
enable-profiling
=
false
; can be overriden to force a fixed number of threads
max-threads
=
<detected at runtime>
; configures the maximum number of messages actors can consume in one run
max-throughput
=
<numeric_limits<size_t>::max()>
; measurement resolution in milliseconds (only if profiling is enabled)
profiling-ms-resolution
=
100
; output file for profiler data (only if profiling is enabled)
profiling-output-file
=
"/dev/null"
; when loading io::middleman
[middleman]
; configures whether MMs try to span a full mesh
enable-automatic-connections
=
false
examples/curl/curl_fuse.cpp
View file @
a3424580
...
@@ -346,28 +346,25 @@ int main() {
...
@@ -346,28 +346,25 @@ int main() {
set_sighandler
();
set_sighandler
();
// initialize CURL
// initialize CURL
curl_global_init
(
CURL_GLOBAL_DEFAULT
);
curl_global_init
(
CURL_GLOBAL_DEFAULT
);
{
// lifetime scope of self
actor_system
system
;
scoped_actor
self
;
scoped_actor
self
{
system
};
// spawn client and curl_master
// spawn client and curl_master
auto
master
=
self
->
spawn
<
detached
>
(
curl_master
);
auto
master
=
self
->
spawn
<
detached
>
(
curl_master
);
self
->
spawn
<
detached
>
(
client
,
master
);
self
->
spawn
<
detached
>
(
client
,
master
);
// poll CTRL+C flag every second
// poll CTRL+C flag every second
while
(
!
shutdown_flag
)
while
(
!
shutdown_flag
)
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
seconds
(
1
));
std
::
this_thread
::
sleep_for
(
std
::
chrono
::
seconds
(
1
));
aout
(
self
)
<<
color
::
cyan
<<
"received CTRL+C"
<<
color
::
reset_endl
;
aout
(
self
)
<<
color
::
cyan
<<
"received CTRL+C"
<<
color
::
reset_endl
;
// shutdown actors
// shutdown actors
anon_send_exit
(
master
,
exit_reason
::
user_shutdown
);
anon_send_exit
(
master
,
exit_reason
::
user_shutdown
);
// await actors
// await actors
act
.
sa_handler
=
[](
int
)
{
abort
();
};
act
.
sa_handler
=
[](
int
)
{
abort
();
};
set_sighandler
();
set_sighandler
();
aout
(
self
)
<<
color
::
cyan
aout
(
self
)
<<
color
::
cyan
<<
"await CURL; this may take a while "
<<
"await CURL; this may take a while "
"(press CTRL+C again to abort)"
"(press CTRL+C again to abort)"
<<
color
::
reset_endl
;
<<
color
::
reset_endl
;
self
->
await_all_other_actors_done
();
self
->
await_all_other_actors_done
();
}
// shutdown libcaf
shutdown
();
// shutdown CURL
// shutdown CURL
curl_global_cleanup
();
curl_global_cleanup
();
}
}
examples/
type_system/announce
_1.cpp
→
examples/
custom_types/custom_types
_1.cpp
View file @
a3424580
// showcases how to add custom POD message types to CAF
#include <tuple>
#include <string>
#include <vector>
#include <vector>
#include <cassert>
#include <cassert>
#include <utility>
#include <utility>
...
@@ -20,102 +24,106 @@ struct foo {
...
@@ -20,102 +24,106 @@ struct foo {
int
b
;
int
b
;
};
};
//
announce requires foo to have the equal operator implemented
//
foo needs to be comparable ...
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
}
// ... and to be serializable
template
<
class
T
>
void
serialize
(
T
&
in_or_out
,
foo
&
x
,
const
unsigned
int
)
{
in_or_out
&
x
.
a
;
in_or_out
&
x
.
b
;
}
// also, CAF gives us `deep_to_string` for implementing `to_string` easily
std
::
string
to_string
(
const
foo
&
x
)
{
// `to_string(foo{{1, 2, 3}, 4})` prints: "foo([1, 2, 3], 4)"
return
"foo"
+
deep_to_string
(
std
::
forward_as_tuple
(
x
.
a
,
x
.
b
));
}
// a pair of two ints
// a pair of two ints
using
foo_pair
=
std
::
pair
<
int
,
int
>
;
using
foo_pair
=
std
::
pair
<
int
,
int
>
;
// another
pair
of two ints
// another
alias for pairs
of two ints
using
foo_pair2
=
std
::
pair
<
int
,
int
>
;
using
foo_pair2
=
std
::
pair
<
int
,
int
>
;
// a struct with
member vector<vector<...>>
// a struct with
a nested container
struct
foo2
{
struct
foo2
{
int
a
;
int
a
;
vector
<
vector
<
double
>>
b
;
vector
<
vector
<
double
>>
b
;
};
};
// foo2 also needs to be comparable ...
bool
operator
==
(
const
foo2
&
lhs
,
const
foo2
&
rhs
)
{
bool
operator
==
(
const
foo2
&
lhs
,
const
foo2
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
}
// receives `remaining` messages
// ... and to be serializable
template
<
class
T
>
void
serialize
(
T
&
in_or_out
,
foo2
&
x
,
const
unsigned
int
)
{
in_or_out
&
x
.
a
;
in_or_out
&
x
.
b
;
// traversed automatically and recursively
}
// `deep_to_string` also traverses nested containers
std
::
string
to_string
(
const
foo2
&
x
)
{
return
"foo"
+
deep_to_string
(
std
::
forward_as_tuple
(
x
.
a
,
x
.
b
));
}
// receives our custom message types
void
testee
(
event_based_actor
*
self
,
size_t
remaining
)
{
void
testee
(
event_based_actor
*
self
,
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
self
,
remaining
-
1
);
if
(
remaining
>
1
)
else
self
->
quit
();
testee
(
self
,
remaining
-
1
);
else
self
->
quit
();
};
};
self
->
become
(
self
->
become
(
// note: we sent a foo_pair2, but match on foo_pair
// note: we sent a foo_pair2, but match on foo_pair
// that
's safe
because both are aliases for std::pair<int, int>
// that
works
because both are aliases for std::pair<int, int>
[
=
](
const
foo_pair
&
val
)
{
[
=
](
const
foo_pair
&
val
)
{
cout
<<
"foo_pair("
aout
(
self
)
<<
"foo_pair"
<<
deep_to_string
(
val
)
<<
endl
;
<<
val
.
first
<<
", "
<<
val
.
second
<<
")"
<<
endl
;
set_next_behavior
();
set_next_behavior
();
},
},
[
=
](
const
foo
&
val
)
{
[
=
](
const
foo
&
val
)
{
cout
<<
"foo({"
;
aout
(
self
)
<<
to_string
(
val
)
<<
endl
;
auto
i
=
val
.
a
.
begin
();
auto
end
=
val
.
a
.
end
();
if
(
i
!=
end
)
{
cout
<<
*
i
;
while
(
++
i
!=
end
)
{
cout
<<
", "
<<
*
i
;
}
}
cout
<<
"}, "
<<
val
.
b
<<
")"
<<
endl
;
set_next_behavior
();
set_next_behavior
();
}
}
);
);
}
}
int
main
(
int
,
char
**
)
{
int
main
(
int
,
char
**
)
{
// announces foo to the libcaf type system;
actor_system_config
cfg
;
// the function expects member pointers to all elements of foo
cfg
.
add_message_type
<
foo
>
(
"foo"
);
announce
<
foo
>
(
"foo"
,
&
foo
::
a
,
&
foo
::
b
);
cfg
.
add_message_type
<
foo2
>
(
"foo2"
);
// announce foo2 to the libcaf type system,
cfg
.
add_message_type
<
foo_pair
>
(
"foo_pair"
);
// note that recursive containers are managed automatically by libcaf
// this actor system can now serialize our custom types when running
announce
<
foo2
>
(
"foo2"
,
&
foo2
::
a
,
&
foo2
::
b
);
// a distributed CAF application or we can serialize them manually
// serialization can throw if types are not announced properly
actor_system
system
{
cfg
};
try
{
// two variables for testing serialization
// init some test data
foo2
f1
;
foo2
vd
;
foo2
f2
;
vd
.
a
=
5
;
// init some test data
vd
.
b
.
resize
(
1
);
f1
.
a
=
5
;
vd
.
b
.
back
().
push_back
(
42
);
f1
.
b
.
resize
(
1
);
// serialize test data
f1
.
b
.
back
().
push_back
(
42
);
vector
<
char
>
buf
;
// I/O buffer
binary_serializer
bs
(
std
::
back_inserter
(
buf
));
vector
<
char
>
buf
;
bs
<<
vd
;
// write f1 to buffer
// deserialize written test data from buffer
binary_serializer
bs
{
system
,
buf
};
binary_deserializer
bd
(
buf
.
data
(),
buf
.
size
());
bs
<<
f1
;
foo2
vd2
;
// read f2 back from buffer
uniform_typeid
<
foo2
>
()
->
deserialize
(
&
vd2
,
&
bd
);
binary_deserializer
bd
{
system
,
buf
};
// deserialized data must be equal to original input
bd
>>
f2
;
assert
(
vd
==
vd2
);
// must be equal
// announce std::pair<int, int> to the type system
assert
(
f1
==
f2
);
announce
<
foo_pair
>
(
"foo_pair"
,
&
foo_pair
::
first
,
&
foo_pair
::
second
);
// libcaf returns the same uniform_type_info
// instance for the type aliases foo_pair and foo_pair2
assert
(
uniform_typeid
<
foo_pair
>
()
==
uniform_typeid
<
foo_pair2
>
());
}
catch
(
std
::
exception
&
e
)
{
cerr
<<
"error during type (de)serialization: "
<<
e
.
what
()
<<
endl
;
return
-
1
;
}
// spawn a testee that receives two messages of user-defined type
// spawn a testee that receives two messages of user-defined type
auto
t
=
spawn
(
testee
,
size_t
{
2
});
auto
t
=
system
.
spawn
(
testee
,
2
);
{
// lifetime scope of self
scoped_actor
self
{
system
};
scoped_actor
self
;
// send t a foo
// send t a foo
self
->
send
(
t
,
foo
{
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
},
5
});
self
->
send
(
t
,
foo
{
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
},
5
});
// send t a foo_pair2
// send t a foo_pair2
self
->
send
(
t
,
foo_pair2
{
3
,
4
});
self
->
send
(
t
,
foo_pair2
{
3
,
4
});
self
->
await_all_other_actors_done
();
}
await_all_actors_done
();
shutdown
();
}
}
examples/
type_system/announce
_2.cpp
→
examples/
custom_types/custom_types
_2.cpp
View file @
a3424580
// showcases how to add custom message types to CAF
// if friend access for serialization is available
#include <utility>
#include <utility>
#include <iostream>
#include <iostream>
...
@@ -11,57 +14,67 @@ using namespace caf;
...
@@ -11,57 +14,67 @@ using namespace caf;
// a simple class using getter and setter member functions
// a simple class using getter and setter member functions
class
foo
{
class
foo
{
int
a_
;
int
b_
;
public:
public:
foo
(
int
a0
=
0
,
int
b0
=
0
)
:
a_
(
a0
),
b_
(
b0
)
{
foo
(
int
a0
=
0
,
int
b0
=
0
)
:
a_
(
a0
),
b_
(
b0
)
{
}
// nop
}
foo
(
const
foo
&
)
=
default
;
foo
(
const
foo
&
)
=
default
;
foo
&
operator
=
(
const
foo
&
)
=
default
;
foo
&
operator
=
(
const
foo
&
)
=
default
;
int
a
()
const
{
return
a_
;
}
int
a
()
const
{
return
a_
;
}
void
set_a
(
int
val
)
{
a_
=
val
;
}
void
set_a
(
int
val
)
{
a_
=
val
;
}
int
b
()
const
{
return
b_
;
}
int
b
()
const
{
return
b_
;
}
void
set_b
(
int
val
)
{
b_
=
val
;
}
void
set_b
(
int
val
)
{
b_
=
val
;
}
};
// compare
friend
bool
operator
==
(
const
foo
&
x
,
const
foo
&
y
)
{
return
x
.
a_
==
y
.
a_
&&
x
.
b_
==
y
.
b_
;
}
// announce requires foo to be comparable
// serialize
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
template
<
class
T
>
return
lhs
.
a
()
==
rhs
.
a
()
friend
void
serialize
(
T
&
in_or_out
,
foo
&
x
,
const
unsigned
int
)
{
&&
lhs
.
b
()
==
rhs
.
b
();
in_or_out
&
x
.
a_
;
}
in_or_out
&
x
.
b_
;
}
// print
friend
std
::
string
to_string
(
const
foo
&
x
)
{
return
"foo"
+
deep_to_string
(
std
::
forward_as_tuple
(
x
.
a_
,
x
.
b_
));
}
private:
int
a_
;
int
b_
;
};
void
testee
(
event_based_actor
*
self
)
{
void
testee
(
event_based_actor
*
self
)
{
self
->
become
(
self
->
become
(
[
=
](
const
foo
&
val
)
{
[
=
](
const
foo
&
x
)
{
aout
(
self
)
<<
"foo("
aout
(
self
)
<<
to_string
(
x
)
<<
endl
;
<<
val
.
a
()
<<
", "
<<
val
.
b
()
<<
")"
<<
endl
;
self
->
quit
();
self
->
quit
();
}
}
);
);
}
}
int
main
(
int
,
char
**
)
{
int
main
(
int
,
char
**
)
{
// if a class uses getter and setter member functions,
actor_system_config
cfg
;
// we pass those to the announce function as { getter, setter } pairs.
cfg
.
add_message_type
<
foo
>
(
"foo"
);
announce
<
foo
>
(
"foo"
,
make_pair
(
&
foo
::
a
,
&
foo
::
set_a
),
actor_system
system
{
cfg
};
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
));
scoped_actor
self
{
system
};
{
auto
t
=
self
->
spawn
(
testee
);
scoped_actor
self
;
self
->
send
(
t
,
foo
{
1
,
2
});
auto
t
=
spawn
(
testee
);
self
->
await_all_other_actors_done
();
self
->
send
(
t
,
foo
{
1
,
2
});
}
await_all_actors_done
();
shutdown
();
return
0
;
}
}
examples/custom_types/custom_types_3.cpp
0 → 100644
View file @
a3424580
// showcases how to add custom message types to CAF
// if no friend access for serialization is possible
#include <utility>
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
std
::
make_pair
;
using
namespace
caf
;
// identical to our second custom type example,
// but without friend declarations
class
foo
{
public:
foo
(
int
a0
=
0
,
int
b0
=
0
)
:
a_
(
a0
),
b_
(
b0
)
{
// nop
}
foo
(
const
foo
&
)
=
default
;
foo
&
operator
=
(
const
foo
&
)
=
default
;
int
a
()
const
{
return
a_
;
}
void
set_a
(
int
val
)
{
a_
=
val
;
}
int
b
()
const
{
return
b_
;
}
void
set_b
(
int
val
)
{
b_
=
val
;
}
private:
int
a_
;
int
b_
;
};
// comparing is straightforward ...
bool
operator
==
(
const
foo
&
x
,
const
foo
&
y
)
{
return
x
.
a
()
==
y
.
a
()
&&
x
.
b
()
==
y
.
b
();
}
// ... and so is to_string, ...
std
::
string
to_string
(
const
foo
&
x
)
{
return
"foo"
+
deep_to_string
(
std
::
forward_as_tuple
(
x
.
a
(),
x
.
b
()));
}
// ... but we need to split serialization into a saving ...
template
<
class
T
>
typename
std
::
enable_if
<
T
::
is_saving
::
value
>::
type
serialize
(
T
&
out
,
const
foo
&
x
,
const
unsigned
int
)
{
out
<<
x
.
a
()
<<
x
.
b
();
}
// ... and a loading function
template
<
class
T
>
typename
std
::
enable_if
<
T
::
is_loading
::
value
>::
type
serialize
(
T
&
in
,
foo
&
x
,
const
unsigned
int
)
{
int
tmp
;
in
>>
tmp
;
x
.
set_a
(
tmp
);
in
>>
tmp
;
x
.
set_b
(
tmp
);
}
void
testee
(
event_based_actor
*
self
)
{
self
->
become
(
[
=
](
const
foo
&
x
)
{
aout
(
self
)
<<
to_string
(
x
)
<<
endl
;
self
->
quit
();
}
);
}
int
main
(
int
,
char
**
)
{
actor_system_config
cfg
;
cfg
.
add_message_type
<
foo
>
(
"foo"
);
actor_system
system
{
cfg
};
scoped_actor
self
{
system
};
auto
t
=
self
->
spawn
(
testee
);
self
->
send
(
t
,
foo
{
1
,
2
});
self
->
await_all_other_actors_done
();
}
examples/hello_world.cpp
View file @
a3424580
...
@@ -36,12 +36,11 @@ void hello_world(event_based_actor* self, const actor& buddy) {
...
@@ -36,12 +36,11 @@ void hello_world(event_based_actor* self, const actor& buddy) {
}
}
int
main
()
{
int
main
()
{
actor_system
system
;
// create a new actor that calls 'mirror()'
// create a new actor that calls 'mirror()'
auto
mirror_actor
=
spawn
(
mirror
);
auto
mirror_actor
=
s
ystem
.
s
pawn
(
mirror
);
// create another actor that calls 'hello_world(mirror_actor)';
// create another actor that calls 'hello_world(mirror_actor)';
spawn
(
hello_world
,
mirror_actor
);
s
ystem
.
s
pawn
(
hello_world
,
mirror_actor
);
// wait until all other actors we have spawned are done
// wait until all other actors we have spawned are done
await_all_actors_done
();
system
.
await_all_actors_done
();
// run cleanup code before exiting main
shutdown
();
}
}
examples/message_passing/calculator.cpp
View file @
a3424580
...
@@ -88,20 +88,17 @@ void tester(event_based_actor* self, const Handle& testee, int x, int y) {
...
@@ -88,20 +88,17 @@ void tester(event_based_actor* self, const Handle& testee, int x, int y) {
);
);
}
}
void
test_calculators
()
{
int
main
()
{
scoped_actor
self
;
actor_system
system
;
scoped_actor
self
{
system
};
aout
(
self
)
<<
"blocking actor:"
<<
endl
;
aout
(
self
)
<<
"blocking actor:"
<<
endl
;
self
->
spawn
(
tester
<
actor
>
,
spawn
<
blocking_api
>
(
blocking_calculator
),
1
,
2
);
self
->
spawn
(
tester
<
actor
>
,
self
->
spawn
<
blocking_api
>
(
blocking_calculator
),
1
,
2
);
self
->
await_all_other_actors_done
();
self
->
await_all_other_actors_done
();
aout
(
self
)
<<
"event-based actor:"
<<
endl
;
aout
(
self
)
<<
"event-based actor:"
<<
endl
;
self
->
spawn
(
tester
<
actor
>
,
spawn
(
calculator
),
3
,
4
);
self
->
spawn
(
tester
<
actor
>
,
s
elf
->
s
pawn
(
calculator
),
3
,
4
);
self
->
await_all_other_actors_done
();
self
->
await_all_other_actors_done
();
aout
(
self
)
<<
"typed actor:"
<<
endl
;
aout
(
self
)
<<
"typed actor:"
<<
endl
;
self
->
spawn
(
tester
<
calculator_actor
>
,
spawn
(
typed_calculator
),
5
,
6
);
self
->
spawn
(
tester
<
calculator_actor
>
,
s
elf
->
s
pawn
(
typed_calculator
),
5
,
6
);
self
->
await_all_other_actors_done
();
self
->
await_all_other_actors_done
();
}
}
int
main
()
{
test_calculators
();
shutdown
();
}
examples/message_passing/dancing_kirby.cpp
View file @
a3424580
...
@@ -71,7 +71,7 @@ void dancing_kirby(event_based_actor* self) {
...
@@ -71,7 +71,7 @@ void dancing_kirby(event_based_actor* self) {
}
}
int
main
()
{
int
main
()
{
spawn
(
dancing_kirby
)
;
actor_system
system
;
await_all_actors_done
(
);
system
.
spawn
(
dancing_kirby
);
s
hutdown
();
s
ystem
.
await_all_actors_done
();
}
}
examples/message_passing/dining_philosophers.cpp
View file @
a3424580
...
@@ -4,11 +4,22 @@
...
@@ -4,11 +4,22 @@
\ ******************************************************************************/
\ ******************************************************************************/
#include <map>
#include <map>
#include <thread>
#include <vector>
#include <vector>
#include <chrono>
#include <chrono>
#include <sstream>
#include <sstream>
#include <iostream>
#include <iostream>
namespace
std
{
string
to_string
(
const
thread
::
id
&
x
)
{
ostringstream
os
;
os
<<
x
;
return
os
.
str
();
}
}
#include "caf/all.hpp"
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
cout
;
...
@@ -58,9 +69,8 @@ chopstick::behavior_type taken_chopstick(chopstick::pointer self,
...
@@ -58,9 +69,8 @@ chopstick::behavior_type taken_chopstick(chopstick::pointer self,
return
busy_atom
::
value
;
return
busy_atom
::
value
;
},
},
[
=
](
put_atom
)
{
[
=
](
put_atom
)
{
if
(
self
->
current_sender
()
==
user
)
{
if
(
self
->
current_sender
()
==
user
)
self
->
become
(
available_chopstick
(
self
));
self
->
become
(
available_chopstick
(
self
));
}
}
}
};
};
}
}
...
@@ -96,8 +106,12 @@ chopstick::behavior_type taken_chopstick(chopstick::pointer self,
...
@@ -96,8 +106,12 @@ chopstick::behavior_type taken_chopstick(chopstick::pointer self,
class
philosopher
:
public
event_based_actor
{
class
philosopher
:
public
event_based_actor
{
public:
public:
philosopher
(
const
std
::
string
&
n
,
const
chopstick
&
l
,
const
chopstick
&
r
)
philosopher
(
actor_config
&
cfg
,
:
name
(
n
),
const
std
::
string
&
n
,
const
chopstick
&
l
,
const
chopstick
&
r
)
:
event_based_actor
(
cfg
),
name
(
n
),
left
(
l
),
left
(
l
),
right
(
r
)
{
right
(
r
)
{
// a philosopher that receives {eat} stops thinking and becomes hungry
// a philosopher that receives {eat} stops thinking and becomes hungry
...
@@ -180,32 +194,26 @@ private:
...
@@ -180,32 +194,26 @@ private:
behavior
hungry
;
// tries to take chopsticks
behavior
hungry
;
// tries to take chopsticks
behavior
granted
;
// has one chopstick and waits for the second one
behavior
granted
;
// has one chopstick and waits for the second one
behavior
denied
;
// could not get first chopsticks
behavior
denied
;
// could not get first chopsticks
behavior
eating
;
// wait
s
for some time, then go thinking again
behavior
eating
;
// wait for some time, then go thinking again
};
};
void
dining_philosophers
()
{
}
// namespace <anonymous>
scoped_actor
self
;
int
main
(
int
,
char
**
)
{
actor_system
system
;
scoped_actor
self
{
system
};
// create five chopsticks
// create five chopsticks
aout
(
self
)
<<
"chopstick ids are:"
;
aout
(
self
)
<<
"chopstick ids are:"
;
std
::
vector
<
chopstick
>
chopsticks
;
std
::
vector
<
chopstick
>
chopsticks
;
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
{
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
{
chopsticks
.
push_back
(
spawn
(
available_chopstick
));
chopsticks
.
push_back
(
s
elf
->
s
pawn
(
available_chopstick
));
aout
(
self
)
<<
" "
<<
chopsticks
.
back
()
->
id
();
aout
(
self
)
<<
" "
<<
chopsticks
.
back
()
->
id
();
}
}
aout
(
self
)
<<
endl
;
aout
(
self
)
<<
endl
;
// spawn five philosophers
// spawn five philosophers
std
::
vector
<
std
::
string
>
names
{
"Plato"
,
"Hume"
,
"Kant"
,
std
::
vector
<
std
::
string
>
names
{
"Plato"
,
"Hume"
,
"Kant"
,
"Nietzsche"
,
"Descartes"
};
"Nietzsche"
,
"Descartes"
};
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
{
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
spawn
<
philosopher
>
(
names
[
i
],
chopsticks
[
i
],
chopsticks
[(
i
+
1
)
%
5
]);
self
->
spawn
<
philosopher
>
(
names
[
i
],
chopsticks
[
i
],
chopsticks
[(
i
+
1
)
%
5
]);
}
system
.
await_all_actors_done
();
}
}
// namespace <anonymous>
int
main
(
int
,
char
**
)
{
dining_philosophers
();
// real philosophers are never done
await_all_actors_done
();
shutdown
();
}
}
examples/message_passing/typed_calculator.cpp
View file @
a3424580
...
@@ -33,6 +33,10 @@ calculator_type::behavior_type typed_calculator(calculator_type::pointer) {
...
@@ -33,6 +33,10 @@ calculator_type::behavior_type typed_calculator(calculator_type::pointer) {
class
typed_calculator_class
:
public
calculator_type
::
base
{
class
typed_calculator_class
:
public
calculator_type
::
base
{
protected:
protected:
typed_calculator_class
(
actor_config
&
cfg
)
:
calculator_type
::
base
(
cfg
)
{
// nop
}
behavior_type
make_behavior
()
override
{
behavior_type
make_behavior
()
override
{
return
{
return
{
[](
plus_atom
,
int
x
,
int
y
)
{
[](
plus_atom
,
int
x
,
int
y
)
{
...
@@ -73,12 +77,11 @@ void tester(event_based_actor* self, const calculator_type& testee) {
...
@@ -73,12 +77,11 @@ void tester(event_based_actor* self, const calculator_type& testee) {
}
// namespace <anonymous>
}
// namespace <anonymous>
int
main
()
{
int
main
()
{
actor_system
system
;
// test function-based impl
// test function-based impl
s
pawn
(
tester
,
spawn
(
typed_calculator
));
s
ystem
.
spawn
(
tester
,
system
.
spawn
(
typed_calculator
));
await_all_actors_done
();
system
.
await_all_actors_done
();
// test class-based impl
// test class-based impl
spawn
(
tester
,
spawn
<
typed_calculator_class
>
());
system
.
spawn
(
tester
,
system
.
spawn
<
typed_calculator_class
>
());
await_all_actors_done
();
system
.
await_all_actors_done
();
// done
shutdown
();
}
}
examples/remote_actors/distributed_calculator.cpp
View file @
a3424580
...
@@ -51,8 +51,9 @@ behavior calculator() {
...
@@ -51,8 +51,9 @@ behavior calculator() {
class
client_impl
:
public
event_based_actor
{
class
client_impl
:
public
event_based_actor
{
public:
public:
client_impl
(
string
hostaddr
,
uint16_t
port
)
client_impl
(
actor_config
&
cfg
,
string
hostaddr
,
uint16_t
port
)
:
host_
(
std
::
move
(
hostaddr
)),
:
event_based_actor
(
cfg
),
host_
(
std
::
move
(
hostaddr
)),
port_
(
port
)
{
port_
(
port
)
{
// nop
// nop
}
}
...
@@ -103,7 +104,7 @@ private:
...
@@ -103,7 +104,7 @@ private:
behavior
reconnecting
(
std
::
function
<
void
()
>
continuation
=
nullptr
)
{
behavior
reconnecting
(
std
::
function
<
void
()
>
continuation
=
nullptr
)
{
using
std
::
chrono
::
seconds
;
using
std
::
chrono
::
seconds
;
auto
mm
=
io
::
get_middleman_actor
();
auto
mm
=
system
().
middleman
().
actor_handle
();
send
(
mm
,
connect_atom
::
value
,
host_
,
port_
);
send
(
mm
,
connect_atom
::
value
,
host_
,
port_
);
return
{
return
{
[
=
](
ok_atom
,
node_id
&
,
actor_addr
&
new_server
,
std
::
set
<
std
::
string
>&
)
{
[
=
](
ok_atom
,
node_id
&
,
actor_addr
&
new_server
,
std
::
set
<
std
::
string
>&
)
{
...
@@ -179,16 +180,14 @@ maybe<int> toint(const string& str) {
...
@@ -179,16 +180,14 @@ maybe<int> toint(const string& str) {
// converts "+" to the atom '+' and "-" to the atom '-'
// converts "+" to the atom '+' and "-" to the atom '-'
maybe
<
atom_value
>
plus_or_minus
(
const
string
&
str
)
{
maybe
<
atom_value
>
plus_or_minus
(
const
string
&
str
)
{
if
(
str
==
"+"
)
{
if
(
str
==
"+"
)
return
maybe
<
atom_value
>
{
plus_atom
::
value
};
return
plus_atom
::
value
;
}
if
(
str
==
"-"
)
if
(
str
==
"-"
)
{
return
minus_atom
::
value
;
return
maybe
<
atom_value
>
{
minus_atom
::
value
};
}
return
none
;
return
none
;
}
}
void
client_repl
(
string
host
,
uint16_t
port
)
{
void
client_repl
(
actor_system
&
system
,
string
host
,
uint16_t
port
)
{
// keeps track of requests and tries to reconnect on server failures
// keeps track of requests and tries to reconnect on server failures
auto
usage
=
[]
{
auto
usage
=
[]
{
cout
<<
"Usage:"
<<
endl
cout
<<
"Usage:"
<<
endl
...
@@ -200,7 +199,7 @@ void client_repl(string host, uint16_t port) {
...
@@ -200,7 +199,7 @@ void client_repl(string host, uint16_t port) {
};
};
usage
();
usage
();
bool
done
=
false
;
bool
done
=
false
;
auto
client
=
spawn
<
client_impl
>
(
std
::
move
(
host
),
port
);
auto
client
=
s
ystem
.
s
pawn
<
client_impl
>
(
std
::
move
(
host
),
port
);
// defining the handler outside the loop is more efficient as it avoids
// defining the handler outside the loop is more efficient as it avoids
// re-creating the same object over and over again
// re-creating the same object over and over again
message_handler
eval
{
message_handler
eval
{
...
@@ -258,54 +257,42 @@ int main(int argc, char** argv) {
...
@@ -258,54 +257,42 @@ int main(int argc, char** argv) {
{
"server,s"
,
"run in server mode"
},
{
"server,s"
,
"run in server mode"
},
{
"client,c"
,
"run in client mode"
}
{
"client,c"
,
"run in client mode"
}
});
});
if
(
!
res
.
error
.
empty
())
{
if
(
!
res
.
error
.
empty
())
cerr
<<
res
.
error
<<
endl
;
return
cerr
<<
res
.
error
<<
endl
,
1
;
return
1
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
}
return
cout
<<
res
.
helptext
<<
endl
,
0
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
// not all CLI arguments could be consumed
cout
<<
res
.
helptext
<<
endl
;
if
(
!
res
.
remainder
.
empty
())
return
0
;
return
cerr
<<
"*** invalid CLI options"
<<
endl
<<
res
.
helptext
<<
endl
,
1
;
}
if
(
!
res
.
remainder
.
empty
())
{
// not all CLI arguments could be consumed
cerr
<<
"*** invalid command line options"
<<
endl
<<
res
.
helptext
<<
endl
;
return
1
;
}
bool
is_server
=
res
.
opts
.
count
(
"server"
)
>
0
;
bool
is_server
=
res
.
opts
.
count
(
"server"
)
>
0
;
if
(
is_server
==
(
res
.
opts
.
count
(
"client"
)
>
0
))
{
if
(
is_server
==
(
res
.
opts
.
count
(
"client"
)
>
0
))
{
if
(
is_server
)
{
if
(
is_server
)
cerr
<<
"*** cannot be server and client at the same time"
<<
endl
;
cerr
<<
"*** cannot be server and client at the same time"
<<
endl
;
}
else
{
else
cerr
<<
"*** either --server or --client option must be set"
<<
endl
;
cerr
<<
"*** either --server or --client option must be set"
<<
endl
;
}
return
1
;
}
if
(
!
is_server
&&
port
==
0
)
{
cerr
<<
"*** no port to server specified"
<<
endl
;
return
1
;
return
1
;
}
}
if
(
!
is_server
&&
port
==
0
)
return
cerr
<<
"*** no port to server specified"
<<
endl
,
1
;
actor_system_config
cfg
;
cfg
.
load
<
io
::
middleman
>
();
actor_system
system
{
cfg
};
if
(
is_server
)
{
if
(
is_server
)
{
auto
calc
=
spawn
(
calculator
);
auto
calc
=
system
.
spawn
(
calculator
);
try
{
// try to publish math actor at given port
// try to publish math actor at given port
cout
<<
"*** try publish at port "
<<
port
<<
endl
;
cout
<<
"*** try publish at port "
<<
port
<<
endl
;
auto
p
=
system
.
middleman
().
publish
(
calc
,
port
);
auto
p
=
io
::
publish
(
calc
,
port
);
if
(
!
p
)
cout
<<
"*** server successfully published at port "
<<
p
<<
endl
;
return
cerr
<<
"*** error: "
<<
p
.
error
().
message
()
<<
endl
,
1
;
cout
<<
"*** press [enter] to quit"
<<
endl
;
cout
<<
"*** server successfully published at port "
<<
*
p
<<
endl
;
string
dummy
;
cout
<<
"*** press [enter] to quit"
<<
endl
;
std
::
getline
(
std
::
cin
,
dummy
);
string
dummy
;
cout
<<
"... cya"
<<
endl
;
std
::
getline
(
std
::
cin
,
dummy
);
}
cout
<<
"... cya"
<<
endl
;
catch
(
std
::
exception
&
e
)
{
cerr
<<
"*** unable to publish math actor at port "
<<
port
<<
"
\n
"
<<
to_verbose_string
(
e
)
// prints exception type and e.what()
<<
endl
;
}
anon_send_exit
(
calc
,
exit_reason
::
user_shutdown
);
anon_send_exit
(
calc
,
exit_reason
::
user_shutdown
);
}
}
else
{
else
{
client_repl
(
host
,
port
);
client_repl
(
system
,
host
,
port
);
}
}
await_all_actors_done
();
system
.
await_all_actors_done
();
shutdown
();
}
}
examples/remote_actors/group_chat.cpp
View file @
a3424580
...
@@ -71,18 +71,12 @@ int main(int argc, char** argv) {
...
@@ -71,18 +71,12 @@ int main(int argc, char** argv) {
{
"name,n"
,
"set name"
,
name
},
{
"name,n"
,
"set name"
,
name
},
{
"group,g"
,
"join group"
,
group_id
}
{
"group,g"
,
"join group"
,
group_id
}
});
});
if
(
!
res
.
error
.
empty
())
{
if
(
!
res
.
error
.
empty
())
cerr
<<
res
.
error
<<
endl
;
return
cerr
<<
res
.
error
<<
endl
,
1
;
return
1
;
if
(
!
res
.
remainder
.
empty
())
}
return
std
::
cout
<<
res
.
helptext
<<
std
::
endl
,
1
;
if
(
!
res
.
remainder
.
empty
())
{
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
std
::
cout
<<
res
.
helptext
<<
std
::
endl
;
return
cout
<<
res
.
helptext
<<
endl
,
0
;
return
1
;
}
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
cout
<<
res
.
helptext
<<
endl
;
return
0
;
}
while
(
name
.
empty
())
{
while
(
name
.
empty
())
{
cout
<<
"please enter your name: "
<<
flush
;
cout
<<
"please enter your name: "
<<
flush
;
if
(
!
getline
(
cin
,
name
))
{
if
(
!
getline
(
cin
,
name
))
{
...
@@ -90,7 +84,10 @@ int main(int argc, char** argv) {
...
@@ -90,7 +84,10 @@ int main(int argc, char** argv) {
return
1
;
return
1
;
}
}
}
}
auto
client_actor
=
spawn
(
client
,
name
);
actor_system_config
cfg
;
cfg
.
load
<
io
::
middleman
>
();
actor_system
system
{
cfg
};
auto
client_actor
=
system
.
spawn
(
client
,
name
);
// evaluate group parameters
// evaluate group parameters
if
(
!
group_id
.
empty
())
{
if
(
!
group_id
.
empty
())
{
auto
p
=
group_id
.
find
(
':'
);
auto
p
=
group_id
.
find
(
':'
);
...
@@ -101,14 +98,15 @@ int main(int argc, char** argv) {
...
@@ -101,14 +98,15 @@ int main(int argc, char** argv) {
try
{
try
{
auto
module
=
group_id
.
substr
(
0
,
p
);
auto
module
=
group_id
.
substr
(
0
,
p
);
auto
group_uri
=
group_id
.
substr
(
p
+
1
);
auto
group_uri
=
group_id
.
substr
(
p
+
1
);
auto
g
=
(
module
==
"remote"
)
?
io
::
remote_group
(
group_uri
)
auto
g
=
(
module
==
"remote"
)
:
group
::
get
(
module
,
group_uri
);
?
system
.
middleman
().
remote_group
(
group_uri
)
:
system
.
groups
().
get
(
module
,
group_uri
);
anon_send
(
client_actor
,
join_atom
::
value
,
g
);
anon_send
(
client_actor
,
join_atom
::
value
,
g
);
}
}
catch
(
exception
&
e
)
{
catch
(
exception
&
e
)
{
cerr
<<
"*** exception: group::get(
\"
"
<<
group_id
.
substr
(
0
,
p
)
cerr
<<
"*** exception: group::get(
\"
"
<<
group_id
.
substr
(
0
,
p
)
<<
"
\"
,
\"
"
<<
group_id
.
substr
(
p
+
1
)
<<
"
\"
) failed
;
"
<<
"
\"
,
\"
"
<<
group_id
.
substr
(
p
+
1
)
<<
"
\"
) failed
:
"
<<
to_verbose_string
(
e
)
<<
endl
;
<<
e
.
what
(
)
<<
endl
;
}
}
}
}
}
}
...
@@ -127,12 +125,12 @@ int main(int argc, char** argv) {
...
@@ -127,12 +125,12 @@ int main(int argc, char** argv) {
[
&
](
const
string
&
cmd
,
const
string
&
mod
,
const
string
&
id
)
{
[
&
](
const
string
&
cmd
,
const
string
&
mod
,
const
string
&
id
)
{
if
(
cmd
==
"/join"
)
{
if
(
cmd
==
"/join"
)
{
try
{
try
{
group
grp
=
(
mod
==
"remote"
)
?
io
::
remote_group
(
id
)
group
grp
=
(
mod
==
"remote"
)
?
system
.
middleman
().
remote_group
(
id
)
:
group
::
get
(
mod
,
id
);
:
system
.
groups
().
get
(
mod
,
id
);
anon_send
(
client_actor
,
join_atom
::
value
,
grp
);
anon_send
(
client_actor
,
join_atom
::
value
,
grp
);
}
}
catch
(
exception
&
e
)
{
catch
(
exception
&
e
)
{
cerr
<<
"*** exception: "
<<
to_verbose_string
(
e
)
<<
endl
;
cerr
<<
"*** exception: "
<<
e
.
what
(
)
<<
endl
;
}
}
}
}
else
{
else
{
...
@@ -158,6 +156,5 @@ int main(int argc, char** argv) {
...
@@ -158,6 +156,5 @@ int main(int argc, char** argv) {
}
}
// force actor to quit
// force actor to quit
anon_send_exit
(
client_actor
,
exit_reason
::
user_shutdown
);
anon_send_exit
(
client_actor
,
exit_reason
::
user_shutdown
);
await_all_actors_done
();
system
.
await_all_actors_done
();
shutdown
();
}
}
examples/remote_actors/group_server.cpp
View file @
a3424580
...
@@ -23,50 +23,23 @@ int main(int argc, char** argv) {
...
@@ -23,50 +23,23 @@ int main(int argc, char** argv) {
auto
res
=
message_builder
(
argv
+
1
,
argv
+
argc
).
extract_opts
({
auto
res
=
message_builder
(
argv
+
1
,
argv
+
argc
).
extract_opts
({
{
"port,p"
,
"set port"
,
port
}
{
"port,p"
,
"set port"
,
port
}
});
});
if
(
!
res
.
error
.
empty
())
{
if
(
!
res
.
error
.
empty
())
cerr
<<
res
.
error
<<
endl
;
return
cerr
<<
res
.
error
<<
endl
,
1
;
return
1
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
}
return
cout
<<
res
.
helptext
<<
endl
,
0
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
if
(
!
res
.
remainder
.
empty
())
cout
<<
res
.
helptext
<<
endl
;
return
cerr
<<
"*** too many arguments"
<<
endl
<<
res
.
helptext
<<
endl
,
1
;
return
0
;
if
(
res
.
opts
.
count
(
"port"
)
==
0
||
port
<=
1024
)
}
return
cerr
<<
"*** no valid port given"
<<
endl
<<
res
.
helptext
<<
endl
,
1
;
if
(
!
res
.
remainder
.
empty
())
{
actor_system
system
{
actor_system_config
{}.
load
<
io
::
middleman
>
()};
// not all CLI arguments could be consumed
auto
pres
=
system
.
middleman
().
publish_local_groups
(
port
);
cerr
<<
"*** too many arguments"
<<
endl
<<
res
.
helptext
<<
endl
;
if
(
!
pres
)
return
1
;
return
cerr
<<
"*** error: "
<<
pres
.
error
().
message
()
<<
endl
,
1
;
}
if
(
res
.
opts
.
count
(
"port"
)
==
0
||
port
<=
1024
)
{
cerr
<<
"*** no valid port (>1024) given"
<<
endl
<<
res
.
helptext
<<
endl
;
return
1
;
}
try
{
// try to bind the group server to the given port,
// this allows other nodes to access groups of this server via
// group::get("remote", "<group>@<host>:<port>");
// note: it is not needed to explicitly create a <group> on the server,
// as groups are created on-the-fly on first usage
io
::
publish_local_groups
(
port
);
}
catch
(
bind_failure
&
e
)
{
// thrown if <port> is already in use
cerr
<<
"*** bind_failure: "
<<
e
.
what
()
<<
endl
;
return
2
;
}
catch
(
network_error
&
e
)
{
// thrown on errors in the socket API
cerr
<<
"*** network error: "
<<
e
.
what
()
<<
endl
;
return
2
;
}
cout
<<
"type 'quit' to shutdown the server"
<<
endl
;
cout
<<
"type 'quit' to shutdown the server"
<<
endl
;
string
line
;
string
line
;
while
(
getline
(
cin
,
line
))
{
while
(
getline
(
cin
,
line
))
if
(
line
==
"quit"
)
{
if
(
line
==
"quit"
)
return
0
;
return
0
;
}
else
else
{
cerr
<<
"illegal command"
<<
endl
;
cerr
<<
"illegal command"
<<
endl
;
}
}
shutdown
();
}
}
examples/type_system/announce_3.cpp
deleted
100644 → 0
View file @
c2a66286
#include <utility>
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
std
::
make_pair
;
using
namespace
caf
;
// a simple class using overloaded getter and setter member functions
class
foo
{
int
a_
;
int
b_
;
public:
foo
()
:
a_
(
0
),
b_
(
0
)
{
}
foo
(
int
a0
,
int
b0
)
:
a_
(
a0
),
b_
(
b0
)
{
}
foo
(
const
foo
&
)
=
default
;
foo
&
operator
=
(
const
foo
&
)
=
default
;
int
a
()
const
{
return
a_
;
}
void
a
(
int
val
)
{
a_
=
val
;
}
int
b
()
const
{
return
b_
;
}
void
b
(
int
val
)
{
b_
=
val
;
}
};
// announce requires foo to have the equal operator implemented
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
return
lhs
.
a
()
==
rhs
.
a
()
&&
lhs
.
b
()
==
rhs
.
b
();
}
// a member function pointer to get an attribute of foo
using
foo_getter
=
int
(
foo
::*
)()
const
;
// a member function pointer to set an attribute of foo
using
foo_setter
=
void
(
foo
::*
)(
int
);
void
testee
(
event_based_actor
*
self
)
{
self
->
become
(
[
=
](
const
foo
&
val
)
{
aout
(
self
)
<<
"foo("
<<
val
.
a
()
<<
", "
<<
val
.
b
()
<<
")"
<<
endl
;
self
->
quit
();
}
);
}
int
main
(
int
,
char
**
)
{
// since the member function "a" is ambiguous, the compiler
// also needs a type to select the correct overload
foo_getter
g1
=
&
foo
::
a
;
foo_setter
s1
=
&
foo
::
a
;
// same is true for b
foo_getter
g2
=
&
foo
::
b
;
foo_setter
s2
=
&
foo
::
b
;
// equal to example 3
announce
<
foo
>
(
"foo"
,
make_pair
(
g1
,
s1
),
make_pair
(
g2
,
s2
));
// alternative syntax that uses casts instead of variables
// (returns false since foo is already announced)
announce
<
foo
>
(
"foo"
,
make_pair
(
static_cast
<
foo_getter
>
(
&
foo
::
a
),
static_cast
<
foo_setter
>
(
&
foo
::
a
)),
make_pair
(
static_cast
<
foo_getter
>
(
&
foo
::
b
),
static_cast
<
foo_setter
>
(
&
foo
::
b
)));
// spawn a new testee and send it a foo
{
scoped_actor
self
;
self
->
send
(
spawn
(
testee
),
foo
{
1
,
2
});
}
await_all_actors_done
();
shutdown
();
return
0
;
}
examples/type_system/announce_4.cpp
deleted
100644 → 0
View file @
c2a66286
#include <iostream>
#include "caf/all.hpp"
#include "caf/to_string.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
std
::
make_pair
;
using
namespace
caf
;
// the foo class from example 3
class
foo
{
int
a_
;
int
b_
;
public:
foo
()
:
a_
(
0
),
b_
(
0
)
{
}
foo
(
int
a0
,
int
b0
)
:
a_
(
a0
),
b_
(
b0
)
{
}
foo
(
const
foo
&
)
=
default
;
foo
&
operator
=
(
const
foo
&
)
=
default
;
int
a
()
const
{
return
a_
;
}
void
set_a
(
int
val
)
{
a_
=
val
;
}
int
b
()
const
{
return
b_
;
}
void
set_b
(
int
val
)
{
b_
=
val
;
}
};
// needed for operator==() of bar
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
return
lhs
.
a
()
==
rhs
.
a
()
&&
lhs
.
b
()
==
rhs
.
b
();
}
// simple struct that has foo as a member
struct
bar
{
foo
f
;
int
i
;
};
// announce requires bar to have the equal operator implemented
bool
operator
==
(
const
bar
&
lhs
,
const
bar
&
rhs
)
{
return
lhs
.
f
==
rhs
.
f
&&
lhs
.
i
==
rhs
.
i
;
}
// "worst case" class ... not a good software design at all ;)
class
baz
{
foo
f_
;
public:
bar
b
;
// announce requires a default constructor
baz
()
=
default
;
inline
baz
(
const
foo
&
mf
,
const
bar
&
mb
)
:
f_
(
mf
),
b
(
mb
)
{
}
const
foo
&
f
()
const
{
return
f_
;
}
void
set_f
(
const
foo
&
val
)
{
f_
=
val
;
}
};
// even worst case classes have to implement operator==
bool
operator
==
(
const
baz
&
lhs
,
const
baz
&
rhs
)
{
return
lhs
.
f
()
==
rhs
.
f
()
&&
lhs
.
b
==
rhs
.
b
;
}
// receives `remaining` messages
void
testee
(
event_based_actor
*
self
,
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
self
,
remaining
-
1
);
else
self
->
quit
();
};
self
->
become
(
[
=
](
const
bar
&
val
)
{
aout
(
self
)
<<
"bar(foo("
<<
val
.
f
.
a
()
<<
", "
<<
val
.
f
.
b
()
<<
"), "
<<
val
.
i
<<
")"
<<
endl
;
set_next_behavior
();
},
[
=
](
const
baz
&
val
)
{
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
aout
(
self
)
<<
to_string
(
make_message
(
val
))
<<
endl
;
set_next_behavior
();
}
);
}
int
main
(
int
,
char
**
)
{
// bar has a non-trivial data member f, thus, we have to told
// announce how to serialize/deserialize this member;
// this is was the compound_member function is for;
// it takes a pointer to the non-trivial member as first argument
// followed by all "sub-members" either as member pointer or
// { getter, setter } pair
auto
meta_bar_f
=
[]
{
return
compound_member
(
&
bar
::
f
,
make_pair
(
&
foo
::
a
,
&
foo
::
set_a
),
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
));
};
// with meta_bar_f, we can now announce bar
announce
<
bar
>
(
"bar"
,
meta_bar_f
(),
&
bar
::
i
);
// baz has non-trivial data members with getter/setter pair
// and getter returning a mutable reference
announce
<
baz
>
(
"baz"
,
compound_member
(
make_pair
(
&
baz
::
f
,
&
baz
::
set_f
),
make_pair
(
&
foo
::
a
,
&
foo
::
set_a
),
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
)),
// compound member that has a compound member
compound_member
(
&
baz
::
b
,
meta_bar_f
(),
&
bar
::
i
));
// spawn a testee that receives two messages
auto
t
=
spawn
(
testee
,
size_t
{
2
});
{
scoped_actor
self
;
self
->
send
(
t
,
bar
{
foo
{
1
,
2
},
3
});
self
->
send
(
t
,
baz
{
foo
{
1
,
2
},
bar
{
foo
{
3
,
4
},
5
}});
}
await_all_actors_done
();
shutdown
();
return
0
;
}
examples/type_system/announce_5.cpp
deleted
100644 → 0
View file @
c2a66286
/******************************************************************************
* This example shows how to implement serialize/deserialize to announce *
* non-trivial data structures to the libcaf type system. *
* *
* Announce() auto-detects STL compliant containers and provides *
* an easy way to tell libcaf how to serialize user defined types. *
* See announce_example 1-4 for usage examples. *
* *
* You should use "hand written" serialize/deserialize implementations *
* if and only if there is no other way. *
******************************************************************************/
#include <cstdint>
#include <iostream>
#include "caf/all.hpp"
#include "caf/to_string.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
namespace
caf
;
namespace
{
// a node containing an integer and a vector of children
struct
tree_node
{
std
::
uint32_t
value
;
std
::
vector
<
tree_node
>
children
;
explicit
tree_node
(
std
::
uint32_t
v
=
0
)
:
value
(
v
)
{
// nop
}
tree_node
&
add_child
(
std
::
uint32_t
v
=
0
)
{
children
.
emplace_back
(
v
);
return
*
this
;
}
tree_node
(
const
tree_node
&
)
=
default
;
// recursively print this node and all of its children to stdout
void
print
()
const
{
// format is: value { children0, children1, ..., childrenN }
// e.g., 10 { 20 { 21, 22 }, 30 }
cout
<<
value
;
if
(
children
.
empty
()
==
false
)
{
cout
<<
" { "
;
auto
begin
=
children
.
begin
();
auto
end
=
children
.
end
();
for
(
auto
i
=
begin
;
i
!=
end
;
++
i
)
{
if
(
i
!=
begin
)
{
cout
<<
", "
;
}
i
->
print
();
}
cout
<<
" } "
;
}
}
};
// a very primitive tree implementation
struct
tree
{
tree_node
root
;
// print tree to stdout
void
print
()
const
{
cout
<<
"tree::print: "
;
root
.
print
();
cout
<<
endl
;
}
};
// tree nodes are equals if values and all values of all children are equal
bool
operator
==
(
const
tree_node
&
lhs
,
const
tree_node
&
rhs
)
{
return
(
lhs
.
value
==
rhs
.
value
)
&&
(
lhs
.
children
==
rhs
.
children
);
}
bool
operator
==
(
const
tree
&
lhs
,
const
tree
&
rhs
)
{
return
lhs
.
root
==
rhs
.
root
;
}
// abstract_uniform_type_info implements all functions of uniform_type_info
// except for serialize() and deserialize() if the template parameter T:
// - does have a default constructor
// - does have a copy constructor
// - does provide operator==
class
tree_type_info
:
public
abstract_uniform_type_info
<
tree
>
{
public:
tree_type_info
()
:
abstract_uniform_type_info
<
tree
>
(
"tree"
)
{
// nop
}
protected:
void
serialize
(
const
void
*
ptr
,
serializer
*
sink
)
const
{
// ptr is guaranteed to be a pointer of type tree
auto
tree_ptr
=
reinterpret_cast
<
const
tree
*>
(
ptr
);
// recursively serialize nodes, beginning with root
serialize_node
(
tree_ptr
->
root
,
sink
);
}
void
deserialize
(
void
*
ptr
,
deserializer
*
source
)
const
{
// ptr is guaranteed to be a pointer of type tree
auto
tree_ptr
=
reinterpret_cast
<
tree
*>
(
ptr
);
tree_ptr
->
root
.
children
.
clear
();
// recursively deserialize nodes, beginning with root
deserialize_node
(
tree_ptr
->
root
,
source
);
}
private:
void
serialize_node
(
const
tree_node
&
node
,
serializer
*
sink
)
const
{
// value, ... children ...
sink
->
write_value
(
node
.
value
);
sink
->
begin_sequence
(
node
.
children
.
size
());
for
(
const
tree_node
&
subnode
:
node
.
children
)
{
serialize_node
(
subnode
,
sink
);
}
sink
->
end_sequence
();
}
void
deserialize_node
(
tree_node
&
node
,
deserializer
*
source
)
const
{
// value, ... children ...
auto
value
=
source
->
read
<
std
::
uint32_t
>
();
node
.
value
=
value
;
auto
num_children
=
source
->
begin_sequence
();
for
(
size_t
i
=
0
;
i
<
num_children
;
++
i
)
{
node
.
add_child
();
deserialize_node
(
node
.
children
.
back
(),
source
);
}
source
->
end_sequence
();
}
};
using
tree_vector
=
std
::
vector
<
tree
>
;
// receives `remaining` messages
void
testee
(
event_based_actor
*
self
,
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
self
,
remaining
-
1
);
else
self
->
quit
();
};
self
->
become
(
[
=
](
const
tree
&
tmsg
)
{
// prints the tree in its serialized format:
// @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
cout
<<
"to_string(self->current_message()): "
<<
to_string
(
self
->
current_message
())
<<
endl
;
// prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg
.
print
();
set_next_behavior
();
},
[
=
](
const
tree_vector
&
trees
)
{
// prints "received 2 trees"
cout
<<
"received "
<<
trees
.
size
()
<<
" trees"
<<
endl
;
// prints:
// @<> ( {
// std::vector<tree, std::allocator<tree>> ( {
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ),
// tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } )
// )
// } )
cout
<<
"to_string: "
<<
to_string
(
self
->
current_message
())
<<
endl
;
set_next_behavior
();
}
);
}
}
// namespace <anonymous>
int
main
()
{
// the tree_type_info is owned by libcaf after this function call
announce
(
typeid
(
tree
),
std
::
unique_ptr
<
uniform_type_info
>
{
new
tree_type_info
});
announce
<
tree_vector
>
(
"tree_vector"
);
tree
t0
;
// create a tree and fill it with some data
t0
.
root
.
add_child
(
10
);
t0
.
root
.
children
.
back
().
add_child
(
11
).
add_child
(
12
).
add_child
(
13
);
t0
.
root
.
add_child
(
20
);
t0
.
root
.
children
.
back
().
add_child
(
21
).
add_child
(
22
);
/*
tree t is now:
0
/ \
/ \
/ \
10 20
/ |\ / \
/ | \ / \
11 12 13 21 22
*/
{
// lifetime scope of self
scoped_actor
self
;
// spawn a testee that receives two messages
auto
t
=
spawn
(
testee
,
size_t
{
2
});
// send a tree
self
->
send
(
t
,
t0
);
// send a vector of trees
tree_vector
tvec
;
tvec
.
push_back
(
t0
);
tvec
.
push_back
(
t0
);
self
->
send
(
t
,
tvec
);
}
await_all_actors_done
();
shutdown
();
return
0
;
}
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