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
765b76a8
Commit
765b76a8
authored
Apr 29, 2016
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update examplesUpdate examples
parent
86da3d35
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
725 additions
and
66 deletions
+725
-66
examples/CMakeLists.txt
examples/CMakeLists.txt
+6
-1
examples/aout.cpp
examples/aout.cpp
+0
-4
examples/composition/behavior_composition.cpp
examples/composition/behavior_composition.cpp
+52
-0
examples/compositions/pipeline.cpp
examples/compositions/pipeline.cpp
+191
-0
examples/custom_types/custom_types_1.cpp
examples/custom_types/custom_types_1.cpp
+3
-13
examples/custom_types/custom_types_2.cpp
examples/custom_types/custom_types_2.cpp
+8
-19
examples/custom_types/custom_types_3.cpp
examples/custom_types/custom_types_3.cpp
+5
-14
examples/dynamic_behavior/dining_philosophers.cpp
examples/dynamic_behavior/dining_philosophers.cpp
+210
-0
examples/dynamic_behavior/skip_messages.cpp
examples/dynamic_behavior/skip_messages.cpp
+50
-0
examples/hello_world.cpp
examples/hello_world.cpp
+1
-3
examples/message_passing/calculator.cpp
examples/message_passing/calculator.cpp
+1
-1
examples/message_passing/cell.cpp
examples/message_passing/cell.cpp
+58
-0
examples/message_passing/delegating.cpp
examples/message_passing/delegating.cpp
+40
-0
examples/message_passing/fixed_stack.cpp
examples/message_passing/fixed_stack.cpp
+94
-0
examples/message_passing/typed_calculator.cpp
examples/message_passing/typed_calculator.cpp
+2
-2
examples/remote_actors/distributed_calculator.cpp
examples/remote_actors/distributed_calculator.cpp
+4
-9
No files found.
examples/CMakeLists.txt
View file @
765b76a8
...
...
@@ -26,7 +26,9 @@ add(custom_types_1 custom_types)
add
(
custom_types_2 custom_types
)
add
(
custom_types_3 custom_types
)
add
(
dancing_kirby message_passing
)
add
(
dining_philosophers message_passing
)
add
(
delegating message_passing
)
add
(
fixed_stack message_passing
)
add
(
cell message_passing
)
add
(
hello_world .
)
add
(
aout .
)
add
(
calculator message_passing
)
...
...
@@ -35,6 +37,9 @@ add(group_server remote_actors)
add
(
group_chat remote_actors
)
add
(
simple_broker brokers
)
add
(
simple_http_broker brokers
)
add
(
dining_philosophers dynamic_behavior
)
add
(
skip_messages dynamic_behavior
)
add
(
behavior_composition composition
)
if
(
NOT CAF_NO_PROTOBUF_EXAMPLES
)
find_package
(
Protobuf
)
...
...
examples/aout.cpp
View file @
765b76a8
/******************************************************************************\
* This example illustrates how to use aout. *
\******************************************************************************/
#include <random>
#include <chrono>
#include <cstdlib>
...
...
examples/composition/behavior_composition.cpp
0 → 100644
View file @
765b76a8
/******************************************************************************\
* This example is a very basic, non-interactive math service implemented *
* using composable states. *
\******************************************************************************/
// This example is partially included in the manual, do not modify
// without updating the references in the *.tex files!
// Manual references: lines 18-50 (Actor.tex)
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
namespace
caf
;
namespace
{
using
add_atom
=
atom_constant
<
atom
(
"add"
)
>
;
using
multiply_atom
=
atom_constant
<
atom
(
"multiply"
)
>
;
using
adder
=
typed_actor
<
replies_to
<
add_atom
,
int
,
int
>::
with
<
int
>>
;
using
multiplier
=
typed_actor
<
replies_to
<
multiply_atom
,
int
,
int
>::
with
<
int
>>
;
using
calculator
=
adder
::
extend_with
<
multiplier
>
;
class
adder_bhvr
:
public
composable_behavior
<
adder
>
{
public:
result
<
int
>
operator
()(
add_atom
,
int
x
,
int
y
)
override
{
return
x
+
y
;
}
};
class
multiplier_bhvr
:
public
composable_behavior
<
multiplier
>
{
public:
result
<
int
>
operator
()(
multiply_atom
,
int
x
,
int
y
)
override
{
return
x
*
y
;
}
};
// calculator_bhvr can be inherited or composed further
using
calculator_bhvr
=
composed_behavior
<
adder_bhvr
,
multiplier_bhvr
>
;
}
// namespace <anonymous>
int
main
()
{
actor_system
system
;
auto
f
=
make_function_view
(
system
.
spawn
<
calculator_bhvr
>
());
cout
<<
"10 + 30 = "
<<
f
(
add_atom
::
value
,
10
,
20
)
<<
endl
;
cout
<<
"7 * 9 = "
<<
f
(
multiply_atom
::
value
,
7
,
9
)
<<
endl
;
}
examples/compositions/pipeline.cpp
0 → 100644
View file @
765b76a8
#include <set>
#include <tuple>
#include <string>
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
endl
;
template
<
class
T
>
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
std
::
tuple
<
T
>&
x
)
{
return
out
<<
std
::
get
<
0
>
(
x
)
<<
endl
;
}
using
namespace
caf
;
namespace
{
void
print_iface
(
const
actor_system
::
uncompressed_message_types_set
&
xs
)
{
cout
<<
"actor {"
<<
endl
;
if
(
xs
.
empty
())
cout
<<
" any -> any"
;
else
for
(
auto
&
x
:
xs
)
cout
<<
" ("
<<
join
(
x
.
first
,
", "
)
<<
") -> ("
<<
join
(
x
.
second
,
", "
)
<<
")"
<<
endl
;
cout
<<
"}"
<<
endl
;
}
using
plus_atom
=
atom_constant
<
atom
(
"plus"
)
>
;
using
minus_atom
=
atom_constant
<
atom
(
"minus"
)
>
;
using
divide_atom
=
atom_constant
<
atom
(
"divide"
)
>
;
using
multiply_atom
=
atom_constant
<
atom
(
"multiply"
)
>
;
using
calculator_actor
=
typed_actor
<
replies_to
<
plus_atom
,
double
,
double
>::
with
<
double
>
,
replies_to
<
minus_atom
,
double
,
double
>::
with
<
double
>
,
replies_to
<
divide_atom
,
double
,
double
>::
with
<
double
>
,
replies_to
<
multiply_atom
,
double
,
double
>::
with
<
double
>>
;
calculator_actor
::
behavior_type
calculator
()
{
return
{
[](
plus_atom
,
double
x
,
double
y
)
{
return
x
+
y
;
},
[](
minus_atom
,
double
x
,
double
y
)
{
return
x
-
y
;
},
[](
divide_atom
,
double
x
,
double
y
)
->
maybe
<
double
>
{
if
(
y
==
0.0
)
return
none
;
return
x
/
y
;
},
[](
multiply_atom
,
double
x
,
double
y
)
{
return
x
*
y
;
}
};
}
using
namespace
caf
::
detail
;
template
<
size_t
I
>
struct
placeholder
{
};
template
<
class
T
,
int
X
=
std
::
is_placeholder
<
T
>
::
value
>
struct
stl_placeholder_to_caf_placeholder_impl
{
using
type
=
placeholder
<
X
-
1
>
;
};
template
<
class
T
>
struct
stl_placeholder_to_caf_placeholder_impl
<
T
,
0
>
{
using
type
=
T
;
};
template
<
class
T
>
struct
stl_placeholder_to_caf_placeholder
:
stl_placeholder_to_caf_placeholder_impl
<
T
>
{
// nop
};
template
<
class
OriginalIns
,
class
Ins
,
class
Binds
,
size_t
I
,
class
...
Ts
>
struct
single_binder_impl
;
// type match in signature
template
<
class
Os
,
class
X
,
class
...
Xs
,
class
...
Ys
,
size_t
I
,
class
...
Ts
>
struct
single_binder_impl
<
Os
,
type_list
<
X
,
Xs
...
>
,
type_list
<
X
,
Ys
...
>
,
I
,
Ts
...
>
:
single_binder_impl
<
Os
,
type_list
<
Xs
...
>
,
type_list
<
Ys
...
>
,
I
+
1
,
Ts
...,
X
>
{
// nop
};
// hit wildcard in bind expression
template
<
class
Os
,
class
X
,
class
...
Xs
,
size_t
Y
,
class
...
Ys
,
size_t
I
,
class
...
Ts
>
struct
single_binder_impl
<
Os
,
type_list
<
X
,
Xs
...
>
,
type_list
<
placeholder
<
Y
>
,
Ys
...
>
,
I
,
Ts
...
>
:
single_binder_impl
<
Os
,
type_list
<
Xs
...
>
,
type_list
<
Ys
...
>
,
I
+
1
,
Ts
...,
typename
tl_at
<
Os
,
Y
>::
type
>
{
// nop
};
// type mismatch between inputs and bind expression (bail out)
template
<
class
Os
,
class
X
,
class
...
Xs
,
class
Y
,
class
...
Ys
,
size_t
I
,
class
...
Ts
>
struct
single_binder_impl
<
Os
,
type_list
<
X
,
Xs
...
>
,
type_list
<
Y
,
Ys
...
>
,
I
,
Ts
...
>
{
using
type
=
void
;
};
// consumed whole bind expression
template
<
class
OriginalIns
,
size_t
I
,
class
...
Ts
>
struct
single_binder_impl
<
OriginalIns
,
type_list
<>
,
type_list
<>
,
I
,
Ts
...
>
{
using
type
=
type_list
<
Ts
...
>
;
};
template
<
class
Inputs
,
class
Outputs
,
class
BindArgs
,
bool
Mismatch
=
tl_size
<
Inputs
>
::
value
!=
tl_size
<
BindArgs
>::
value
>
struct
single_binder
{
using
bound_inputs
=
typename
single_binder_impl
<
Inputs
,
Inputs
,
typename
tl_map
<
BindArgs
,
stl_placeholder_to_caf_placeholder
>::
type
,
0
>::
type
;
using
type
=
typename
std
::
conditional
<
std
::
is_same
<
void
,
bound_inputs
>::
value
,
void
,
typed_mpi
<
bound_inputs
,
Outputs
>
>::
type
;
};
template
<
class
X
,
class
Y
,
class
Z
>
struct
single_binder
<
X
,
Y
,
Z
,
true
>
{
using
type
=
void
;
};
template
<
class
TypedMessagingInterfaceBindArgsPair
>
struct
signle_bind_caller
;
template
<
class
In
,
class
Out
,
class
BindArgs
>
struct
signle_bind_caller
<
type_pair
<
typed_mpi
<
In
,
Out
>
,
BindArgs
>>
:
single_binder
<
In
,
Out
,
BindArgs
>
{};
template
<
class
Signatures
,
class
...
Ts
>
struct
binder
;
template
<
class
...
Ss
,
class
...
Ts
>
struct
binder
<
type_list
<
Ss
...
>
,
Ts
...
>
{
using
bind_args
=
type_list
<
Ts
...
>
;
using
type
=
typename
detail
::
tl_filter_not_type
<
typename
tl_map
<
type_list
<
type_pair
<
Ss
,
bind_args
>
...
>
,
signle_bind_caller
>::
type
,
void
>::
type
;
};
template
<
class
T
,
class
...
Ts
>
int
mybind
(
T
x
,
Ts
...
xs
)
{
typename
binder
<
typename
T
::
signatures
,
Ts
...
>::
type
*
y
=
0
;
cout
<<
typeid
(
decltype
(
*
y
)).
name
()
<<
endl
;
return
42
;
}
}
// namespace <anonymous>
int
main
(
int
argc
,
char
**
argv
)
{
using
namespace
std
::
placeholders
;
actor_system
system
{
argc
,
argv
};
auto
calc
=
system
.
spawn
(
calculator
);
cout
<<
"calc = "
;
print_iface
(
system
.
uncompressed_message_types
(
calc
));
auto
multiplier
=
calc
.
bind
(
multiply_atom
::
value
,
_1
,
_2
);
auto
f
=
make_function_view
(
multiplier
);
cout
<<
"4 * 5 = "
<<
f
(
4.0
,
5.0
)
<<
endl
;
// tell functor to divide instead
f
.
assign
(
calc
.
bind
(
divide_atom
::
value
,
_1
,
_2
));
cout
<<
"4 / 5 = "
<<
f
(
4.0
,
5.0
)
<<
endl
;
// f(x) = x * x * x;
mybind
(
calc
,
multiply_atom
::
value
,
_1
,
_1
);
mybind
(
calc
,
_3
,
_1
,
_2
);
/*
auto g = make_function_adapter(doubler);
cout << "7^2 = " << g(7.0) << endl;
g.reset(doubler * doubler);
cout << "7^3 = " << g(7.0) << endl;
*/
anon_send_exit
(
calc
,
exit_reason
::
kill
);
}
examples/custom_types/custom_types_1.cpp
View file @
765b76a8
...
...
@@ -22,12 +22,7 @@ struct foo {
int
b
;
};
// foo needs to be comparable ...
bool
operator
==
(
const
foo
&
lhs
,
const
foo
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
// ... and to be serializable
// foo needs to be serializable
template
<
class
T
>
void
serialize
(
T
&
in_or_out
,
foo
&
x
,
const
unsigned
int
)
{
in_or_out
&
x
.
a
;
...
...
@@ -52,12 +47,7 @@ struct foo2 {
vector
<
vector
<
double
>>
b
;
};
// foo2 also needs to be comparable ...
bool
operator
==
(
const
foo2
&
lhs
,
const
foo2
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
b
==
rhs
.
b
;
}
// ... and to be serializable
// foo2 also needs to be serializable
template
<
class
T
>
void
serialize
(
T
&
in_or_out
,
foo2
&
x
,
const
unsigned
int
)
{
in_or_out
&
x
.
a
;
...
...
@@ -115,7 +105,7 @@ int main(int, char**) {
binary_deserializer
bd
{
system
,
buf
};
bd
>>
f2
;
// must be equal
assert
(
f1
==
f2
);
assert
(
to_string
(
f1
)
==
to_string
(
f2
)
);
// spawn a testee that receives two messages of user-defined type
auto
t
=
system
.
spawn
(
testee
,
2
);
scoped_actor
self
{
system
};
...
...
examples/custom_types/custom_types_2.cpp
View file @
765b76a8
...
...
@@ -38,19 +38,12 @@ public:
b_
=
val
;
}
// compare
friend
bool
operator
==
(
const
foo
&
x
,
const
foo
&
y
)
{
return
x
.
a_
==
y
.
a_
&&
x
.
b_
==
y
.
b_
;
template
<
class
Processor
>
friend
void
serialize
(
Processor
&
proc
,
foo
&
x
,
const
unsigned
int
)
{
proc
&
x
.
a_
;
proc
&
x
.
b_
;
}
// serialize
template
<
class
T
>
friend
void
serialize
(
T
&
in_or_out
,
foo
&
x
,
const
unsigned
int
)
{
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_
));
}
...
...
@@ -60,21 +53,17 @@ private:
int
b_
;
};
void
testee
(
event_based_actor
*
self
)
{
self
->
become
(
behavior
testee
(
event_based_actor
*
self
)
{
return
{
[
=
](
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
();
anon_send
(
system
.
spawn
(
testee
),
foo
{
1
,
2
});
}
examples/custom_types/custom_types_3.cpp
View file @
765b76a8
...
...
@@ -44,12 +44,7 @@ private:
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, ...
// to_string is straightforward ...
std
::
string
to_string
(
const
foo
&
x
)
{
return
"foo"
+
deep_to_string
(
std
::
forward_as_tuple
(
x
.
a
(),
x
.
b
()));
}
...
...
@@ -72,21 +67,17 @@ serialize(T& in, foo& x, const unsigned int) {
x
.
set_b
(
tmp
);
}
void
testee
(
event_based_actor
*
self
)
{
self
->
become
(
behavior
testee
(
event_based_actor
*
self
)
{
return
{
[
=
](
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
();
anon_send
(
system
.
spawn
(
testee
),
foo
{
1
,
2
});
}
examples/dynamic_behavior/dining_philosophers.cpp
0 → 100644
View file @
765b76a8
/******************************************************************************\
* This example is an implementation of the classical Dining Philosophers *
* exercise using only libcaf's event-based actor implementation. *
\ ******************************************************************************/
#include <map>
#include <thread>
#include <vector>
#include <chrono>
#include <sstream>
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
cerr
;
using
std
::
endl
;
using
std
::
chrono
::
seconds
;
using
namespace
caf
;
namespace
{
// atoms for chopstick interface
using
put_atom
=
atom_constant
<
atom
(
"put"
)
>
;
using
take_atom
=
atom_constant
<
atom
(
"take"
)
>
;
using
taken_atom
=
atom_constant
<
atom
(
"taken"
)
>
;
// atoms for philosopher interface
using
eat_atom
=
atom_constant
<
atom
(
"eat"
)
>
;
using
think_atom
=
atom_constant
<
atom
(
"think"
)
>
;
// a chopstick
using
chopstick
=
typed_actor
<
replies_to
<
take_atom
>::
with
<
taken_atom
,
bool
>
,
reacts_to
<
put_atom
>>
;
chopstick
::
behavior_type
taken_chopstick
(
chopstick
::
pointer
self
,
actor_addr
);
// either taken by a philosopher or available
chopstick
::
behavior_type
available_chopstick
(
chopstick
::
pointer
self
)
{
return
{
[
=
](
take_atom
)
->
std
::
tuple
<
taken_atom
,
bool
>
{
self
->
become
(
taken_chopstick
(
self
,
self
->
current_sender
()));
return
std
::
make_tuple
(
taken_atom
::
value
,
true
);
},
[](
put_atom
)
{
cerr
<<
"chopstick received unexpected 'put'"
<<
endl
;
}
};
}
chopstick
::
behavior_type
taken_chopstick
(
chopstick
::
pointer
self
,
actor_addr
user
)
{
return
{
[](
take_atom
)
->
std
::
tuple
<
taken_atom
,
bool
>
{
return
std
::
make_tuple
(
taken_atom
::
value
,
false
);
},
[
=
](
put_atom
)
{
if
(
self
->
current_sender
()
==
user
)
self
->
become
(
available_chopstick
(
self
));
}
};
}
/* Based on: http://www.dalnefre.com/wp/2010/08/dining-philosophers-in-humus/
*
*
* +-------------+ {busy|taken}
* /-------->| thinking |<------------------\
* | +-------------+ |
* | | |
* | | {eat} |
* | | |
* | V |
* | +-------------+ {busy} +-------------+
* | | hungry |----------->| denied |
* | +-------------+ +-------------+
* | |
* | | {taken}
* | |
* | V
* | +-------------+
* | | granted |
* | +-------------+
* | | |
* | {busy} | | {taken}
* \-----------/ |
* | V
* | {think} +-------------+
* \---------| eating |
* +-------------+
*/
class
philosopher
:
public
event_based_actor
{
public:
philosopher
(
actor_config
&
cfg
,
const
std
::
string
&
n
,
const
chopstick
&
l
,
const
chopstick
&
r
)
:
event_based_actor
(
cfg
),
name_
(
n
),
left_
(
l
),
right_
(
r
)
{
// we only accept one message per state and skip others in the meantime
set_default_handler
(
skip
);
// a philosopher that receives {eat} stops thinking and becomes hungry
thinking_
.
assign
(
[
=
](
eat_atom
)
{
become
(
hungry_
);
send
(
left_
,
take_atom
::
value
);
send
(
right_
,
take_atom
::
value
);
}
);
// wait for the first answer of a chopstick
hungry_
.
assign
(
[
=
](
taken_atom
,
bool
result
)
{
if
(
result
)
become
(
granted_
);
else
become
(
denied_
);
}
);
// philosopher was able to obtain the first chopstick
granted_
.
assign
(
[
=
](
taken_atom
,
bool
result
)
{
if
(
result
)
{
aout
(
this
)
<<
name_
<<
" has picked up chopsticks with IDs "
<<
left_
->
id
()
<<
" and "
<<
right_
->
id
()
<<
" and starts to eat
\n
"
;
// eat some time
delayed_send
(
this
,
seconds
(
5
),
think_atom
::
value
);
become
(
eating_
);
}
else
{
send
(
current_sender
()
==
left_
?
right_
:
left_
,
put_atom
::
value
);
send
(
this
,
eat_atom
::
value
);
become
(
thinking_
);
}
}
);
// philosopher was *not* able to obtain the first chopstick
denied_
.
assign
(
[
=
](
taken_atom
,
bool
result
)
{
if
(
result
)
send
(
current_sender
()
==
left_
?
left_
:
right_
,
put_atom
::
value
);
send
(
this
,
eat_atom
::
value
);
become
(
thinking_
);
}
);
// philosopher obtained both chopstick and eats (for five seconds)
eating_
.
assign
(
[
=
](
think_atom
)
{
send
(
left_
,
put_atom
::
value
);
send
(
right_
,
put_atom
::
value
);
delayed_send
(
this
,
seconds
(
5
),
eat_atom
::
value
);
aout
(
this
)
<<
name_
<<
" puts down his chopsticks and starts to think
\n
"
;
become
(
thinking_
);
}
);
}
const
char
*
name
()
const
override
{
return
name_
.
c_str
();
}
protected:
behavior
make_behavior
()
override
{
// start thinking
send
(
this
,
think_atom
::
value
);
// philosophers start to think after receiving {think}
return
(
[
=
](
think_atom
)
{
aout
(
this
)
<<
name_
<<
" starts to think
\n
"
;
delayed_send
(
this
,
seconds
(
5
),
eat_atom
::
value
);
become
(
thinking_
);
}
);
}
private:
std
::
string
name_
;
// the name of this philosopher
chopstick
left_
;
// left chopstick
chopstick
right_
;
// right chopstick
behavior
thinking_
;
// initial behavior
behavior
hungry_
;
// tries to take chopsticks
behavior
granted_
;
// has one chopstick and waits for the second one
behavior
denied_
;
// could not get first chopsticks
behavior
eating_
;
// wait for some time, then go thinking again
};
}
// namespace <anonymous>
int
main
(
int
,
char
**
)
{
actor_system
system
;
scoped_actor
self
{
system
};
// create five chopsticks
aout
(
self
)
<<
"chopstick ids are:"
;
std
::
vector
<
chopstick
>
chopsticks
;
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
{
chopsticks
.
push_back
(
self
->
spawn
(
available_chopstick
));
aout
(
self
)
<<
" "
<<
chopsticks
.
back
()
->
id
();
}
aout
(
self
)
<<
endl
;
// spawn five philosophers
std
::
vector
<
std
::
string
>
names
{
"Plato"
,
"Hume"
,
"Kant"
,
"Nietzsche"
,
"Descartes"
};
for
(
size_t
i
=
0
;
i
<
5
;
++
i
)
self
->
spawn
<
philosopher
>
(
names
[
i
],
chopsticks
[
i
],
chopsticks
[(
i
+
1
)
%
5
]);
}
examples/dynamic_behavior/skip_messages.cpp
0 → 100644
View file @
765b76a8
#include "caf/all.hpp"
using
namespace
caf
;
using
idle_atom
=
atom_constant
<
atom
(
"idle"
)
>
;
using
request_atom
=
atom_constant
<
atom
(
"request"
)
>
;
using
response_atom
=
atom_constant
<
atom
(
"response"
)
>
;
behavior
server
(
event_based_actor
*
self
)
{
return
{
[
=
](
idle_atom
,
const
actor
&
worker
)
{
self
->
become
(
keep_behavior
,
[
=
](
request_atom
atm
)
{
self
->
delegate
(
worker
,
atm
);
self
->
unbecome
();
},
[
=
](
idle_atom
)
{
return
skip
();
}
);
},
[
=
](
request_atom
)
{
return
skip
();
}
};
}
behavior
client
(
event_based_actor
*
self
,
const
actor
&
serv
)
{
self
->
link_to
(
serv
);
self
->
send
(
serv
,
idle_atom
::
value
,
self
);
return
{
[
=
](
request_atom
)
{
self
->
send
(
serv
,
idle_atom
::
value
,
self
);
return
response_atom
::
value
;
}
};
}
int
main
()
{
actor_system
system
;
auto
serv
=
system
.
spawn
(
server
);
auto
worker
=
system
.
spawn
(
client
,
serv
);
scoped_actor
self
{
system
};
self
->
request
(
serv
,
std
::
chrono
::
seconds
(
10
),
request_atom
::
value
).
receive
([
&
](
response_atom
)
{
aout
(
self
)
<<
"received response from "
<<
(
self
->
current_sender
()
==
worker
?
"worker
\n
"
:
"server
\n
"
);
});
self
->
send_exit
(
serv
,
exit_reason
::
user_shutdown
);
}
examples/hello_world.cpp
View file @
765b76a8
...
...
@@ -16,8 +16,6 @@ behavior mirror(event_based_actor* self) {
[
=
](
const
string
&
what
)
->
string
{
// prints "Hello World!" via aout (thread-safe cout wrapper)
aout
(
self
)
<<
what
<<
endl
;
// terminates this actor ('become' otherwise loops forever)
self
->
quit
();
// reply "!dlroW olleH"
return
string
(
what
.
rbegin
(),
what
.
rend
());
}
...
...
@@ -42,5 +40,5 @@ int main() {
auto
mirror_actor
=
system
.
spawn
(
mirror
);
// create another actor that calls 'hello_world(mirror_actor)';
system
.
spawn
(
hello_world
,
mirror_actor
);
// system will wait until both actors are d
one
before leaving main
// system will wait until both actors are d
estroyed
before leaving main
}
examples/message_passing/calculator.cpp
View file @
765b76a8
...
...
@@ -5,7 +5,7 @@
// This example is partially included in the manual, do not modify
// without updating the references in the *.tex files!
// Manual references: lines 17-21,
24-26, 28-68, 70-104, and 137-143
(Actor.tex)
// Manual references: lines 17-21,
31-65, 67-101, and 135-140
(Actor.tex)
#include <iostream>
...
...
examples/message_passing/cell.cpp
0 → 100644
View file @
765b76a8
/******************************************************************************\
* This example is a very basic, non-interactive math service implemented *
* for both the blocking and the event-based API. *
\******************************************************************************/
// This example is partially included in the manual, do not modify
// without updating the references in the *.tex files!
// Manual references: lines 18-44, and 50-51 (Actor.tex)
#include <iostream>
#include "caf/all.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
namespace
caf
;
using
cell
=
typed_actor
<
reacts_to
<
put_atom
,
int
>
,
replies_to
<
get_atom
>::
with
<
int
>>
;
struct
cell_state
{
int
value
=
0
;
};
cell
::
behavior_type
type_checked_cell
(
cell
::
stateful_pointer
<
cell_state
>
self
)
{
return
{
[
=
](
put_atom
,
int
val
)
{
self
->
state
.
value
=
val
;
},
[
=
](
get_atom
)
{
return
self
->
state
.
value
;
}
};
}
behavior
unchecked_cell
(
stateful_actor
<
cell_state
>*
self
)
{
return
{
[
=
](
put_atom
,
int
val
)
{
self
->
state
.
value
=
val
;
},
[
=
](
get_atom
)
{
return
self
->
state
.
value
;
}
};
}
int
main
()
{
actor_system
system
;
// create one cell for each implementation
auto
cell1
=
system
.
spawn
(
type_checked_cell
);
auto
cell2
=
system
.
spawn
(
unchecked_cell
);
auto
f
=
make_function_view
(
cell1
);
cout
<<
"cell value: "
<<
f
(
get_atom
::
value
)
<<
endl
;
f
(
put_atom
::
value
,
20
);
cout
<<
"cell value (after setting to 20): "
<<
f
(
get_atom
::
value
)
<<
endl
;
// get an unchecked cell and send it some garbage
anon_send
(
cell2
,
"hello there!"
);
}
examples/message_passing/delegating.cpp
0 → 100644
View file @
765b76a8
#include <iostream>
#include "caf/all.hpp"
using
std
::
endl
;
using
namespace
caf
;
using
add_atom
=
atom_constant
<
atom
(
"add"
)
>
;
using
calc
=
typed_actor
<
replies_to
<
add_atom
,
int
,
int
>::
with
<
int
>>
;
void
actor_a
(
event_based_actor
*
self
,
calc
worker
)
{
self
->
request
(
worker
,
std
::
chrono
::
seconds
(
10
),
add_atom
::
value
,
1
,
2
).
then
(
[
=
](
int
result
)
{
aout
(
self
)
<<
"1 + 2 = "
<<
result
<<
endl
;
self
->
send_exit
(
worker
,
exit_reason
::
user_shutdown
);
}
);
}
calc
::
behavior_type
actor_b
(
calc
::
pointer
self
,
calc
worker
)
{
self
->
link_to
(
worker
);
return
{
[
=
](
add_atom
add
,
int
x
,
int
y
)
{
return
self
->
delegate
(
worker
,
add
,
x
,
y
);
}
};
}
calc
::
behavior_type
actor_c
()
{
return
{
[](
add_atom
,
int
x
,
int
y
)
{
return
x
+
y
;
}
};
}
int
main
()
{
actor_system
system
;
system
.
spawn
(
actor_a
,
system
.
spawn
(
actor_b
,
system
.
spawn
(
actor_c
)));
}
examples/message_passing/fixed_stack.cpp
0 → 100644
View file @
765b76a8
#include <cstdint>
#include <iostream>
#include "caf/all.hpp"
using
std
::
endl
;
using
namespace
caf
;
using
pop_atom
=
atom_constant
<
atom
(
"pop"
)
>
;
using
push_atom
=
atom_constant
<
atom
(
"push"
)
>
;
enum
class
fixed_stack_errc
:
uint8_t
{
push_to_full
=
1
,
pop_from_empty
};
error
make_error
(
fixed_stack_errc
x
)
{
return
error
{
static_cast
<
uint8_t
>
(
x
),
atom
(
"FixedStack"
)};
}
class
fixed_stack
:
public
event_based_actor
{
public:
fixed_stack
(
actor_config
&
cfg
,
size_t
stack_size
)
:
event_based_actor
(
cfg
),
size_
(
stack_size
)
{
full_
.
assign
(
[
=
](
push_atom
,
int
)
->
error
{
return
fixed_stack_errc
::
push_to_full
;
},
[
=
](
pop_atom
)
->
int
{
auto
result
=
data_
.
back
();
data_
.
pop_back
();
become
(
filled_
);
return
result
;
}
);
filled_
.
assign
(
[
=
](
push_atom
,
int
what
)
{
data_
.
push_back
(
what
);
if
(
data_
.
size
()
==
size_
)
become
(
full_
);
},
[
=
](
pop_atom
)
->
int
{
auto
result
=
data_
.
back
();
data_
.
pop_back
();
if
(
data_
.
empty
())
become
(
empty_
);
return
result
;
}
);
empty_
.
assign
(
[
=
](
push_atom
,
int
what
)
{
data_
.
push_back
(
what
);
become
(
filled_
);
},
[
=
](
pop_atom
)
->
error
{
return
fixed_stack_errc
::
pop_from_empty
;
}
);
}
behavior
make_behavior
()
override
{
if
(
size_
<
2
)
throw
std
::
runtime_error
(
"size < 2 is not supported for fixed_stack"
);
return
empty_
;
}
private:
size_t
size_
;
std
::
vector
<
int
>
data_
;
behavior
full_
;
behavior
filled_
;
behavior
empty_
;
};
int
main
()
{
actor_system
system
;
auto
st
=
system
.
spawn
<
fixed_stack
>
(
5
);
scoped_actor
self
{
system
};
// fill stack
for
(
int
i
=
0
;
i
<
10
;
++
i
)
self
->
send
(
st
,
push_atom
::
value
,
i
);
// drain stack
aout
(
self
)
<<
"stack: { "
;
bool
stack_empty
=
false
;
while
(
!
stack_empty
)
{
self
->
request
(
st
,
std
::
chrono
::
seconds
(
10
),
pop_atom
::
value
).
receive
(
[
&
](
int
x
)
{
aout
(
self
)
<<
x
<<
" "
;
},
[
&
](
const
error
&
)
{
stack_empty
=
true
;
}
);
}
aout
(
self
)
<<
"}"
<<
endl
;
self
->
send_exit
(
st
,
exit_reason
::
user_shutdown
);
}
examples/message_passing/typed_calculator.cpp
View file @
765b76a8
...
...
@@ -20,7 +20,7 @@ using calculator_type =
typed_actor
<
replies_to
<
plus_atom
,
int
,
int
>::
with
<
result_atom
,
int
>
,
replies_to
<
minus_atom
,
int
,
int
>::
with
<
result_atom
,
int
>>
;
calculator_type
::
behavior_type
typed_calculator
(
calculator_type
::
pointer
)
{
calculator_type
::
behavior_type
typed_calculator
_fun
(
calculator_type
::
pointer
)
{
return
{
[](
plus_atom
,
int
x
,
int
y
)
{
return
std
::
make_tuple
(
result_atom
::
value
,
x
+
y
);
...
...
@@ -79,7 +79,7 @@ void tester(event_based_actor* self, const calculator_type& testee) {
int
main
()
{
actor_system
system
;
// test function-based impl
system
.
spawn
(
tester
,
system
.
spawn
(
typed_calculator
));
system
.
spawn
(
tester
,
system
.
spawn
(
typed_calculator
_fun
));
system
.
await_all_actors_done
();
// test class-based impl
system
.
spawn
(
tester
,
system
.
spawn
<
typed_calculator_class
>
());
...
...
examples/remote_actors/distributed_calculator.cpp
View file @
765b76a8
...
...
@@ -38,7 +38,7 @@ using rebind_atom = atom_constant<atom("rebind")>;
using
reconnect_atom
=
atom_constant
<
atom
(
"reconnect"
)
>
;
// our "service"
behavior
calculator
()
{
behavior
calculator
_fun
()
{
return
{
[](
plus_atom
,
int
a
,
int
b
)
->
message
{
return
make_message
(
result_atom
::
value
,
a
+
b
);
...
...
@@ -55,7 +55,7 @@ public:
:
event_based_actor
(
cfg
),
host_
(
std
::
move
(
hostaddr
)),
port_
(
port
)
{
// nop
set_default_handler
(
skip
);
}
behavior
make_behavior
()
override
{
...
...
@@ -105,8 +105,6 @@ private:
}
behavior
reconnecting
(
std
::
function
<
void
()
>
continuation
=
nullptr
)
{
return
{};
/* TODO: implement me
using
std
::
chrono
::
seconds
;
auto
mm
=
system
().
middleman
().
actor_handle
();
send
(
mm
,
connect_atom
::
value
,
host_
,
port_
);
...
...
@@ -151,11 +149,8 @@ private:
send_mm
();
}
);
},
// simply ignore all requests until we have a connection
others >> skip
}
};
*/
}
actor
server_
;
...
...
@@ -283,7 +278,7 @@ int main(int argc, char** argv) {
cfg
.
load
<
io
::
middleman
>
();
actor_system
system
{
cfg
};
if
(
is_server
)
{
auto
calc
=
system
.
spawn
(
calculator
);
auto
calc
=
system
.
spawn
(
calculator
_fun
);
// try to publish math actor at given port
cout
<<
"*** try publish at port "
<<
port
<<
endl
;
auto
p
=
system
.
middleman
().
publish
(
calc
,
port
);
...
...
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