Commit 8f523243 authored by Dominik Charousset's avatar Dominik Charousset

Provide new CAF_MAIN convenience API

parent 037450b4
...@@ -185,7 +185,7 @@ TAB_SIZE = 2 ...@@ -185,7 +185,7 @@ TAB_SIZE = 2
# will result in a user-defined paragraph with heading "Side Effects:". # will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines. # You can put \n's in the value part of an alias to insert newlines.
ALIASES = ALIASES = experimental="@attention This feature is **experimental**."
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C. # sources only. Doxygen will then generate output that is more tailored for C.
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
#include <iostream> #include <iostream>
#include "caf/all.hpp" #include "caf/all.hpp"
#include "caf/io/all.hpp"
using namespace caf; using namespace caf;
using std::endl; using std::endl;
int main() { void caf_main(actor_system& system) {
actor_system system;
for (int i = 1; i <= 50; ++i) { for (int i = 1; i <= 50; ++i) {
system.spawn([i](blocking_actor* self) { system.spawn([i](blocking_actor* self) {
aout(self) << "Hi there! This is actor nr. " aout(self) << "Hi there! This is actor nr. "
...@@ -27,3 +27,5 @@ int main() { ...@@ -27,3 +27,5 @@ int main() {
}); });
} }
} }
CAF_MAIN()
...@@ -179,46 +179,36 @@ optional<uint16_t> as_u16(const std::string& str) { ...@@ -179,46 +179,36 @@ optional<uint16_t> as_u16(const std::string& str) {
return static_cast<uint16_t>(stoul(str)); return static_cast<uint16_t>(stoul(str));
} }
int main(int argc, char** argv) { class config : public actor_system_config {
using std::string; public:
actor_system_config cfg{argc, argv};
if (cfg.cli_helptext_printed)
return 0;
cfg.load<io::middleman>();
uint16_t port = 0; uint16_t port = 0;
string host = "localhost"; std::string host = "localhost";
auto res = cfg.args_remainder.extract_opts({ bool server_mode = false;
{"server,s", "run in server mode"},
{"client,c", "run in client mode"}, void init() override {
{"port,p", "set port", port}, opt_group{custom_options_, "global"}
{"host,H", "set host (client mode only)", host} .add(port, "port,p", "set port")
}); .add(host, "host,H", "set host (ignored in server mode)")
if (! res.error.empty()) .add(server_mode, "server-mode,s", "enable server mode");
return cerr << res.error << endl, 1; }
if (res.opts.count("help") > 0) };
return cout << res.helptext << endl, 0;
if (! res.remainder.empty()) void caf_main(actor_system& system, config& cfg) {
// not all CLI arguments could be consumed if (cfg.server_mode) {
return cerr << "*** too many arguments" << endl << res.helptext << endl, 1;
if (res.opts.count("port") == 0)
return cerr << "*** no port given" << endl << res.helptext << endl, 1;
actor_system system{cfg};
if (res.opts.count("server") > 0) {
cout << "run in server mode" << endl; cout << "run in server mode" << endl;
auto pong_actor = system.spawn(pong); auto pong_actor = system.spawn(pong);
auto server_actor = system.middleman().spawn_server(server, port, pong_actor); auto server_actor = system.middleman().spawn_server(server, cfg.port,
pong_actor);
print_on_exit(server_actor, "server"); print_on_exit(server_actor, "server");
print_on_exit(pong_actor, "pong"); print_on_exit(pong_actor, "pong");
} else if (res.opts.count("client") > 0) { return;
auto ping_actor = system.spawn(ping, size_t{20});
auto io_actor = system.middleman().spawn_client(broker_impl, host,
port, ping_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 {
cerr << "*** neither client nor server mode set" << endl
<< res.helptext << endl;
return 1;
} }
auto ping_actor = system.spawn(ping, size_t{20});
auto io_actor = system.middleman().spawn_client(broker_impl, cfg.host,
cfg.port, ping_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);
} }
CAF_MAIN(io::middleman)
...@@ -64,39 +64,25 @@ behavior server(broker* self) { ...@@ -64,39 +64,25 @@ behavior server(broker* self) {
}; };
} }
optional<uint16_t> as_u16(const std::string& str) { class config : public actor_system_config {
return static_cast<uint16_t>(stoul(str)); public:
}
int main(int argc, const char** argv) {
uint16_t port = 0; uint16_t port = 0;
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"port,p", "set port", port}, void init() override {
}); opt_group{custom_options_, "global"}
if (! res.error.empty()) { .add(port, "port,p", "set port");
cerr << res.error << endl;
return 1;
}
if (res.opts.count("help") > 0) {
cout << res.helptext << endl;
return 0;
}
if (! res.remainder.empty()) {
// not all CLI arguments could be consumed
cerr << "*** too many arguments" << endl << res.helptext << endl;
return 1;
}
if (res.opts.count("port") == 0) {
cerr << "*** no port given" << endl << res.helptext << endl;
return 1;
} }
cout << "*** run in server mode listen on: " << port << endl; };
void caf_main(actor_system& system, config& cfg) {
cout << "*** run in server mode listen on: " << cfg.port << endl;
cout << "*** to quit the program, simply press <enter>" << endl; cout << "*** to quit the program, simply press <enter>" << endl;
actor_system system; auto server_actor = system.middleman().spawn_server(server, cfg.port);
auto server_actor = system.middleman().spawn_server(server, port);
// 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);
} }
CAF_MAIN(io::middleman)
...@@ -22,6 +22,8 @@ profiling-output-file="/dev/null" ...@@ -22,6 +22,8 @@ profiling-output-file="/dev/null"
enable-automatic-connections=false enable-automatic-connections=false
; accepted alternative: 'asio' (only when compiling CAF with ASIO) ; accepted alternative: 'asio' (only when compiling CAF with ASIO)
network-backend='default' network-backend='default'
; heartbeat message interval in ms (0 disables heartbeating)
heartbeat-interval=0
; when loading riac::probe ; when loading riac::probe
[probe] [probe]
......
...@@ -42,9 +42,10 @@ using calculator_bhvr = composed_behavior<adder_bhvr, multiplier_bhvr>; ...@@ -42,9 +42,10 @@ using calculator_bhvr = composed_behavior<adder_bhvr, multiplier_bhvr>;
} // namespace <anonymous> } // namespace <anonymous>
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto f = make_function_view(system.spawn<calculator_bhvr>()); auto f = make_function_view(system.spawn<calculator_bhvr>());
cout << "10 + 20 = " << f(add_atom::value, 10, 20) << endl; cout << "10 + 20 = " << f(add_atom::value, 10, 20) << endl;
cout << "7 * 9 = " << f(multiply_atom::value, 7, 9) << endl; cout << "7 * 9 = " << f(multiply_atom::value, 7, 9) << endl;
} }
CAF_MAIN()
...@@ -45,9 +45,10 @@ protected: ...@@ -45,9 +45,10 @@ protected:
} // namespace <anonymous> } // namespace <anonymous>
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto f = make_function_view(system.spawn<dict_behavior>()); auto f = make_function_view(system.spawn<dict_behavior>());
f(put_atom::value, "CAF", "success"); f(put_atom::value, "CAF", "success");
cout << "CAF is the key to " << f(get_atom::value, "CAF") << endl; cout << "CAF is the key to " << f(get_atom::value, "CAF") << endl;
} }
CAF_MAIN()
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
// CAF // CAF
#include "caf/all.hpp" #include "caf/all.hpp"
#include "caf/io/all.hpp"
CAF_PUSH_WARNINGS CAF_PUSH_WARNINGS
#include <curl/curl.h> #include <curl/curl.h>
...@@ -329,8 +330,7 @@ std::atomic<bool> shutdown_flag{false}; ...@@ -329,8 +330,7 @@ std::atomic<bool> shutdown_flag{false};
} // namespace <anonymous> } // namespace <anonymous>
int main(int argc, char** argv) { void caf_main(actor_system& system) {
// random number setup
// install signal handler // install signal handler
struct sigaction act; struct sigaction act;
act.sa_handler = [](int) { shutdown_flag = true; }; act.sa_handler = [](int) { shutdown_flag = true; };
...@@ -343,7 +343,7 @@ int main(int argc, char** argv) { ...@@ -343,7 +343,7 @@ int main(int argc, char** argv) {
set_sighandler(); set_sighandler();
// initialize CURL // initialize CURL
curl_global_init(CURL_GLOBAL_DEFAULT); curl_global_init(CURL_GLOBAL_DEFAULT);
actor_system system{argc, argv}; // get a scoped actor for the communication with our CURL actors
scoped_actor self{system}; 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);
...@@ -365,3 +365,5 @@ int main(int argc, char** argv) { ...@@ -365,3 +365,5 @@ int main(int argc, char** argv) {
// shutdown CURL // shutdown CURL
curl_global_cleanup(); curl_global_cleanup();
} }
CAF_MAIN(io::middleman)
...@@ -81,14 +81,16 @@ void testee(event_based_actor* self, size_t remaining) { ...@@ -81,14 +81,16 @@ void testee(event_based_actor* self, size_t remaining) {
); );
} }
int main(int argc, char** argv) { class config : public actor_system_config {
actor_system_config cfg{argc, argv}; public:
cfg.add_message_type<foo>("foo"); void init() override {
cfg.add_message_type<foo2>("foo2"); add_message_type<foo>("foo");
cfg.add_message_type<foo_pair>("foo_pair"); add_message_type<foo2>("foo2");
// this actor system can now serialize our custom types when running add_message_type<foo_pair>("foo_pair");
// a distributed CAF application or we can serialize them manually }
actor_system system{cfg}; };
void caf_main(actor_system& system, config&) {
// two variables for testing serialization // two variables for testing serialization
foo2 f1; foo2 f1;
foo2 f2; foo2 f2;
...@@ -115,3 +117,5 @@ int main(int argc, char** argv) { ...@@ -115,3 +117,5 @@ int main(int argc, char** argv) {
self->send(t, foo_pair2{3, 4}); self->send(t, foo_pair2{3, 4});
self->await_all_other_actors_done(); self->await_all_other_actors_done();
} }
CAF_MAIN()
...@@ -61,9 +61,15 @@ behavior testee(event_based_actor* self) { ...@@ -61,9 +61,15 @@ behavior testee(event_based_actor* self) {
}; };
} }
int main(int argc, char** argv) { class config : public actor_system_config {
actor_system_config cfg{argc, argv}; public:
cfg.add_message_type<foo>("foo"); void init() override {
actor_system system{cfg}; add_message_type<foo>("foo");
}
};
void caf_main(actor_system& system, config&) {
anon_send(system.spawn(testee), foo{1, 2}); anon_send(system.spawn(testee), foo{1, 2});
} }
CAF_MAIN()
...@@ -75,9 +75,15 @@ behavior testee(event_based_actor* self) { ...@@ -75,9 +75,15 @@ behavior testee(event_based_actor* self) {
}; };
} }
int main(int argc, char** argv) { class config : public actor_system_config {
actor_system_config cfg{argc, argv}; public:
cfg.add_message_type<foo>("foo"); void init() override {
actor_system system{cfg}; add_message_type<foo>("foo");
}
};
void caf_main(actor_system& system, config&) {
anon_send(system.spawn(testee), foo{1, 2}); anon_send(system.spawn(testee), foo{1, 2});
} }
CAF_MAIN()
...@@ -191,8 +191,7 @@ private: ...@@ -191,8 +191,7 @@ private:
} // namespace <anonymous> } // namespace <anonymous>
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
scoped_actor self{system}; scoped_actor self{system};
// create five chopsticks // create five chopsticks
aout(self) << "chopstick ids are:"; aout(self) << "chopstick ids are:";
...@@ -208,3 +207,5 @@ int main(int argc, char** argv) { ...@@ -208,3 +207,5 @@ int main(int argc, char** argv) {
for (size_t i = 0; i < 5; ++i) for (size_t i = 0; i < 5; ++i)
self->spawn<philosopher>(names[i], chopsticks[i], chopsticks[(i + 1) % 5]); self->spawn<philosopher>(names[i], chopsticks[i], chopsticks[(i + 1) % 5]);
} }
CAF_MAIN()
...@@ -36,8 +36,7 @@ behavior client(event_based_actor* self, const actor& serv) { ...@@ -36,8 +36,7 @@ behavior client(event_based_actor* self, const actor& serv) {
}; };
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto serv = system.spawn(server); auto serv = system.spawn(server);
auto worker = system.spawn(client, serv); auto worker = system.spawn(client, serv);
scoped_actor self{system}; scoped_actor self{system};
...@@ -48,3 +47,5 @@ int main(int argc, char** argv) { ...@@ -48,3 +47,5 @@ int main(int argc, char** argv) {
}); });
self->send_exit(serv, exit_reason::user_shutdown); self->send_exit(serv, exit_reason::user_shutdown);
} }
CAF_MAIN()
...@@ -127,8 +127,7 @@ void tester(scoped_actor& self, const Handle& hdl, int x, int y, Ts&&... xs) { ...@@ -127,8 +127,7 @@ void tester(scoped_actor& self, const Handle& hdl, int x, int y, Ts&&... xs) {
tester(self, std::forward<Ts>(xs)...); tester(self, std::forward<Ts>(xs)...);
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto a1 = system.spawn(blocking_calculator_fun); auto a1 = system.spawn(blocking_calculator_fun);
auto a2 = system.spawn(calculator_fun); auto a2 = system.spawn(calculator_fun);
auto a3 = system.spawn(typed_calculator_fun); auto a3 = system.spawn(typed_calculator_fun);
...@@ -138,3 +137,5 @@ int main(int argc, char** argv) { ...@@ -138,3 +137,5 @@ int main(int argc, char** argv) {
scoped_actor self{system}; scoped_actor self{system};
tester(self, a1, 1, 2, a2, 3, 4, a3, 5, 6, a4, 7, 8, a5, 9, 10, a6, 11, 12); tester(self, a1, 1, 2, a2, 3, 4, a3, 5, 6, a4, 7, 8, a5, 9, 10, a6, 11, 12);
} }
CAF_MAIN()
...@@ -44,8 +44,7 @@ behavior unchecked_cell(stateful_actor<cell_state>* self) { ...@@ -44,8 +44,7 @@ behavior unchecked_cell(stateful_actor<cell_state>* self) {
}; };
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
// create one cell for each implementation // create one cell for each implementation
auto cell1 = system.spawn(type_checked_cell); auto cell1 = system.spawn(type_checked_cell);
auto cell2 = system.spawn(unchecked_cell); auto cell2 = system.spawn(unchecked_cell);
...@@ -56,3 +55,5 @@ int main(int argc, char** argv) { ...@@ -56,3 +55,5 @@ int main(int argc, char** argv) {
// get an unchecked cell and send it some garbage // get an unchecked cell and send it some garbage
anon_send(cell2, "hello there!"); anon_send(cell2, "hello there!");
} }
CAF_MAIN()
...@@ -74,7 +74,8 @@ void dancing_kirby(event_based_actor* self) { ...@@ -74,7 +74,8 @@ void dancing_kirby(event_based_actor* self) {
); );
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
system.spawn(dancing_kirby); system.spawn(dancing_kirby);
} }
CAF_MAIN()
...@@ -36,7 +36,8 @@ calc::behavior_type actor_c() { ...@@ -36,7 +36,8 @@ calc::behavior_type actor_c() {
}; };
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
system.spawn(actor_a, system.spawn(actor_b, system.spawn(actor_c))); system.spawn(actor_a, system.spawn(actor_b, system.spawn(actor_c)));
} }
CAF_MAIN()
...@@ -47,13 +47,17 @@ divider::behavior_type divider_impl() { ...@@ -47,13 +47,17 @@ divider::behavior_type divider_impl() {
}; };
} }
int main(int argc, char** argv) { class config : public actor_system_config {
auto renderer = [](uint8_t x, atom_value, const message&) { public:
return "math_error" + deep_to_string_as_tuple(static_cast<math_error>(x)); void init() override {
}; auto renderer = [](uint8_t x, atom_value, const message&) {
actor_system_config cfg{argc, argv}; return "math_error" + deep_to_string_as_tuple(static_cast<math_error>(x));
cfg.add_error_category(atom("math"), renderer); };
actor_system system{cfg}; add_error_category(atom("math"), renderer);
}
};
void caf_main(actor_system& system, config&) {
double x; double x;
double y; double y;
cout << "x: " << flush; cout << "x: " << flush;
...@@ -72,3 +76,5 @@ int main(int argc, char** argv) { ...@@ -72,3 +76,5 @@ int main(int argc, char** argv) {
} }
); );
} }
CAF_MAIN()
...@@ -69,10 +69,9 @@ private: ...@@ -69,10 +69,9 @@ private:
behavior empty_; behavior empty_;
}; };
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto st = system.spawn<fixed_stack>(5);
scoped_actor self{system}; scoped_actor self{system};
auto st = self->spawn<fixed_stack>(5);
// fill stack // fill stack
for (int i = 0; i < 10; ++i) for (int i = 0; i < 10; ++i)
self->send(st, push_atom::value, i); self->send(st, push_atom::value, i);
...@@ -92,3 +91,5 @@ int main(int argc, char** argv) { ...@@ -92,3 +91,5 @@ int main(int argc, char** argv) {
aout(self) << "}" << endl; aout(self) << "}" << endl;
self->send_exit(st, exit_reason::user_shutdown); self->send_exit(st, exit_reason::user_shutdown);
} }
CAF_MAIN()
...@@ -14,8 +14,7 @@ behavior foo(event_based_actor* self) { ...@@ -14,8 +14,7 @@ behavior foo(event_based_actor* self) {
}; };
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
scoped_actor self{system}; scoped_actor self{system};
aout(self) << "spawn foo" << endl; aout(self) << "spawn foo" << endl;
self->spawn(foo); self->spawn(foo);
...@@ -23,3 +22,5 @@ int main(int argc, char** argv) { ...@@ -23,3 +22,5 @@ int main(int argc, char** argv) {
aout(self) << "spawn foo again with priority_aware flag" << endl; aout(self) << "spawn foo again with priority_aware flag" << endl;
self->spawn<priority_aware>(foo); self->spawn<priority_aware>(foo);
} }
CAF_MAIN()
...@@ -42,8 +42,9 @@ adder::behavior_type calculator_master(adder::pointer self) { ...@@ -42,8 +42,9 @@ adder::behavior_type calculator_master(adder::pointer self) {
}; };
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
auto f = make_function_view(system.spawn(calculator_master)); auto f = make_function_view(system.spawn(calculator_master));
cout << "12 + 13 = " << f(add_atom::value, 12, 13) << endl; cout << "12 + 13 = " << f(add_atom::value, 12, 13) << endl;
} }
CAF_MAIN()
...@@ -57,8 +57,7 @@ void blocking_testee(blocking_actor* self, vector<cell> cells) { ...@@ -57,8 +57,7 @@ void blocking_testee(blocking_actor* self, vector<cell> cells) {
}); });
} }
int main(int argc, char** argv) { void caf_main(actor_system& system) {
actor_system system{argc, argv};
vector<cell> cells; vector<cell> cells;
for (auto i = 0; i < 5; ++i) for (auto i = 0; i < 5; ++i)
cells.emplace_back(system.spawn(cell_impl, i * i)); cells.emplace_back(system.spawn(cell_impl, i * i));
...@@ -72,3 +71,5 @@ int main(int argc, char** argv) { ...@@ -72,3 +71,5 @@ int main(int argc, char** argv) {
aout(self) << "blocking_testee" << endl; aout(self) << "blocking_testee" << endl;
system.spawn(blocking_testee, cells); system.spawn(blocking_testee, cells);
} }
CAF_MAIN()
...@@ -249,48 +249,39 @@ void client_repl(actor_system& system, string host, uint16_t port) { ...@@ -249,48 +249,39 @@ void client_repl(actor_system& system, string host, uint16_t port) {
} // namespace <anonymous> } // namespace <anonymous>
int main(int argc, char** argv) { class config : public actor_system_config {
public:
uint16_t port = 0; uint16_t port = 0;
string host = "localhost"; std::string host = "localhost";
auto res = message_builder(argv + 1, argv + argc).extract_opts({ bool server_mode = false;
{"port,p", "set port (either to publish at or to connect to)", port},
{"host,H", "set host (client mode only, default: localhost)", host}, void init() override {
{"server,s", "run in server mode"}, opt_group{custom_options_, "global"}
{"client,c", "run in client mode"} .add(port, "port,p", "set port")
}); .add(host, "host,H", "set host (ignored in server mode)")
if (! res.error.empty()) .add(server_mode, "server-mode,s", "enable server mode");
return cerr << res.error << endl, 1;
if (res.opts.count("help") > 0)
return cout << res.helptext << endl, 0;
// not all CLI arguments could be consumed
if (! res.remainder.empty())
return cerr << "*** invalid CLI options" << endl << res.helptext << endl, 1;
bool is_server = res.opts.count("server") > 0;
if (is_server == (res.opts.count("client") > 0)) {
if (is_server)
cerr << "*** cannot be server and client at the same time" << endl;
else
cerr << "*** either --server or --client option must be set" << endl;
return 1;
} }
if (! is_server && port == 0) };
return cerr << "*** no port to server specified" << endl, 1;
actor_system_config cfg; void caf_main(actor_system& system, config& cfg) {
cfg.load<io::middleman>(); if (! cfg.server_mode && cfg.port == 0) {
actor_system system{cfg}; cerr << "*** no port to server specified" << endl;
if (is_server) { return;
}
if (cfg.server_mode) {
auto calc = system.spawn(calculator_fun); auto calc = system.spawn(calculator_fun);
// 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 " << cfg.port << endl;
auto p = system.middleman().publish(calc, port); auto p = system.middleman().publish(calc, cfg.port);
cout << "*** server successfully published at port " << p << endl; cout << "*** server successfully published at port " << p << endl;
cout << "*** press [enter] to quit" << endl; cout << "*** press [enter] to quit" << endl;
string dummy; string dummy;
std::getline(std::cin, dummy); std::getline(std::cin, dummy);
cout << "... cya" << endl; cout << "... cya" << endl;
anon_send_exit(calc, exit_reason::user_shutdown); anon_send_exit(calc, exit_reason::user_shutdown);
return;
} }
else { client_repl(system, cfg.host, cfg.port);
client_repl(system, host, port);
}
} }
CAF_MAIN(io::middleman)
...@@ -61,48 +61,45 @@ void client(event_based_actor* self, const string& name) { ...@@ -61,48 +61,45 @@ void client(event_based_actor* self, const string& name) {
); );
} }
int main(int argc, char** argv) { class config : public actor_system_config {
string name; public:
string group_id; std::string name;
auto res = message_builder(argv + 1, argv + argc).extract_opts({ std::string group_id;
{"name,n", "set name", name},
{"group,g", "join group", group_id} void init() override {
}); opt_group{custom_options_, "global"}
if (! res.error.empty()) .add(name, "name,n", "set name")
return cerr << res.error << endl, 1; .add(group_id, "group,g", "join group");
if (! res.remainder.empty()) }
return std::cout << res.helptext << std::endl, 1; };
if (res.opts.count("help") > 0)
return cout << res.helptext << endl, 0; void caf_main(actor_system& system, config& cfg) {
while (name.empty()) { while (cfg.name.empty()) {
cout << "please enter your name: " << flush; cout << "please enter your name: " << flush;
if (! getline(cin, name)) { if (! getline(cin, cfg.name)) {
cerr << "*** no name given... terminating" << endl; cerr << "*** no name given... terminating" << endl;
return 1; return;
} }
} }
actor_system_config cfg; auto client_actor = system.spawn(client, cfg.name);
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 (! cfg.group_id.empty()) {
auto p = group_id.find(':'); auto p = cfg.group_id.find(':');
if (p == std::string::npos) { if (p == std::string::npos) {
cerr << "*** error parsing argument " << group_id cerr << "*** error parsing argument " << cfg.group_id
<< ", expected format: <module_name>:<group_id>"; << ", expected format: <module_name>:<group_id>";
} else { } else {
try { try {
auto module = group_id.substr(0, p); auto module = cfg.group_id.substr(0, p);
auto group_uri = group_id.substr(p + 1); auto group_uri = cfg.group_id.substr(p + 1);
auto g = (module == "remote") auto g = (module == "remote")
? system.middleman().remote_group(group_uri) ? system.middleman().remote_group(group_uri)
: system.groups().get(module, 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(\"" << cfg.group_id.substr(0, p)
<< "\", \"" << group_id.substr(p + 1) << "\") failed: " << "\", \"" << cfg.group_id.substr(p + 1) << "\") failed: "
<< e.what() << endl; << e.what() << endl;
} }
} }
...@@ -154,3 +151,5 @@ int main(int argc, char** argv) { ...@@ -154,3 +151,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);
} }
CAF_MAIN(io::middleman)
...@@ -18,26 +18,25 @@ ...@@ -18,26 +18,25 @@
using namespace std; using namespace std;
using namespace caf; using namespace caf;
int main(int argc, char** argv) { class config : public actor_system_config {
public:
uint16_t port = 0; uint16_t port = 0;
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"port,p", "set port", port} void init() override {
}); opt_group{custom_options_, "global"}
if (! res.error.empty()) .add(port, "port,p", "set port");
return cerr << res.error << endl, 1; }
if (res.opts.count("help") > 0) };
return cout << res.helptext << endl, 0;
if (! res.remainder.empty()) void caf_main(actor_system& system, config& cfg) {
return cerr << "*** too many arguments" << endl << res.helptext << endl, 1; system.middleman().publish_local_groups(cfg.port);
if (res.opts.count("port") == 0 || port <= 1024)
return cerr << "*** no valid port given" << endl << res.helptext << endl, 1;
actor_system system{actor_system_config{}.load<io::middleman>()};
system.middleman().publish_local_groups(port);
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;
else else
cerr << "illegal command" << endl; cerr << "illegal command" << endl;
} }
CAF_MAIN(io::middleman)
...@@ -35,6 +35,7 @@ set (LIBCAF_CORE_SRCS ...@@ -35,6 +35,7 @@ set (LIBCAF_CORE_SRCS
src/behavior_impl.cpp src/behavior_impl.cpp
src/blocking_actor.cpp src/blocking_actor.cpp
src/concatenated_tuple.cpp src/concatenated_tuple.cpp
src/config_option.cpp
src/continue_helper.cpp src/continue_helper.cpp
src/decorated_tuple.cpp src/decorated_tuple.cpp
src/deep_to_string.cpp src/deep_to_string.cpp
......
...@@ -23,11 +23,14 @@ ...@@ -23,11 +23,14 @@
#include <atomic> #include <atomic>
#include <string> #include <string>
#include <memory> #include <memory>
#include <typeindex>
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include "caf/actor_system.hpp" #include "caf/fwd.hpp"
#include "caf/config_value.hpp"
#include "caf/config_option.hpp"
#include "caf/actor_factory.hpp" #include "caf/actor_factory.hpp"
#include "caf/type_erased_value.hpp" #include "caf/type_erased_value.hpp"
...@@ -36,6 +39,7 @@ ...@@ -36,6 +39,7 @@
namespace caf { namespace caf {
/// Configures an `actor_system` on startup.
class actor_system_config { class actor_system_config {
public: public:
friend class actor_system; friend class actor_system;
...@@ -58,61 +62,51 @@ public: ...@@ -58,61 +62,51 @@ public:
using error_renderers = std::unordered_map<atom_value, error_renderer>; using error_renderers = std::unordered_map<atom_value, error_renderer>;
/// A variant type for config parameters. using option_ptr = std::unique_ptr<config_option>;
using config_value = variant<std::string, double, int64_t, bool, atom_value>;
/// Helper class to generate config readers for different input types. using options_vector = std::vector<option_ptr>;
class option {
public:
using config_reader_sink = std::function<void (size_t, config_value&)>;
option(const char* category, const char* name, const char* explanation);
virtual ~option();
inline const char* name() const {
return name_;
}
inline const char* category() const { class opt_group {
return category_; public:
} opt_group(options_vector& xs, const char* category);
inline const char* explanation() const { template <class T>
return explanation_; opt_group& add(T& storage, const char* name, const char* explanation) {
xs_.emplace_back(make_config_option(storage, cat_, name, explanation));
return *this;
} }
virtual std::string to_string() const = 0; private:
options_vector& xs_;
virtual config_reader_sink to_sink() const = 0; const char* cat_;
virtual message::cli_arg to_cli_arg() const = 0;
protected:
const char* category_;
const char* name_;
const char* explanation_;
}; };
using option_ptr = std::unique_ptr<option>; virtual ~actor_system_config();
using options_vector = std::vector<option_ptr>;
actor_system_config(); actor_system_config();
actor_system_config(int argc, char** argv); actor_system_config(const actor_system_config&) = delete;
actor_system_config& operator=(const actor_system_config&) = delete;
actor_system_config& parse(int argc, char** argv,
const char* config_file_name = nullptr);
/// Allows other nodes to spawn actors created by `fun`
/// dynamically by using `name` as identifier.
/// @experimental
actor_system_config& add_actor_factory(std::string name, actor_factory fun); actor_system_config& add_actor_factory(std::string name, actor_factory fun);
/// Allows others to spawn actors of type `T` /// Allows other nodes to spawn actors of type `T`
/// dynamically by using `name` as identifier. /// dynamically by using `name` as identifier.
/// @experimental
template <class T, class... Ts> template <class T, class... Ts>
actor_system_config& add_actor_type(std::string name) { actor_system_config& add_actor_type(std::string name) {
return add_actor_factory(std::move(name), make_actor_factory<T, Ts...>()); return add_actor_factory(std::move(name), make_actor_factory<T, Ts...>());
} }
/// Allows others to spawn actors implemented by function `f` /// Allows other nodes to spawn actors implemented by function `f`
/// dynamically by using `name` as identifier. /// dynamically by using `name` as identifier.
/// @experimental
template <class F> template <class F>
actor_system_config& add_actor_type(std::string name, F f) { actor_system_config& add_actor_type(std::string name, F f) {
return add_actor_factory(std::move(name), make_actor_factory(std::move(f))); return add_actor_factory(std::move(name), make_actor_factory(std::move(f)));
...@@ -213,6 +207,13 @@ public: ...@@ -213,6 +207,13 @@ public:
node_id network_id; node_id network_id;
proxy_registry* network_proxies; proxy_registry* network_proxies;
protected:
virtual void init();
virtual std::string make_help_text(const std::vector<message::cli_arg>&);
options_vector custom_options_;
private: private:
static std::string render_sec(uint8_t, atom_value, const message&); static std::string render_sec(uint8_t, atom_value, const message&);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "caf/sec.hpp" #include "caf/sec.hpp"
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/send.hpp" #include "caf/send.hpp"
#include "caf/skip.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
#include "caf/actor.hpp" #include "caf/actor.hpp"
#include "caf/after.hpp" #include "caf/after.hpp"
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
#include "caf/behavior.hpp" #include "caf/behavior.hpp"
#include "caf/duration.hpp" #include "caf/duration.hpp"
#include "caf/exception.hpp" #include "caf/exception.hpp"
#include "caf/exec_main.hpp"
#include "caf/resumable.hpp" #include "caf/resumable.hpp"
#include "caf/streambuf.hpp" #include "caf/streambuf.hpp"
#include "caf/actor_addr.hpp" #include "caf/actor_addr.hpp"
...@@ -54,7 +56,6 @@ ...@@ -54,7 +56,6 @@
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/deserializer.hpp" #include "caf/deserializer.hpp"
#include "caf/scoped_actor.hpp" #include "caf/scoped_actor.hpp"
#include "caf/skip.hpp"
#include "caf/actor_ostream.hpp" #include "caf/actor_ostream.hpp"
#include "caf/function_view.hpp" #include "caf/function_view.hpp"
#include "caf/index_mapping.hpp" #include "caf/index_mapping.hpp"
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_CONFIG_OPTION_HPP
#define CAF_CONFIG_OPTION_HPP
#include <memory>
#include <string>
#include <cstdint>
#include <cstring>
#include <functional>
#include "caf/atom.hpp"
#include "caf/message.hpp"
#include "caf/variant.hpp"
#include "caf/config_value.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/static_visitor.hpp"
namespace caf {
/// Helper class to generate config readers for different input types.
class config_option {
public:
using config_reader_sink = std::function<void (size_t, config_value&)>;
config_option(const char* category, const char* name, const char* explanation);
virtual ~config_option();
inline const char* name() const {
return name_.c_str();
}
inline char short_name() const {
return short_name_;
}
inline const char* category() const {
return category_;
}
inline const char* explanation() const {
return explanation_;
}
/// Returns the held value as string.
virtual std::string to_string() const = 0;
/// Returns a sink function for config readers.
virtual config_reader_sink to_sink() = 0;
/// Returns a CLI argument parser.
virtual message::cli_arg to_cli_arg(bool use_caf_prefix = false) = 0;
/// Returns a human-readable type name for the visited type.
struct type_name_visitor : static_visitor<const char*> {
const char* operator()(const std::string&) const;
const char* operator()(double) const;
const char* operator()(int64_t) const;
const char* operator()(size_t) const;
const char* operator()(uint16_t) const;
const char* operator()(bool) const;
const char* operator()(atom_value) const;
};
protected:
// 32-bit platforms
template <class T>
static typename std::enable_if<sizeof(T) == sizeof(uint32_t), bool>::type
unsigned_assign_in_range(T&, int64_t& x) {
return x <= std::numeric_limits<T>::max();
}
// 64-bit platforms
template <class T>
static typename std::enable_if<sizeof(T) == sizeof(uint64_t), bool>::type
unsigned_assign_in_range(T&, int64_t&) {
return true;
}
template <class T, class U>
static bool assign_config_value(T& x, U& y) {
x = std::move(y);
return true;
}
static bool assign_config_value(size_t& x, int64_t& y);
static bool assign_config_value(uint16_t& x, int64_t& y);
void report_type_error(size_t line, config_value& x, const char* expected);
private:
const char* category_;
std::string name_;
const char* explanation_;
char short_name_;
};
template <class T>
class config_option_impl : public config_option {
public:
config_option_impl(T& ref, const char* ctg, const char* nm, const char* xp)
: config_option(ctg, nm, xp),
ref_(ref) {
// nop
}
std::string to_string() const override {
return deep_to_string(ref_);
}
message::cli_arg to_cli_arg(bool use_caf_prefix) override {
std::string argname;
if (use_caf_prefix)
argname = "caf#";
if (strcmp(category(), "global") != 0) {
argname += category();
argname += ".";
}
argname += name();
if (short_name() != '\0') {
argname += ',';
argname += short_name();
}
return {std::move(argname), explanation(), ref_};
}
config_reader_sink to_sink() override {
return [=](size_t ln, config_value& x) {
// the INI parser accepts all integers as int64_t
using cfg_type =
typename std::conditional<
std::is_integral<T>::value && ! std::is_same<bool, T>::value,
int64_t,
T
>::type;
if (get<cfg_type>(&x) && assign_config_value(ref_, get<cfg_type>(x)))
return;
type_name_visitor tnv;
report_type_error(ln, x, tnv(ref_));
};
}
private:
T& ref_;
};
template <class T>
std::unique_ptr<config_option>
make_config_option(T& storage, const char* category,
const char* name, const char* explanation) {
auto ptr = new config_option_impl<T>(storage, category, name, explanation);
return std::unique_ptr<config_option>{ptr};
}
} // namespace caf
#endif // CAF_CONFIG_OPTION_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_CONFIG_VALUE_HPP
#define CAF_CONFIG_VALUE_HPP
#include <string>
#include <cstdint>
#include "caf/atom.hpp"
#include "caf/variant.hpp"
namespace caf {
/// A variant type for config parameters.
using config_value = variant<std::string, double, int64_t, bool, atom_value>;
} // namespace caf
#endif // CAF_CONFIG_VALUE_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_EXEC_MAIN_HPP
#define CAF_EXEC_MAIN_HPP
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
namespace caf {
template <class>
struct exec_main_helper;
template <>
struct exec_main_helper<detail::type_list<actor_system&>> {
using config = actor_system_config;
template <class F>
void operator()(F& fun, actor_system& sys, config&) {
fun(sys);
}
};
template <class T>
struct exec_main_helper<detail::type_list<actor_system&, T&>> {
using config = T;
template <class F>
void operator()(F& fun, actor_system& sys, config& cfg) {
fun(sys, cfg);
}
};
template <class... Ts, class F = void (*)(actor_system&)>
int exec_main(F fun, int argc, char** argv,
const char* config_file_name = "caf-application.ini") {
using trait = typename detail::get_callable_trait<F>::type;
using helper = exec_main_helper<typename trait::arg_types>;
// pass CLI options to config
typename helper::config cfg;
cfg.parse(argc, argv, config_file_name);
// return immediately if a help text was printed
if (cfg.cli_helptext_printed)
return 0;
// load modules
std::initializer_list<unit_t> unused{unit_t{cfg.template load<Ts>()}...};
CAF_IGNORE_UNUSED(unused);
// pass config to the actor system
actor_system system{cfg};
if (cfg.slave_mode) {
}
helper f;
f(fun, system, cfg);
return 0;
}
} // namespace caf
#define CAF_MAIN(...) \
int main(int argc, char** argv) { \
::caf::exec_main<__VA_ARGS__>(caf_main, argc, argv); \
}
#endif // CAF_EXEC_MAIN_HPP
...@@ -171,9 +171,16 @@ public: ...@@ -171,9 +171,16 @@ public:
/// Evaluates option arguments. /// Evaluates option arguments.
consumer fun; consumer fun;
/// Set to true for zero-argument options.
bool* flag;
/// Creates a CLI argument without data. /// Creates a CLI argument without data.
cli_arg(std::string name, std::string text); cli_arg(std::string name, std::string text);
/// Creates a CLI flag option. The `flag` is set to `true` if the option
/// was set, otherwise it is `false`.
cli_arg(std::string name, std::string text, bool& flag);
/// Creates a CLI argument storing its matched argument in `dest`. /// Creates a CLI argument storing its matched argument in `dest`.
cli_arg(std::string name, std::string text, atom_value& dest); cli_arg(std::string name, std::string text, atom_value& dest);
...@@ -454,12 +461,14 @@ message::cli_arg::cli_arg(typename std::enable_if< ...@@ -454,12 +461,14 @@ message::cli_arg::cli_arg(typename std::enable_if<
return true; return true;
} }
return false; return false;
}) { }),
flag(nullptr) {
// nop // nop
} }
template <class T> template <class T>
message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::vector<T>& arg) message::cli_arg::cli_arg(std::string nstr, std::string tstr,
std::vector<T>& arg)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)), text(std::move(tstr)),
fun([&arg](const std::string& str) -> bool { fun([&arg](const std::string& str) -> bool {
...@@ -470,7 +479,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::vector<T>& ar ...@@ -470,7 +479,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::vector<T>& ar
return true; return true;
} }
return false; return false;
}) { }),
flag(nullptr) {
// nop // nop
} }
......
...@@ -40,7 +40,7 @@ actor_system::actor_system() : actor_system(actor_system_config{}) { ...@@ -40,7 +40,7 @@ actor_system::actor_system() : actor_system(actor_system_config{}) {
} }
actor_system::actor_system(int argc, char** argv) actor_system::actor_system(int argc, char** argv)
: actor_system(actor_system_config{argc, argv}) { : actor_system(actor_system_config{}.parse(argc, argv)) {
// nop // nop
} }
......
This diff is collapsed.
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config_option.hpp"
#include <iostream>
namespace caf {
config_option::config_option(const char* category, const char* name,
const char* explanation)
: category_(category),
name_(name),
explanation_(explanation),
short_name_('\0') {
auto last = name_.end();
auto comma = std::find(name_.begin(), last, ',');
if (comma != last) {
auto i = comma;
++i;
if (i != last)
short_name_ = *i;
name_.erase(comma, last);
}
}
config_option::~config_option() {
// nop
}
const char* config_option::type_name_visitor::operator()(const std::string&) const {
return "a string";
}
const char* config_option::type_name_visitor::operator()(double) const {
return "a double";
}
const char* config_option::type_name_visitor::operator()(int64_t) const {
return "an integer";
}
const char* config_option::type_name_visitor::operator()(size_t) const {
return "an unsigned integer";
}
const char* config_option::type_name_visitor::operator()(uint16_t) const {
return "an unsigned short integer";
}
const char* config_option::type_name_visitor::operator()(bool) const {
return "a boolean";
}
const char* config_option::type_name_visitor::operator()(atom_value) const {
return "an atom";
}
bool config_option::assign_config_value(size_t& x, int64_t& y) {
if (y < 0 || ! unsigned_assign_in_range(x, y))
return false;
x = std::move(y);
return true;
}
bool config_option::assign_config_value(uint16_t& x, int64_t& y) {
if (y < 0 || y > std::numeric_limits<uint16_t>::max())
return false;
x = std::move(y);
return true;
}
void config_option::report_type_error(size_t ln, config_value& x,
const char* expected) {
type_name_visitor tnv;
std::cerr << "error in line " << ln << ": expected "
<< expected << " found "
<< apply_visitor(tnv, x) << std::endl;
}
} // namespace caf
...@@ -263,6 +263,8 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs, ...@@ -263,6 +263,8 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs,
} }
// no value given, try two-argument form below // no value given, try two-argument form below
return skip(); return skip();
} else if (i->second->flag) {
*i->second->flag = true;
} }
insert_opt_name(i->second); insert_opt_name(i->second);
return none; return none;
...@@ -281,6 +283,8 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs, ...@@ -281,6 +283,8 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs,
} }
insert_opt_name(j->second); insert_opt_name(j->second);
return none; return none;
} else if (j->second->flag) {
*j->second->flag = true;
} }
insert_opt_name(j->second); insert_opt_name(j->second);
return none; return none;
...@@ -318,14 +322,23 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs, ...@@ -318,14 +322,23 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs,
message::cli_arg::cli_arg(std::string nstr, std::string tstr) message::cli_arg::cli_arg(std::string nstr, std::string tstr)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)) { text(std::move(tstr)),
flag(nullptr) {
// nop // nop
} }
message::cli_arg::cli_arg(std::string nstr, std::string tstr, bool& arg)
: name(std::move(nstr)),
text(std::move(tstr)),
flag(&arg) {
arg = false;
}
message::cli_arg::cli_arg(std::string nstr, std::string tstr, consumer f) message::cli_arg::cli_arg(std::string nstr, std::string tstr, consumer f)
: name(std::move(nstr)), : name(std::move(nstr)),
text(std::move(tstr)), text(std::move(tstr)),
fun(std::move(f)) { fun(std::move(f)),
flag(nullptr) {
// nop // nop
} }
...@@ -338,7 +351,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, atom_value& arg) ...@@ -338,7 +351,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, atom_value& arg)
return true; return true;
} }
return false; return false;
}) { }),
flag(nullptr) {
// nop // nop
} }
...@@ -348,7 +362,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::string& arg) ...@@ -348,7 +362,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, std::string& arg)
fun([&arg](const std::string& str) -> bool { fun([&arg](const std::string& str) -> bool {
arg = str; arg = str;
return true; return true;
}) { }),
flag(nullptr) {
// nop // nop
} }
...@@ -359,7 +374,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, ...@@ -359,7 +374,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr,
fun([&arg](const std::string& str) -> bool { fun([&arg](const std::string& str) -> bool {
arg.push_back(str); arg.push_back(str);
return true; return true;
}) { }),
flag(nullptr) {
// nop // nop
} }
......
...@@ -145,7 +145,7 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) { ...@@ -145,7 +145,7 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) {
} }
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system system{actor_system_config{argc, argv}.load<io::middleman>()}; actor_system system{actor_system_config{}.load<io::middleman>().parse(argc, argv)};
auto p = system.spawn(ping, size_t{10}); auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client..."); CAF_MESSAGE("spawn_client...");
auto cl = system.middleman().spawn_client(peer_fun, "127.0.0.1", port, p); auto cl = system.middleman().spawn_client(peer_fun, "127.0.0.1", port, p);
...@@ -155,7 +155,7 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -155,7 +155,7 @@ void run_client(int argc, char** argv, uint16_t port) {
} }
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system system{actor_system_config{argc, argv}.load<io::middleman>()}; actor_system system{actor_system_config{}.load<io::middleman>().parse(argc, argv)};
scoped_actor self{system}; scoped_actor self{system};
CAF_MESSAGE("spawn peer acceptor"); CAF_MESSAGE("spawn peer acceptor");
auto serv = system.middleman().spawn_broker(peer_acceptor_fun, auto serv = system.middleman().spawn_broker(peer_acceptor_fun,
......
...@@ -34,18 +34,24 @@ namespace { ...@@ -34,18 +34,24 @@ namespace {
constexpr char local_host[] = "127.0.0.1"; constexpr char local_host[] = "127.0.0.1";
caf::actor_system_config make_actor_system_config() { class custom_config : public caf::actor_system_config {
caf::actor_system_config cfg(caf::test::engine::argc(), public:
caf::test::engine::argv()); void init() override {
cfg.load<caf::io::middleman>(); load<caf::io::middleman>();
// see `CAF_TEST(custom_message_type)` add_message_type<std::vector<int>>("std::vector<int>");
cfg.add_message_type<std::vector<int>>("std::vector<int>"); }
return cfg;
} using actor_system_config::parse;
custom_config& parse() {
parse(caf::test::engine::argc(), caf::test::engine::argv());
return *this;
}
};
struct fixture { struct fixture {
caf::actor_system server_side{make_actor_system_config()}; caf::actor_system server_side{custom_config{}.parse()};
caf::actor_system client_side{make_actor_system_config()}; caf::actor_system client_side{custom_config{}.parse()};
caf::io::middleman& server_side_mm = server_side.middleman(); caf::io::middleman& server_side_mm = server_side.middleman();
caf::io::middleman& client_side_mm = client_side.middleman(); caf::io::middleman& client_side_mm = client_side.middleman();
}; };
......
...@@ -34,16 +34,24 @@ namespace { ...@@ -34,16 +34,24 @@ namespace {
constexpr char local_host[] = "127.0.0.1"; constexpr char local_host[] = "127.0.0.1";
actor_system_config make_actor_system_config() { class custom_config : public caf::actor_system_config {
actor_system_config cfg(test::engine::argc(), test::engine::argv()); public:
cfg.load<io::middleman>(); void init() override {
cfg.add_message_type<std::vector<actor>>("std::vector<actor>"); load<caf::io::middleman>();
return cfg; add_message_type<std::vector<actor>>("std::vector<actor>");
} }
using actor_system_config::parse;
custom_config& parse() {
parse(caf::test::engine::argc(), caf::test::engine::argv());
return *this;
}
};
struct fixture { struct fixture {
actor_system server_side{make_actor_system_config()}; caf::actor_system server_side{custom_config{}.parse()};
actor_system client_side{make_actor_system_config()}; caf::actor_system client_side{custom_config{}.parse()};
io::middleman& server_side_mm = server_side.middleman(); io::middleman& server_side_mm = server_side.middleman();
io::middleman& client_side_mm = client_side.middleman(); io::middleman& client_side_mm = client_side.middleman();
}; };
......
...@@ -106,8 +106,9 @@ behavior server(stateful_actor<server_state>* self) { ...@@ -106,8 +106,9 @@ behavior server(stateful_actor<server_state>* self) {
} }
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg{argc, argv}; actor_system_config cfg;
cfg.load<io::middleman>() cfg.parse(argc, argv)
.load<io::middleman>()
.add_actor_type("mirror", mirror); .add_actor_type("mirror", mirror);
actor_system system{cfg}; actor_system system{cfg};
auto serv = system.middleman().remote_actor("localhost", port); auto serv = system.middleman().remote_actor("localhost", port);
...@@ -115,7 +116,7 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -115,7 +116,7 @@ void run_client(int argc, char** argv, uint16_t port) {
} }
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system system{actor_system_config{argc, argv}.load<io::middleman>()}; actor_system system{actor_system_config{}.load<io::middleman>().parse(argc, argv)};
auto serv = system.spawn(server); auto serv = system.spawn(server);
auto port = system.middleman().publish(serv, 0); auto port = system.middleman().publish(serv, 0);
CAF_REQUIRE(port != 0); CAF_REQUIRE(port != 0);
......
...@@ -159,7 +159,7 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self, ...@@ -159,7 +159,7 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self,
} }
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system system{actor_system_config{argc, argv}.load<io::middleman>()}; actor_system system{actor_system_config{}.load<io::middleman>().parse(argc, argv)};
auto p = system.spawn(ping, size_t{10}); auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client_typed..."); CAF_MESSAGE("spawn_client_typed...");
auto cl = system.middleman().spawn_client(peer_fun, "localhost", port, p); auto cl = system.middleman().spawn_client(peer_fun, "localhost", port, p);
...@@ -169,7 +169,7 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -169,7 +169,7 @@ void run_client(int argc, char** argv, uint16_t port) {
} }
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system system{actor_system_config{argc, argv}.load<io::middleman>()}; actor_system system{actor_system_config{}.load<io::middleman>().parse(argc, argv)};
scoped_actor self{system}; scoped_actor self{system};
auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong)); auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong));
std::thread child; std::thread child;
......
...@@ -75,10 +75,11 @@ server_type::behavior_type server() { ...@@ -75,10 +75,11 @@ server_type::behavior_type server() {
} }
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg{argc, argv}; actor_system_config cfg;
cfg.load<io::middleman>() cfg.load<io::middleman>()
.add_message_type<ping>("ping") .add_message_type<ping>("ping")
.add_message_type<pong>("pong"); .add_message_type<pong>("pong")
.parse(argc, argv);
actor_system system{cfg}; actor_system system{cfg};
// check whether invalid_argument is thrown // check whether invalid_argument is thrown
// when trying to connect to get an untyped // when trying to connect to get an untyped
...@@ -103,10 +104,11 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -103,10 +104,11 @@ void run_client(int argc, char** argv, uint16_t port) {
} }
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system_config cfg{argc, argv}; actor_system_config cfg;
cfg.load<io::middleman>() cfg.load<io::middleman>()
.add_message_type<ping>("ping") .add_message_type<ping>("ping")
.add_message_type<pong>("pong"); .add_message_type<pong>("pong")
.parse(argc, argv);
actor_system system{cfg}; actor_system system{cfg};
auto port = system.middleman().publish(system.spawn(server), 0, "127.0.0.1"); auto port = system.middleman().publish(system.spawn(server), 0, "127.0.0.1");
CAF_REQUIRE(port != 0); CAF_REQUIRE(port != 0);
......
...@@ -56,9 +56,10 @@ public: ...@@ -56,9 +56,10 @@ public:
struct fixture { struct fixture {
fixture() : testee(unsafe_actor_handle_init) { fixture() : testee(unsafe_actor_handle_init) {
new (&system) actor_system(actor_system_config{test::engine::argc(), new (&system) actor_system(actor_system_config{}
test::engine::argv()} .load<io::middleman>()
.load<io::middleman>()); .parse(test::engine::argc(),
test::engine::argv()));
testee = system.spawn<dummy>(); testee = system.spawn<dummy>();
} }
......
...@@ -233,7 +233,8 @@ void bootstrap(actor_system& system, ...@@ -233,7 +233,8 @@ void bootstrap(actor_system& system,
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
actor_system_config cfg{argc, argv}; actor_system_config cfg;
cfg.parse(argc, argv);
if (cfg.cli_helptext_printed) if (cfg.cli_helptext_printed)
return 0; return 0;
if (cfg.slave_mode) if (cfg.slave_mode)
......
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