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
8ee58b35
Commit
8ee58b35
authored
Apr 03, 2013
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
modified all examples do use event-based API only
parent
b490caff
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
438 additions
and
199 deletions
+438
-199
examples/CMakeLists.txt
examples/CMakeLists.txt
+2
-2
examples/hello_world.cpp
examples/hello_world.cpp
+4
-5
examples/message_passing/calculator.cpp
examples/message_passing/calculator.cpp
+23
-29
examples/remote_actors/distributed_calculator.cpp
examples/remote_actors/distributed_calculator.cpp
+223
-0
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_chat.cpp
+28
-42
examples/remote_actors/group_server.cpp
examples/remote_actors/group_server.cpp
+2
-1
examples/type_system/announce_1.cpp
examples/type_system/announce_1.cpp
+40
-31
examples/type_system/announce_2.cpp
examples/type_system/announce_2.cpp
+15
-12
examples/type_system/announce_3.cpp
examples/type_system/announce_3.cpp
+15
-11
examples/type_system/announce_4.cpp
examples/type_system/announce_4.cpp
+28
-20
examples/type_system/announce_5.cpp
examples/type_system/announce_5.cpp
+58
-46
No files found.
examples/CMakeLists.txt
View file @
8ee58b35
...
...
@@ -17,8 +17,8 @@ add(announce_5 type_system)
add
(
dancing_kirby message_passing
)
add
(
dining_philosophers message_passing
)
add
(
hello_world .
)
add
(
math_ac
tor message_passing
)
add
(
distributed_
math_ac
tor remote_actors
)
add
(
calcula
tor message_passing
)
add
(
distributed_
calcula
tor remote_actors
)
add
(
group_server remote_actors
)
add
(
group_chat remote_actors
)
...
...
examples/hello_world.cpp
View file @
8ee58b35
...
...
@@ -9,8 +9,8 @@ void mirror() {
become
(
// invoke this lambda expression if we receive a string
on_arg_match
>>
[](
const
std
::
string
&
what
)
{
// prints "Hello World!"
std
::
c
out
<<
what
<<
std
::
endl
;
// prints "Hello World!"
via aout (thread-safe wrapper for cout)
a
out
<<
what
<<
std
::
endl
;
// replies "!dlroW olleH"
reply
(
std
::
string
(
what
.
rbegin
(),
what
.
rend
()));
// terminates this actor
...
...
@@ -20,13 +20,13 @@ void mirror() {
}
void
hello_world
(
const
actor_ptr
&
buddy
)
{
// send "Hello World!" to
the mirror
// send "Hello World!" to
our buddy
send
(
buddy
,
"Hello World!"
);
// wait for messages
become
(
on_arg_match
>>
[](
const
std
::
string
&
what
)
{
// prints "!dlroW olleH"
std
::
c
out
<<
what
<<
std
::
endl
;
a
out
<<
what
<<
std
::
endl
;
// terminate this actor
self
->
quit
();
}
...
...
@@ -42,5 +42,4 @@ int main() {
await_all_others_done
();
// run cleanup code before exiting main
shutdown
();
return
0
;
}
examples/message_passing/
math_ac
tor.cpp
→
examples/message_passing/
calcula
tor.cpp
View file @
8ee58b35
...
...
@@ -34,8 +34,7 @@ void blocking_math_fun() {
).
until
(
gref
(
done
));
}
// implementation using the event-based API
void
math_fun
()
{
void
calculator
()
{
// execute this behavior until actor terminates
become
(
on
(
atom
(
"plus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
...
...
@@ -44,43 +43,38 @@ void math_fun() {
on
(
atom
(
"minus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
-
b
);
},
// the [=] capture copies the 'this' pointer into the lambda
// thus, it has access to all members and member functions
on
(
atom
(
"quit"
))
>>
[
=
]
{
on
(
atom
(
"quit"
))
>>
[]
{
// terminate actor with normal exit reason
self
->
quit
();
}
);
}
// utility function
int
fetch_result
(
actor_ptr
&
calculator
,
atom_value
operation
,
int
a
,
int
b
)
{
// send request
send
(
calculator
,
operation
,
a
,
b
);
// wait for result
int
result
;
receive
(
on
<
atom
(
"result"
),
int
>
()
>>
[
&
](
int
r
)
{
result
=
r
;
});
// print and return result
cout
<<
a
<<
" "
<<
to_string
(
operation
)
<<
" "
<<
b
<<
" = "
<<
result
<<
endl
;
return
result
;
void
tester
(
const
actor_ptr
&
testee
)
{
self
->
link_to
(
testee
);
// will be invoked if we receive an unexpected response message
self
->
on_sync_failure
([]
{
aout
<<
"AUT (actor under test) failed"
<<
endl
;
self
->
quit
(
exit_reason
::
user_defined
);
});
// first test: 2 + 1 = 3
sync_send
(
testee
,
atom
(
"plus"
),
2
,
1
).
then
(
on
(
atom
(
"result"
),
3
)
>>
[
=
]
{
// second test: 2 - 1 = 1
sync_send
(
testee
,
atom
(
"minus"
),
2
,
1
).
then
(
on
(
atom
(
"result"
),
1
)
>>
[
=
]
{
// both tests succeeded
aout
<<
"AUT (actor under test) seems to be ok"
<<
endl
;
send
(
testee
,
atom
(
"quit"
));
}
);
}
);
}
int
main
()
{
// spawn a context-switching actor that invokes math_fun
auto
a1
=
spawn
<
blocking_api
>
(
blocking_math_fun
);
// spawn an event-based math actor
auto
a2
=
spawn
(
math_fun
);
// do some testing on both implementations
assert
((
fetch_result
(
a1
,
atom
(
"plus"
),
1
,
2
)
==
3
));
assert
((
fetch_result
(
a2
,
atom
(
"plus"
),
1
,
2
)
==
3
));
assert
((
fetch_result
(
a1
,
atom
(
"minus"
),
2
,
1
)
==
1
));
assert
((
fetch_result
(
a2
,
atom
(
"minus"
),
2
,
1
)
==
1
));
// tell both actors to terminate
send
(
a1
,
atom
(
"quit"
));
send
(
a2
,
atom
(
"quit"
));
// wait until all spawned actors are terminated
spawn
(
tester
,
spawn
(
calculator
));
await_all_others_done
();
// done
shutdown
();
return
0
;
}
...
...
examples/remote_actors/distributed_
math_ac
tor.cpp
→
examples/remote_actors/distributed_
calcula
tor.cpp
View file @
8ee58b35
...
...
@@ -25,186 +25,147 @@ using namespace std;
using
namespace
cppa
;
using
namespace
cppa
::
placeholders
;
// our service provider
struct
math_actor
:
event_based_actor
{
void
init
()
{
// execute this behavior until actor terminates
become
(
on
(
atom
(
"plus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
+
b
);
},
on
(
atom
(
"minus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
-
b
);
},
on
(
atom
(
"quit"
))
>>
[
=
]()
{
quit
();
}
);
}
};
inline
string
&
ltrim
(
string
&
s
)
{
s
.
erase
(
s
.
begin
(),
find_if
(
s
.
begin
(),
s
.
end
(),
[](
char
c
)
{
return
!
isspace
(
c
);
}));
return
s
;
}
inline
string
&
rtrim
(
std
::
string
&
s
)
{
s
.
erase
(
find_if
(
s
.
rbegin
(),
s
.
rend
(),
[](
char
c
)
{
return
!
isspace
(
c
);
}).
base
(),
s
.
end
());
return
s
;
// our "service"
void
calculator
()
{
become
(
on
(
atom
(
"plus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
+
b
);
},
on
(
atom
(
"minus"
),
arg_match
)
>>
[](
int
a
,
int
b
)
{
reply
(
atom
(
"result"
),
a
-
b
);
},
on
(
atom
(
"quit"
))
>>
[
=
]()
{
self
->
quit
();
}
);
}
inline
string
&
trim
(
std
::
string
&
s
)
{
return
ltrim
(
rtrim
(
s
));
inline
string
trim
(
std
::
string
s
)
{
auto
not_space
=
[](
char
c
)
{
return
!
isspace
(
c
);
};
// trim left
s
.
erase
(
s
.
begin
(),
find_if
(
s
.
begin
(),
s
.
end
(),
not_space
));
// trim right
s
.
erase
(
find_if
(
s
.
rbegin
(),
s
.
rend
(),
not_space
).
base
(),
s
.
end
());
return
std
::
move
(
s
);
}
option
<
int
>
toint
(
const
string
&
str
)
{
if
(
str
.
empty
())
return
{};
char
*
endptr
=
nullptr
;
int
result
=
static_cast
<
int
>
(
strtol
(
str
.
c_str
(),
&
endptr
,
10
));
if
(
endptr
!=
nullptr
&&
*
endptr
==
'\0'
)
{
return
result
;
void
client_bhvr
(
const
string
&
host
,
uint16_t
port
,
const
actor_ptr
&
server
)
{
// recover from sync failures by trying to reconnect to server
if
(
!
self
->
has_sync_failure_handler
())
{
self
->
on_sync_failure
([
=
]
{
aout
<<
"*** lost connection to "
<<
host
<<
":"
<<
port
<<
endl
;
client_bhvr
(
host
,
port
,
nullptr
);
});
}
return
{};
}
template
<
typename
T
>
struct
project_helper
;
template
<
>
struct
project_helper
<
string
>
{
template
<
typename
T
>
inline
option
<
T
>
convert
(
const
string
&
from
,
typename
enable_if
<
is_integral
<
T
>::
value
>::
type
*
=
0
)
{
c
har
*
endptr
=
nullptr
;
auto
result
=
static_cast
<
T
>
(
strtol
(
from
.
c_str
(),
&
endptr
,
10
))
;
if
(
endptr
!=
nullptr
&&
*
endptr
==
'\0'
)
return
result
;
return
{};
// connect to server if needed
if
(
!
server
)
{
aout
<<
"*** try to connect to "
<<
host
<<
":"
<<
port
<<
endl
;
try
{
auto
new_serv
=
remote_actor
(
host
,
port
)
;
self
->
monitor
(
new_serv
);
aout
<<
"reconnection succeeded"
<<
endl
;
client_bhvr
(
host
,
port
,
new_serv
);
return
;
}
c
atch
(
exception
&
)
{
aout
<<
"connection failed, try again in 3s"
<<
endl
;
delayed_send
(
self
,
chrono
::
seconds
(
3
),
atom
(
"reconnect"
))
;
}
}
};
template
<
typename
From
,
typename
To
>
option
<
To
>
projection
(
const
From
&
from
)
{
project_helper
<
From
>
f
;
return
f
.
template
convert
<
To
>(
from
);
become
(
on_arg_match
.
when
(
_x1
.
in
({
atom
(
"plus"
),
atom
(
"minus"
)})
&&
gval
(
server
)
!=
nullptr
)
>>
[
=
](
atom_value
op
,
int
lhs
,
int
rhs
)
{
sync_send_tuple
(
server
,
self
->
last_dequeued
()).
then
(
on
(
atom
(
"result"
),
arg_match
)
>>
[
=
](
int
result
)
{
aout
<<
lhs
<<
" "
<<
to_string
(
op
)
<<
" "
<<
rhs
<<
" = "
<<
result
<<
endl
;
}
);
},
on
(
atom
(
"DOWN"
),
arg_match
)
>>
[
=
](
uint32_t
)
{
aout
<<
"*** server down, try to reconnect ..."
<<
endl
;
client_bhvr
(
host
,
port
,
nullptr
);
},
on
(
atom
(
"rebind"
),
arg_match
)
>>
[
=
](
const
string
&
host
,
uint16_t
port
)
{
aout
<<
"*** rebind to new server: "
<<
host
<<
":"
<<
port
<<
endl
;
client_bhvr
(
host
,
port
,
nullptr
);
},
on
(
atom
(
"reconnect"
))
>>
[
=
]
{
client_bhvr
(
host
,
port
,
nullptr
);
}
);
}
void
client_repl
(
actor_ptr
server
,
string
host
,
uint16_t
port
)
{
void
client_repl
(
const
string
&
host
,
uint16_t
port
)
{
typedef
cow_tuple
<
atom_value
,
int
,
int
>
request
;
// keeps track of requests and tries to reconnect on server failures
auto
client
=
factory
::
event_based
([
=
](
actor_ptr
*
serv
,
vector
<
request
>*
q
)
{
self
->
monitor
(
*
serv
);
auto
send_next_request
=
[
=
]
{
if
(
!
q
->
empty
())
{
*
serv
<<
q
->
front
();
}
};
self
->
become
(
on
<
atom_value
,
int
,
int
>
().
when
(
_x1
.
in
({
atom
(
"plus"
),
atom
(
"minus"
)}))
>>
[
=
]
{
if
(
q
->
empty
())
{
*
serv
<<
self
->
last_dequeued
();
}
q
->
push_back
(
*
tuple_cast
<
atom_value
,
int
,
int
>
(
self
->
last_dequeued
()));
},
on
(
atom
(
"result"
),
arg_match
)
>>
[
=
](
int
result
)
{
if
(
q
->
empty
())
{
aout
<<
"received a result, but didn't send a request
\n
"
;
return
;
}
ostringstream
oss
;
auto
&
r
=
q
->
front
();
aout
<<
get
<
1
>
(
r
)
<<
" "
<<
to_string
(
get
<
0
>
(
r
))
<<
" "
<<
get
<
2
>
(
r
)
<<
" = "
<<
result
<<
endl
;
q
->
erase
(
q
->
begin
());
send_next_request
();
},
on
(
atom
(
"DOWN"
),
arg_match
)
>>
[
=
](
uint32_t
reason
)
{
if
(
*
serv
==
self
->
last_sender
())
{
serv
->
reset
();
// sets *serv = nullptr
ostringstream
oss
;
aout
<<
"*** server exited with reason = "
<<
reason
<<
", try to reconnect"
<<
endl
;
send
(
self
,
atom
(
"reconnect"
));
}
},
on
(
atom
(
"reconnect"
))
>>
[
=
]
{
if
(
*
serv
!=
nullptr
)
return
;
try
{
*
serv
=
remote_actor
(
host
,
port
);
self
->
monitor
(
*
serv
);
aout
<<
"reconnection succeeded"
<<
endl
;
send_next_request
();
}
catch
(
exception
&
)
{
delayed_send
(
self
,
chrono
::
seconds
(
3
),
atom
(
"reconnect"
));
}
},
on
(
atom
(
"rebind"
),
arg_match
)
>>
[
=
](
string
&
host
,
uint16_t
port
)
{
actor_ptr
new_serv
;
try
{
new_serv
=
remote_actor
(
move
(
host
),
port
);
self
->
monitor
(
new_serv
);
aout
<<
"rebind succeeded"
<<
endl
;
*
serv
=
new_serv
;
send_next_request
();
}
catch
(
exception
&
e
)
{
aout
<<
"*** rebind failed: "
<<
to_verbose_string
(
e
)
<<
endl
;
}
},
on
(
atom
(
"quit"
))
>>
[
=
]
{
self
->
quit
();
},
others
()
>>
[]
{
aout
<<
"unexpected message: "
<<
self
->
last_dequeued
()
<<
endl
;
}
);
}).
spawn
(
server
);
aout
<<
"quit Quit the program
\n
"
"<x> + <y> Calculate <x>+<y> and print result
\n
"
"<x> - <y> Calculate <x>-<y> and print result
\n
"
"connect <host> <port> Reconfigure server"
<<
endl
;
aout
<<
"Usage:
\n
"
"quit Quit the program
\n
"
"<x> + <y> Calculate <x>+<y> and print result
\n
"
"<x> - <y> Calculate <x>-<y> and print result
\n
"
"connect <host> <port> Reconfigure server"
<<
endl
<<
endl
;
string
line
;
auto
client
=
spawn
(
client_bhvr
,
host
,
port
,
nullptr
);
const
char
connect
[]
=
"connect "
;
while
(
getline
(
cin
,
line
))
{
trim
(
line
);
line
=
trim
(
std
::
move
(
line
));
// ignore leading and trailing whitespaces
if
(
line
==
"quit"
)
{
send
(
client
,
atom
(
"quit"
));
// force client to quit
send_exit
(
client
,
exit_reason
::
user_defined
);
return
;
}
// the STL way of line.starts_with("connect")
else
if
(
equal
(
begin
(
connect
),
end
(
connect
)
-
1
,
begin
(
line
)))
{
match_split
(
line
,
' '
)
(
on
(
"connect"
,
val
<
string
>
,
projection
<
string
,
uint16_t
>
)
>>
[
&
](
string
&
host
,
uint16_t
port
)
{
send
(
client
,
atom
(
"rebind"
),
move
(
host
),
port
);
on
(
"connect"
,
arg_match
)
>>
[
&
](
string
&
host
,
string
&
sport
)
{
try
{
auto
lport
=
std
::
stoul
(
sport
);
if
(
lport
<
std
::
numeric_limits
<
uint16_t
>::
max
())
{
auto
port
=
static_cast
<
uint16_t
>
(
lport
);
send
(
client
,
atom
(
"rebind"
),
move
(
host
),
port
);
}
else
{
aout
<<
lport
<<
" is not a valid port"
<<
endl
;
}
}
catch
(
std
::
exception
&
e
)
{
aout
<<
"
\"
"
<<
sport
<<
"
\"
is not an unsigned integer"
<<
endl
;
}
},
others
()
>>
[]
{
aout
<<
"
illegal host/port definition
"
<<
endl
;
aout
<<
"
*** usage: connect <host> <port>
"
<<
endl
;
}
);
}
else
{
auto
toint
=
[](
const
string
&
str
)
->
option
<
int
>
{
try
{
return
{
std
::
stoi
(
str
)};
}
catch
(
std
::
exception
&
)
{
aout
<<
"
\"
"
<<
str
<<
"
\"
is not an integer"
<<
endl
;
return
{};
}
};
bool
success
=
false
;
auto
pos
=
find_if
(
begin
(
line
),
end
(
line
),
[](
char
c
)
{
return
c
==
'+'
||
c
==
'-'
;
});
if
(
pos
!=
end
(
line
))
{
string
lsub
(
begin
(
line
),
pos
);
string
rsub
(
pos
+
1
,
end
(
line
));
auto
lhs
=
toint
(
trim
(
lsub
));
auto
rhs
=
toint
(
trim
(
rsub
));
auto
first
=
begin
(
line
);
auto
last
=
end
(
line
);
auto
pos
=
find_if
(
first
,
last
,
[](
char
c
)
{
return
c
==
'+'
||
c
==
'-'
;
});
if
(
pos
!=
last
)
{
auto
lsub
=
trim
(
string
(
first
,
pos
));
auto
rsub
=
trim
(
string
(
pos
+
1
,
last
));
auto
lhs
=
toint
(
lsub
);
auto
rhs
=
toint
(
rsub
);
if
(
lhs
&&
rhs
)
{
auto
op
=
(
*
pos
==
'+'
)
?
atom
(
"plus"
)
:
atom
(
"minus"
);
send
(
client
,
op
,
*
lhs
,
*
rhs
);
}
else
{
if
(
!
lhs
)
aout
<<
"
\"
"
+
lsub
+
"
\"
is not an integer"
<<
endl
;
if
(
!
rhs
)
aout
<<
"
\"
"
+
rsub
+
"
\"
is not an integer"
<<
endl
;
}
}
else
if
(
!
success
)
aout
<<
"*** invalid format; use: X +/- Y"
<<
endl
;
else
if
(
!
success
)
{
aout
<<
"*** invalid format; usage: <x> [+|-] <y>"
<<
endl
;
}
}
}
}
...
...
@@ -237,13 +198,14 @@ int main(int argc, char** argv) {
if
(
port
==
0
)
cerr
<<
"*** no port specified"
<<
endl
;
if
(
mode
.
empty
())
cerr
<<
"*** no mode specified"
<<
endl
;
cerr
<<
endl
;
print_desc
(
&
desc
,
cerr
)();
auto
description_printer
=
print_desc
(
&
desc
,
cerr
);
description_printer
();
return
-
1
;
}
if
(
mode
==
"server"
)
{
try
{
// try to publish math actor at given port
publish
(
spawn
<
math_actor
>
(
),
port
);
publish
(
spawn
(
calculator
),
port
);
}
catch
(
exception
&
e
)
{
cerr
<<
"*** unable to publish math actor at port "
<<
port
<<
"
\n
"
...
...
@@ -253,15 +215,7 @@ int main(int argc, char** argv) {
}
else
{
if
(
host
.
empty
())
host
=
"localhost"
;
try
{
auto
server
=
remote_actor
(
host
,
port
);
client_repl
(
server
,
host
,
port
);
}
catch
(
exception
&
e
)
{
cerr
<<
"unable to connect to remote actor at host
\"
"
<<
host
<<
"
\"
on port "
<<
port
<<
"
\n
"
<<
to_verbose_string
(
e
)
<<
endl
;
}
client_repl
(
host
,
port
);
}
await_all_others_done
();
shutdown
();
...
...
examples/remote_actors/group_chat.cpp
View file @
8ee58b35
...
...
@@ -29,7 +29,7 @@ istream& operator>>(istream& is, line& l) {
return
is
;
}
string
s_last_line
;
namespace
{
string
s_last_line
;
}
any_tuple
split_line
(
const
line
&
l
)
{
istringstream
strs
(
l
.
str
);
...
...
@@ -42,46 +42,32 @@ any_tuple split_line(const line& l) {
return
any_tuple
::
view
(
std
::
move
(
result
));
}
class
client
:
public
event_based_actor
{
public:
client
(
string
name
)
:
m_name
(
move
(
name
))
{
}
protected:
void
init
()
{
become
(
on
(
atom
(
"broadcast"
),
arg_match
)
>>
[
=
](
const
string
&
message
)
{
for
(
auto
&
dest
:
joined_groups
())
{
send
(
dest
,
m_name
+
": "
+
message
);
}
},
on
(
atom
(
"join"
),
arg_match
)
>>
[
=
](
const
group_ptr
&
what
)
{
for
(
auto
g
:
joined_groups
())
{
cout
<<
"*** leave "
<<
to_string
(
g
)
<<
endl
;
send
(
g
,
m_name
+
" has left the chatroom"
);
leave
(
g
);
}
cout
<<
"*** join "
<<
to_string
(
what
)
<<
endl
;
join
(
what
);
send
(
what
,
m_name
+
" has entered the chatroom"
);
},
on
<
string
>
()
>>
[
=
](
const
string
&
txt
)
{
// don't print own messages
if
(
last_sender
()
!=
this
)
cout
<<
txt
<<
endl
;
},
others
()
>>
[
=
]()
{
cout
<<
"unexpected: "
<<
to_string
(
last_dequeued
())
<<
endl
;
void
client
(
const
string
&
name
)
{
become
(
on
(
atom
(
"broadcast"
),
arg_match
)
>>
[
=
](
const
string
&
message
)
{
for
(
auto
&
dest
:
self
->
joined_groups
())
{
send
(
dest
,
name
+
": "
+
message
);
}
);
}
private:
string
m_name
;
};
},
on
(
atom
(
"join"
),
arg_match
)
>>
[
=
](
const
group_ptr
&
what
)
{
for
(
auto
g
:
self
->
joined_groups
())
{
cout
<<
"*** leave "
<<
to_string
(
g
)
<<
endl
;
send
(
g
,
name
+
" has left the chatroom"
);
self
->
leave
(
g
);
}
cout
<<
"*** join "
<<
to_string
(
what
)
<<
endl
;
self
->
join
(
what
);
send
(
what
,
name
+
" has entered the chatroom"
);
},
on
<
string
>
()
>>
[
=
](
const
string
&
txt
)
{
// don't print own messages
if
(
self
->
last_sender
()
!=
self
)
cout
<<
txt
<<
endl
;
},
others
()
>>
[
=
]()
{
cout
<<
"unexpected: "
<<
to_string
(
self
->
last_dequeued
())
<<
endl
;
}
);
}
int
main
(
int
argc
,
char
**
argv
)
{
...
...
@@ -105,7 +91,7 @@ int main(int argc, char** argv) {
}
cout
<<
"*** starting client, type '/help' for a list of commands"
<<
endl
;
auto
client_actor
=
spawn
<
client
>
(
name
);
auto
client_actor
=
spawn
(
client
,
name
);
// evaluate group parameters
if
(
!
group_id
.
empty
())
{
...
...
@@ -156,7 +142,7 @@ int main(int argc, char** argv) {
}
);
// force actor to quit
quit_actor
(
client_actor
,
exit_reason
::
user_defined
);
send_exit
(
client_actor
,
exit_reason
::
user_defined
);
await_all_others_done
();
shutdown
();
return
0
;
...
...
examples/remote_actors/group_server.cpp
View file @
8ee58b35
...
...
@@ -30,7 +30,8 @@ int main(int argc, char** argv) {
}
if
(
!
args_valid
)
{
// print_desc(&desc) returns a function printing the stored help text
print_desc
(
&
desc
)();
auto
desc_printer
=
print_desc
(
&
desc
);
desc_printer
();
return
1
;
}
try
{
...
...
examples/type_system/announce_1.cpp
View file @
8ee58b35
...
...
@@ -41,6 +41,38 @@ bool operator==( const foo2& lhs, const foo2& rhs ) {
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
// receives `remaining` messages
void
testee
(
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
remaining
-
1
);
else
self
->
quit
();
};
become
(
// note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int>
on
<
foo_pair
>
()
>>
[
=
](
const
foo_pair
&
val
)
{
cout
<<
"foo_pair("
<<
val
.
first
<<
","
<<
val
.
second
<<
")"
<<
endl
;
set_next_behavior
();
},
on
<
foo
>
()
>>
[
=
](
const
foo
&
val
)
{
cout
<<
"foo({"
;
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
();
}
);
}
int
main
(
int
,
char
**
)
{
// announces foo to the libcppa type system;
...
...
@@ -75,41 +107,18 @@ int main(int, char**) {
// std::pair<int,int> is already announced
assert
(
announce
<
foo_pair2
>
(
&
foo_pair2
::
first
,
&
foo_pair2
::
second
)
==
false
);
// send a foo to ourselves
send
(
self
,
foo
{
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
},
5
});
// send a foo_pair2 to ourselves
send
(
self
,
foo_pair2
{
3
,
4
});
// quits the program
send
(
self
,
atom
(
"done"
));
// libcppa returns the same uniform_type_info
// instance for foo_pair and foo_pair2
assert
(
uniform_typeid
<
foo_pair
>
()
==
uniform_typeid
<
foo_pair2
>
());
// receive two messages
int
i
=
0
;
receive_for
(
i
,
2
)
(
// note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int>
on
<
foo_pair
>
()
>>
[](
const
foo_pair
&
val
)
{
cout
<<
"foo_pair("
<<
val
.
first
<<
","
<<
val
.
second
<<
")"
<<
endl
;
},
on
<
foo
>
()
>>
[](
const
foo
&
val
)
{
cout
<<
"foo({"
;
auto
i
=
val
.
a
.
begin
();
auto
end
=
val
.
a
.
end
();
if
(
i
!=
end
)
{
cout
<<
*
i
;
while
(
++
i
!=
end
)
{
cout
<<
","
<<
*
i
;
}
}
cout
<<
"},"
<<
val
.
b
<<
")"
<<
endl
;
}
);
// spawn a testee that receives two messages
auto
t
=
spawn
(
testee
,
2
);
// send t a foo
send
(
t
,
foo
{
std
::
vector
<
int
>
{
1
,
2
,
3
,
4
},
5
});
// send t a foo_pair2
send
(
t
,
foo_pair2
{
3
,
4
});
await_all_others_done
();
shutdown
();
return
0
;
}
...
...
examples/type_system/announce_2.cpp
View file @
8ee58b35
...
...
@@ -35,29 +35,32 @@ class foo {
};
// announce requires foo to
have the equal operator implemented
// announce requires foo to
be comparable
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
return
lhs
.
a
()
==
rhs
.
a
()
&&
lhs
.
b
()
==
rhs
.
b
();
}
int
main
(
int
,
char
**
)
{
// if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs.
announce
<
foo
>
(
make_pair
(
&
foo
::
a
,
&
foo
::
set_a
),
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
));
// send a foo to ourselves ...
send
(
self
,
foo
{
1
,
2
});
receive
(
// ... and receive it
void
testee
()
{
become
(
on
<
foo
>
()
>>
[](
const
foo
&
val
)
{
c
out
<<
"foo("
a
out
<<
"foo("
<<
val
.
a
()
<<
","
<<
val
.
b
()
<<
")"
<<
endl
;
self
->
quit
();
}
);
}
int
main
(
int
,
char
**
)
{
// if a class uses getter and setter member functions,
// we pass those to the announce function as { getter, setter } pairs.
announce
<
foo
>
(
make_pair
(
&
foo
::
a
,
&
foo
::
set_a
),
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
));
auto
t
=
spawn
(
testee
);
send
(
t
,
foo
{
1
,
2
});
await_all_others_done
();
shutdown
();
return
0
;
}
...
...
examples/type_system/announce_3.cpp
View file @
8ee58b35
...
...
@@ -46,6 +46,18 @@ typedef int (foo::*foo_getter)() const;
// a member function pointer to set an attribute of foo
typedef
void
(
foo
::*
foo_setter
)(
int
);
void
testee
()
{
become
(
on
<
foo
>
()
>>
[](
const
foo
&
val
)
{
aout
<<
"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
...
...
@@ -65,17 +77,9 @@ int main(int, char**) {
make_pair
(
static_cast
<
foo_getter
>
(
&
foo
::
b
),
static_cast
<
foo_setter
>
(
&
foo
::
b
)));
// send a foo to ourselves ...
send
(
self
,
foo
{
1
,
2
});
receive
(
// ... and receive it
on
<
foo
>
()
>>
[](
const
foo
&
val
)
{
cout
<<
"foo("
<<
val
.
a
()
<<
","
<<
val
.
b
()
<<
")"
<<
endl
;
}
);
// spawn a new testee and send it a foo
send
(
spawn
(
testee
),
foo
{
1
,
2
});
await_all_others_done
();
shutdown
();
return
0
;
}
...
...
examples/type_system/announce_4.cpp
View file @
8ee58b35
...
...
@@ -78,6 +78,29 @@ bool operator==(const baz& lhs, const baz& rhs) {
&&
lhs
.
b
==
rhs
.
b
;
}
// receives `remaining` messages
void
testee
(
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
remaining
-
1
);
else
self
->
quit
();
};
become
(
on
<
bar
>
()
>>
[
=
](
const
bar
&
val
)
{
aout
<<
"bar(foo("
<<
val
.
f
.
a
()
<<
","
<<
val
.
f
.
b
()
<<
"),"
<<
val
.
i
<<
")"
<<
endl
;
set_next_behavior
();
},
on
<
baz
>
()
>>
[
=
](
const
baz
&
val
)
{
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
aout
<<
to_string
(
object
::
from
(
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;
...
...
@@ -102,26 +125,11 @@ int main(int, char**) {
make_pair
(
&
foo
::
b
,
&
foo
::
set_b
)),
&
bar
::
i
));
// send a bar to ourselves
send
(
self
,
bar
{
foo
{
1
,
2
},
3
});
// send a baz to ourselves
send
(
self
,
baz
{
foo
{
1
,
2
},
bar
{
foo
{
3
,
4
},
5
}});
// receive two messages
int
i
=
0
;
receive_for
(
i
,
2
)
(
on
<
bar
>
()
>>
[](
const
bar
&
val
)
{
cout
<<
"bar(foo("
<<
val
.
f
.
a
()
<<
","
<<
val
.
f
.
b
()
<<
"),"
<<
val
.
i
<<
")"
<<
endl
;
},
on
<
baz
>
()
>>
[](
const
baz
&
val
)
{
// prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
cout
<<
to_string
(
object
::
from
(
val
))
<<
endl
;
}
);
// spawn a testee that receives two messages
auto
t
=
spawn
(
testee
,
2
);
send
(
t
,
bar
{
foo
{
1
,
2
},
3
});
send
(
t
,
baz
{
foo
{
1
,
2
},
bar
{
foo
{
3
,
4
},
5
}});
await_all_others_done
();
shutdown
();
return
0
;
}
...
...
examples/type_system/announce_5.cpp
View file @
8ee58b35
...
...
@@ -39,18 +39,18 @@ struct tree_node {
void
print
()
const
{
// format is: value { children0, children1, ..., childrenN }
// e.g., 10 { 20 { 21, 22 }, 30 }
c
out
<<
value
;
a
out
<<
value
;
if
(
children
.
empty
()
==
false
)
{
c
out
<<
" { "
;
a
out
<<
" { "
;
auto
begin
=
children
.
begin
();
auto
end
=
children
.
end
();
for
(
auto
i
=
begin
;
i
!=
end
;
++
i
)
{
if
(
i
!=
begin
)
{
c
out
<<
", "
;
a
out
<<
", "
;
}
i
->
print
();
}
c
out
<<
" } "
;
a
out
<<
" } "
;
}
}
...
...
@@ -62,9 +62,9 @@ struct tree {
// print tree to stdout
void
print
()
const
{
c
out
<<
"tree::print: "
;
a
out
<<
"tree::print: "
;
root
.
print
();
c
out
<<
endl
;
a
out
<<
endl
;
}
};
...
...
@@ -138,17 +138,53 @@ class tree_type_info : public util::abstract_uniform_type_info<tree> {
};
typedef
std
::
vector
<
tree
>
tree_vector
;
// receives `remaining` messages
void
testee
(
size_t
remaining
)
{
auto
set_next_behavior
=
[
=
]
{
if
(
remaining
>
1
)
testee
(
remaining
-
1
);
else
self
->
quit
();
};
become
(
on_arg_match
>>
[
=
](
const
tree
&
tmsg
)
{
// prints the tree in its serialized format:
// @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
aout
<<
"to_string(self->last_dequeued()): "
<<
to_string
(
self
->
last_dequeued
())
<<
endl
;
// prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg
.
print
();
set_next_behavior
();
},
on_arg_match
>>
[
=
](
const
tree_vector
&
trees
)
{
// prints "received 2 trees"
aout
<<
"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, { } } } )
// )
// } )
aout
<<
"to_string: "
<<
to_string
(
self
->
last_dequeued
())
<<
endl
;
set_next_behavior
();
}
);
}
int
main
()
{
// the tree_type_info is owned by libcppa after this function call
announce
(
typeid
(
tree
),
new
tree_type_info
);
tree
t
;
// create a tree and fill it with some data
tree
t
0
;
// create a tree and fill it with some data
t
.
root
.
add_child
(
10
);
t
.
root
.
children
.
back
().
add_child
(
11
).
add_child
(
12
).
add_child
(
13
);
t
0
.
root
.
add_child
(
10
);
t
0
.
root
.
children
.
back
().
add_child
(
11
).
add_child
(
12
).
add_child
(
13
);
t
.
root
.
add_child
(
20
);
t
.
root
.
children
.
back
().
add_child
(
21
).
add_child
(
22
);
t
0
.
root
.
add_child
(
20
);
t
0
.
root
.
children
.
back
().
add_child
(
21
).
add_child
(
22
);
/*
tree t is now:
...
...
@@ -162,44 +198,20 @@ int main() {
11 12 13 21 22
*/
// s
end a tree to ourselves ...
send
(
self
,
t
);
// s
pawn a testee that receives two messages
auto
t
=
spawn
(
testee
,
2
);
// send a vector of trees to ourselves
typedef
std
::
vector
<
tree
>
tree_vector
;
// send a tree
send
(
t
,
t0
);
// send a vector of trees
announce
<
tree_vector
>
();
tree_vector
tvec
;
tvec
.
push_back
(
t
);
tvec
.
push_back
(
t
);
send
(
self
,
tvec
);
// receive both messages
int
i
=
0
;
receive_for
(
i
,
2
)
(
// ... and receive it
on
<
tree
>
()
>>
[](
const
tree
&
tmsg
)
{
// prints the tree in its serialized format:
// @<> ( { tree ( 0, { 10, { 11, { }, 12, { }, 13, { } }, 20, { 21, { }, 22, { } } } ) } )
cout
<<
"to_string(self->last_dequeued()): "
<<
to_string
(
self
->
last_dequeued
())
<<
endl
;
// prints the tree using the print member function:
// 0 { 10 { 11, 12, 13 } , 20 { 21, 22 } }
tmsg
.
print
();
},
on
<
tree_vector
>
()
>>
[](
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
->
last_dequeued
())
<<
endl
;
}
);
tvec
.
push_back
(
t0
);
tvec
.
push_back
(
t0
);
send
(
t
,
tvec
);
await_all_others_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