Commit 765b76a8 authored by Dominik Charousset's avatar Dominik Charousset

Update examplesUpdate examples

parent 86da3d35
......@@ -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)
......
/******************************************************************************\
* This example illustrates how to use aout. *
\******************************************************************************/
#include <random>
#include <chrono>
#include <cstdlib>
......
/******************************************************************************\
* 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;
}
#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);
}
......@@ -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};
......
......@@ -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});
}
......@@ -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});
}
/******************************************************************************\
* 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]);
}
#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);
}
......@@ -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 done before leaving main
// system will wait until both actors are destroyed before leaving main
}
......@@ -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>
......
/******************************************************************************\
* 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!");
}
#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)));
}
#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);
}
......@@ -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>());
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment