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
# 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.
ALIASES =
ALIASES = experimental="@attention This feature is **experimental**."
# 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.
......
......@@ -4,12 +4,12 @@
#include <iostream>
#include "caf/all.hpp"
#include "caf/io/all.hpp"
using namespace caf;
using std::endl;
int main() {
actor_system system;
void caf_main(actor_system& system) {
for (int i = 1; i <= 50; ++i) {
system.spawn([i](blocking_actor* self) {
aout(self) << "Hi there! This is actor nr. "
......@@ -27,3 +27,5 @@ int main() {
});
}
}
CAF_MAIN()
......@@ -179,46 +179,36 @@ optional<uint16_t> as_u16(const std::string& str) {
return static_cast<uint16_t>(stoul(str));
}
int main(int argc, char** argv) {
using std::string;
actor_system_config cfg{argc, argv};
if (cfg.cli_helptext_printed)
return 0;
cfg.load<io::middleman>();
class config : public actor_system_config {
public:
uint16_t port = 0;
string host = "localhost";
auto res = cfg.args_remainder.extract_opts({
{"server,s", "run in server mode"},
{"client,c", "run in client mode"},
{"port,p", "set port", port},
{"host,H", "set host (client mode only)", host}
});
if (! res.error.empty())
return cerr << res.error << endl, 1;
if (res.opts.count("help") > 0)
return cout << res.helptext << endl, 0;
if (! res.remainder.empty())
// not all CLI arguments could be consumed
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) {
std::string host = "localhost";
bool server_mode = false;
void init() override {
opt_group{custom_options_, "global"}
.add(port, "port,p", "set port")
.add(host, "host,H", "set host (ignored in server mode)")
.add(server_mode, "server-mode,s", "enable server mode");
}
};
void caf_main(actor_system& system, config& cfg) {
if (cfg.server_mode) {
cout << "run in server mode" << endl;
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(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);
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);
} else {
cerr << "*** neither client nor server mode set" << endl
<< res.helptext << endl;
return 1;
}
}
CAF_MAIN(io::middleman)
......@@ -64,39 +64,25 @@ behavior server(broker* self) {
};
}
optional<uint16_t> as_u16(const std::string& str) {
return static_cast<uint16_t>(stoul(str));
}
int main(int argc, const char** argv) {
class config : public actor_system_config {
public:
uint16_t port = 0;
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"port,p", "set port", port},
});
if (! res.error.empty()) {
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;
void init() override {
opt_group{custom_options_, "global"}
.add(port, "port,p", "set port");
}
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;
actor_system system;
auto server_actor = system.middleman().spawn_server(server, port);
auto server_actor = system.middleman().spawn_server(server, cfg.port);
// wait for any input
std::string dummy;
std::getline(std::cin, dummy);
// kill server
anon_send_exit(server_actor, exit_reason::user_shutdown);
}
CAF_MAIN(io::middleman)
......@@ -22,6 +22,8 @@ profiling-output-file="/dev/null"
enable-automatic-connections=false
; accepted alternative: 'asio' (only when compiling CAF with ASIO)
network-backend='default'
; heartbeat message interval in ms (0 disables heartbeating)
heartbeat-interval=0
; when loading riac::probe
[probe]
......
......@@ -42,9 +42,10 @@ using calculator_bhvr = composed_behavior<adder_bhvr, multiplier_bhvr>;
} // namespace <anonymous>
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
auto f = make_function_view(system.spawn<calculator_bhvr>());
cout << "10 + 20 = " << f(add_atom::value, 10, 20) << endl;
cout << "7 * 9 = " << f(multiply_atom::value, 7, 9) << endl;
}
CAF_MAIN()
......@@ -45,9 +45,10 @@ protected:
} // namespace <anonymous>
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
auto f = make_function_view(system.spawn<dict_behavior>());
f(put_atom::value, "CAF", "success");
cout << "CAF is the key to " << f(get_atom::value, "CAF") << endl;
}
CAF_MAIN()
......@@ -43,6 +43,7 @@
// CAF
#include "caf/all.hpp"
#include "caf/io/all.hpp"
CAF_PUSH_WARNINGS
#include <curl/curl.h>
......@@ -329,8 +330,7 @@ std::atomic<bool> shutdown_flag{false};
} // namespace <anonymous>
int main(int argc, char** argv) {
// random number setup
void caf_main(actor_system& system) {
// install signal handler
struct sigaction act;
act.sa_handler = [](int) { shutdown_flag = true; };
......@@ -343,7 +343,7 @@ int main(int argc, char** argv) {
set_sighandler();
// initialize CURL
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};
// spawn client and curl_master
auto master = self->spawn<detached>(curl_master);
......@@ -365,3 +365,5 @@ int main(int argc, char** argv) {
// shutdown CURL
curl_global_cleanup();
}
CAF_MAIN(io::middleman)
......@@ -81,14 +81,16 @@ void testee(event_based_actor* self, size_t remaining) {
);
}
int main(int argc, char** argv) {
actor_system_config cfg{argc, argv};
cfg.add_message_type<foo>("foo");
cfg.add_message_type<foo2>("foo2");
cfg.add_message_type<foo_pair>("foo_pair");
// this actor system can now serialize our custom types when running
// a distributed CAF application or we can serialize them manually
actor_system system{cfg};
class config : public actor_system_config {
public:
void init() override {
add_message_type<foo>("foo");
add_message_type<foo2>("foo2");
add_message_type<foo_pair>("foo_pair");
}
};
void caf_main(actor_system& system, config&) {
// two variables for testing serialization
foo2 f1;
foo2 f2;
......@@ -115,3 +117,5 @@ int main(int argc, char** argv) {
self->send(t, foo_pair2{3, 4});
self->await_all_other_actors_done();
}
CAF_MAIN()
......@@ -61,9 +61,15 @@ behavior testee(event_based_actor* self) {
};
}
int main(int argc, char** argv) {
actor_system_config cfg{argc, argv};
cfg.add_message_type<foo>("foo");
actor_system system{cfg};
class config : public actor_system_config {
public:
void init() override {
add_message_type<foo>("foo");
}
};
void caf_main(actor_system& system, config&) {
anon_send(system.spawn(testee), foo{1, 2});
}
CAF_MAIN()
......@@ -75,9 +75,15 @@ behavior testee(event_based_actor* self) {
};
}
int main(int argc, char** argv) {
actor_system_config cfg{argc, argv};
cfg.add_message_type<foo>("foo");
actor_system system{cfg};
class config : public actor_system_config {
public:
void init() override {
add_message_type<foo>("foo");
}
};
void caf_main(actor_system& system, config&) {
anon_send(system.spawn(testee), foo{1, 2});
}
CAF_MAIN()
......@@ -191,8 +191,7 @@ private:
} // namespace <anonymous>
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
scoped_actor self{system};
// create five chopsticks
aout(self) << "chopstick ids are:";
......@@ -208,3 +207,5 @@ int main(int argc, char** argv) {
for (size_t i = 0; i < 5; ++i)
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) {
};
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
auto serv = system.spawn(server);
auto worker = system.spawn(client, serv);
scoped_actor self{system};
......@@ -48,3 +47,5 @@ int main(int argc, char** argv) {
});
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) {
tester(self, std::forward<Ts>(xs)...);
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
auto a1 = system.spawn(blocking_calculator_fun);
auto a2 = system.spawn(calculator_fun);
auto a3 = system.spawn(typed_calculator_fun);
......@@ -138,3 +137,5 @@ int main(int argc, char** argv) {
scoped_actor self{system};
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) {
};
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
// create one cell for each implementation
auto cell1 = system.spawn(type_checked_cell);
auto cell2 = system.spawn(unchecked_cell);
......@@ -56,3 +55,5 @@ int main(int argc, char** argv) {
// get an unchecked cell and send it some garbage
anon_send(cell2, "hello there!");
}
CAF_MAIN()
......@@ -74,7 +74,8 @@ void dancing_kirby(event_based_actor* self) {
);
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
system.spawn(dancing_kirby);
}
CAF_MAIN()
......@@ -36,7 +36,8 @@ calc::behavior_type actor_c() {
};
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
system.spawn(actor_a, system.spawn(actor_b, system.spawn(actor_c)));
}
CAF_MAIN()
......@@ -47,13 +47,17 @@ divider::behavior_type divider_impl() {
};
}
int main(int argc, char** argv) {
class config : public actor_system_config {
public:
void init() override {
auto renderer = [](uint8_t x, atom_value, const message&) {
return "math_error" + deep_to_string_as_tuple(static_cast<math_error>(x));
};
actor_system_config cfg{argc, argv};
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 y;
cout << "x: " << flush;
......@@ -72,3 +76,5 @@ int main(int argc, char** argv) {
}
);
}
CAF_MAIN()
......@@ -69,10 +69,9 @@ private:
behavior empty_;
};
int main(int argc, char** argv) {
actor_system system{argc, argv};
auto st = system.spawn<fixed_stack>(5);
void caf_main(actor_system& system) {
scoped_actor self{system};
auto st = self->spawn<fixed_stack>(5);
// fill stack
for (int i = 0; i < 10; ++i)
self->send(st, push_atom::value, i);
......@@ -92,3 +91,5 @@ int main(int argc, char** argv) {
aout(self) << "}" << endl;
self->send_exit(st, exit_reason::user_shutdown);
}
CAF_MAIN()
......@@ -14,8 +14,7 @@ behavior foo(event_based_actor* self) {
};
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
scoped_actor self{system};
aout(self) << "spawn foo" << endl;
self->spawn(foo);
......@@ -23,3 +22,5 @@ int main(int argc, char** argv) {
aout(self) << "spawn foo again with priority_aware flag" << endl;
self->spawn<priority_aware>(foo);
}
CAF_MAIN()
......@@ -42,8 +42,9 @@ adder::behavior_type calculator_master(adder::pointer self) {
};
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
auto f = make_function_view(system.spawn(calculator_master));
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) {
});
}
int main(int argc, char** argv) {
actor_system system{argc, argv};
void caf_main(actor_system& system) {
vector<cell> cells;
for (auto i = 0; i < 5; ++i)
cells.emplace_back(system.spawn(cell_impl, i * i));
......@@ -72,3 +71,5 @@ int main(int argc, char** argv) {
aout(self) << "blocking_testee" << endl;
system.spawn(blocking_testee, cells);
}
CAF_MAIN()
......@@ -249,48 +249,39 @@ void client_repl(actor_system& system, string host, uint16_t port) {
} // namespace <anonymous>
int main(int argc, char** argv) {
class config : public actor_system_config {
public:
uint16_t port = 0;
string host = "localhost";
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"port,p", "set port (either to publish at or to connect to)", port},
{"host,H", "set host (client mode only, default: localhost)", host},
{"server,s", "run in server mode"},
{"client,c", "run in client mode"}
});
if (! res.error.empty())
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;
std::string host = "localhost";
bool server_mode = false;
void init() override {
opt_group{custom_options_, "global"}
.add(port, "port,p", "set port")
.add(host, "host,H", "set host (ignored in server mode)")
.add(server_mode, "server-mode,s", "enable server mode");
}
};
void caf_main(actor_system& system, config& cfg) {
if (! cfg.server_mode && cfg.port == 0) {
cerr << "*** no port to server specified" << endl;
return;
}
if (! is_server && port == 0)
return cerr << "*** no port to server specified" << endl, 1;
actor_system_config cfg;
cfg.load<io::middleman>();
actor_system system{cfg};
if (is_server) {
if (cfg.server_mode) {
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);
cout << "*** try publish at port " << cfg.port << endl;
auto p = system.middleman().publish(calc, cfg.port);
cout << "*** server successfully published at port " << p << endl;
cout << "*** press [enter] to quit" << endl;
string dummy;
std::getline(std::cin, dummy);
cout << "... cya" << endl;
anon_send_exit(calc, exit_reason::user_shutdown);
return;
}
else {
client_repl(system, host, port);
}
client_repl(system, cfg.host, cfg.port);
}
CAF_MAIN(io::middleman)
......@@ -61,48 +61,45 @@ void client(event_based_actor* self, const string& name) {
);
}
int main(int argc, char** argv) {
string name;
string group_id;
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"name,n", "set name", name},
{"group,g", "join group", group_id}
});
if (! res.error.empty())
return cerr << res.error << endl, 1;
if (! res.remainder.empty())
return std::cout << res.helptext << std::endl, 1;
if (res.opts.count("help") > 0)
return cout << res.helptext << endl, 0;
while (name.empty()) {
class config : public actor_system_config {
public:
std::string name;
std::string group_id;
void init() override {
opt_group{custom_options_, "global"}
.add(name, "name,n", "set name")
.add(group_id, "group,g", "join group");
}
};
void caf_main(actor_system& system, config& cfg) {
while (cfg.name.empty()) {
cout << "please enter your name: " << flush;
if (! getline(cin, name)) {
if (! getline(cin, cfg.name)) {
cerr << "*** no name given... terminating" << endl;
return 1;
return;
}
}
actor_system_config cfg;
cfg.load<io::middleman>();
actor_system system{cfg};
auto client_actor = system.spawn(client, name);
auto client_actor = system.spawn(client, cfg.name);
// evaluate group parameters
if (! group_id.empty()) {
auto p = group_id.find(':');
if (! cfg.group_id.empty()) {
auto p = cfg.group_id.find(':');
if (p == std::string::npos) {
cerr << "*** error parsing argument " << group_id
cerr << "*** error parsing argument " << cfg.group_id
<< ", expected format: <module_name>:<group_id>";
} else {
try {
auto module = group_id.substr(0, p);
auto group_uri = group_id.substr(p + 1);
auto module = cfg.group_id.substr(0, p);
auto group_uri = cfg.group_id.substr(p + 1);
auto g = (module == "remote")
? system.middleman().remote_group(group_uri)
: system.groups().get(module, group_uri);
anon_send(client_actor, join_atom::value, g);
}
catch (exception& e) {
cerr << "*** exception: group::get(\"" << group_id.substr(0, p)
<< "\", \"" << group_id.substr(p + 1) << "\") failed: "
cerr << "*** exception: group::get(\"" << cfg.group_id.substr(0, p)
<< "\", \"" << cfg.group_id.substr(p + 1) << "\") failed: "
<< e.what() << endl;
}
}
......@@ -154,3 +151,5 @@ int main(int argc, char** argv) {
// force actor to quit
anon_send_exit(client_actor, exit_reason::user_shutdown);
}
CAF_MAIN(io::middleman)
......@@ -18,26 +18,25 @@
using namespace std;
using namespace caf;
int main(int argc, char** argv) {
class config : public actor_system_config {
public:
uint16_t port = 0;
auto res = message_builder(argv + 1, argv + argc).extract_opts({
{"port,p", "set port", port}
});
if (! res.error.empty())
return cerr << res.error << endl, 1;
if (res.opts.count("help") > 0)
return cout << res.helptext << endl, 0;
if (! res.remainder.empty())
return cerr << "*** too many arguments" << endl << res.helptext << endl, 1;
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);
void init() override {
opt_group{custom_options_, "global"}
.add(port, "port,p", "set port");
}
};
void caf_main(actor_system& system, config& cfg) {
system.middleman().publish_local_groups(cfg.port);
cout << "type 'quit' to shutdown the server" << endl;
string line;
while (getline(cin, line))
if (line == "quit")
return 0;
return;
else
cerr << "illegal command" << endl;
}
CAF_MAIN(io::middleman)
......@@ -35,6 +35,7 @@ set (LIBCAF_CORE_SRCS
src/behavior_impl.cpp
src/blocking_actor.cpp
src/concatenated_tuple.cpp
src/config_option.cpp
src/continue_helper.cpp
src/decorated_tuple.cpp
src/deep_to_string.cpp
......
......@@ -23,11 +23,14 @@
#include <atomic>
#include <string>
#include <memory>
#include <typeindex>
#include <functional>
#include <type_traits>
#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/type_erased_value.hpp"
......@@ -36,6 +39,7 @@
namespace caf {
/// Configures an `actor_system` on startup.
class actor_system_config {
public:
friend class actor_system;
......@@ -58,61 +62,51 @@ public:
using error_renderers = std::unordered_map<atom_value, error_renderer>;
/// A variant type for config parameters.
using config_value = variant<std::string, double, int64_t, bool, atom_value>;
using option_ptr = std::unique_ptr<config_option>;
/// Helper class to generate config readers for different input types.
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_;
}
using options_vector = std::vector<option_ptr>;
inline const char* category() const {
return category_;
}
class opt_group {
public:
opt_group(options_vector& xs, const char* category);
inline const char* explanation() const {
return explanation_;
template <class T>
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;
virtual config_reader_sink to_sink() const = 0;
virtual message::cli_arg to_cli_arg() const = 0;
protected:
const char* category_;
const char* name_;
const char* explanation_;
private:
options_vector& xs_;
const char* cat_;
};
using option_ptr = std::unique_ptr<option>;
using options_vector = std::vector<option_ptr>;
virtual ~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);
/// Allows others to spawn actors of type `T`
/// Allows other nodes to spawn actors of type `T`
/// dynamically by using `name` as identifier.
/// @experimental
template <class T, class... Ts>
actor_system_config& add_actor_type(std::string name) {
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.
/// @experimental
template <class 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)));
......@@ -213,6 +207,13 @@ public:
node_id network_id;
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:
static std::string render_sec(uint8_t, atom_value, const message&);
......
......@@ -25,6 +25,7 @@
#include "caf/sec.hpp"
#include "caf/atom.hpp"
#include "caf/send.hpp"
#include "caf/skip.hpp"
#include "caf/unit.hpp"
#include "caf/actor.hpp"
#include "caf/after.hpp"
......@@ -38,6 +39,7 @@
#include "caf/behavior.hpp"
#include "caf/duration.hpp"
#include "caf/exception.hpp"
#include "caf/exec_main.hpp"
#include "caf/resumable.hpp"
#include "caf/streambuf.hpp"
#include "caf/actor_addr.hpp"
......@@ -54,7 +56,6 @@
#include "caf/actor_system.hpp"
#include "caf/deserializer.hpp"
#include "caf/scoped_actor.hpp"
#include "caf/skip.hpp"
#include "caf/actor_ostream.hpp"
#include "caf/function_view.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:
/// Evaluates option arguments.
consumer fun;
/// Set to true for zero-argument options.
bool* flag;
/// Creates a CLI argument without data.
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`.
cli_arg(std::string name, std::string text, atom_value& dest);
......@@ -454,12 +461,14 @@ message::cli_arg::cli_arg(typename std::enable_if<
return true;
}
return false;
}) {
}),
flag(nullptr) {
// nop
}
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)),
text(std::move(tstr)),
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
return true;
}
return false;
}) {
}),
flag(nullptr) {
// nop
}
......
......@@ -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_config{argc, argv}) {
: actor_system(actor_system_config{}.parse(argc, argv)) {
// nop
}
......
......@@ -31,77 +31,29 @@ namespace caf {
namespace {
struct type_name_visitor : static_visitor<const char*> {
const char* operator()(const std::string&) const {
return "a string";
}
const char* operator()(double) const {
return "a double";
}
const char* operator()(int64_t) const {
return "an integer";
}
const char* operator()(size_t) const {
return "an unsigned integer";
}
const char* operator()(uint16_t) const {
return "an unsigned short integer";
}
const char* operator()(bool) const {
return "a boolean";
}
const char* operator()(atom_value) const {
return "an atom";
}
};
template <class T, class U>
bool assign_config_value(T& x, U& y) {
x = std::move(y);
return true;
}
// 32-bit platforms
template <class T>
inline 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>
inline typename std::enable_if<sizeof(T) == sizeof(uint64_t), bool>::type
unsigned_assign_in_range(T&, int64_t&) {
return true;
}
bool 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 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;
}
using options_vector = actor_system_config::options_vector;
class actor_system_config_reader {
public:
using config_value = actor_system_config::config_value;
using sink = std::function<void (size_t, config_value&)>;
actor_system_config_reader(options_vector& xs) {
actor_system_config_reader(options_vector& xs, options_vector& ys) {
add_opts(xs);
add_opts(ys);
}
void add_opts(options_vector& xs) {
for (auto& x : xs) {
std::string key = x->category();
key += '.';
key += x->name();
// name can have format "<long>,<short>"; consider only long name
auto name_begin = x->name();
auto name_end = name_begin;
for (auto c = *name_end; c != ',' && c != 0; ++name_end) {
// nop
}
key.insert(key.end(), name_begin, name_end);
//key += x->name();
sinks_.emplace(std::move(key), x->to_sink());
}
}
......@@ -119,78 +71,16 @@ private:
std::map<std::string, sink> sinks_;
};
using cstr = const char*;
template <class T>
void add_option(options_vector& xs,
T& storage, cstr category, cstr name, cstr explanation) {
using option = actor_system_config::option;
using config_value = actor_system_config::config_value;
class impl : public option {
public:
impl(cstr ctg, cstr nm, cstr xp, T& ref) : option(ctg, nm, xp), ref_(ref) {
// nop
}
std::string to_string() const override {
return deep_to_string(ref_);
}
message::cli_arg to_cli_arg() const override {
std::string argname = "caf#";
argname += category();
argname += ".";
argname += name();
return {std::move(argname), explanation(), ref_};
}
config_reader_sink to_sink() const 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;
std::cerr << "error in line " << ln << ": expected "
<< tnv(ref_) << " found "
<< apply_visitor(tnv, x) << std::endl;
};
}
private:
T& ref_;
};
return xs.emplace_back(new impl(category, name, explanation, storage));
}
class opt_group {
public:
opt_group(options_vector& xs, cstr category) : xs_(xs), category_(category) {
// nop
}
template <class T>
opt_group& add(T& storage, cstr option_name, cstr explanation) {
add_option(xs_, storage, category_, option_name, explanation);
return *this;
}
private:
options_vector& xs_;
cstr category_;
};
} // namespace <anonymous>
actor_system_config::option::option(cstr ct, cstr nm, cstr xp)
: category_(ct),
name_(nm),
explanation_(xp) {
actor_system_config::opt_group::opt_group(options_vector& xs,
const char* category)
: xs_(xs),
cat_(category) {
// nop
}
actor_system_config::option::~option() {
actor_system_config::~actor_system_config() {
// nop
}
......@@ -238,7 +128,7 @@ actor_system_config::actor_system_config()
opt_group{options_, "probe"}
.add(nexus_host, "nexus-host",
"sets the hostname or IP address for connecting to the Nexus")
.add(nexus_port, "probe.nexus-port",
.add(nexus_port, "nexus-port",
"sets the port for connecting to the Nexus");
opt_group(options_, "opencl")
.add(opencl_device_ids, "device-ids",
......@@ -248,13 +138,49 @@ actor_system_config::actor_system_config()
error_renderers_.emplace(atom("exit"), render_exit_reason);
}
actor_system_config::actor_system_config(int argc, char** argv)
: actor_system_config() {
if (argc < 1)
return;
std::string
actor_system_config::make_help_text(const std::vector<message::cli_arg>& xs) {
auto is_no_caf_option = [](const message::cli_arg& arg) {
return arg.name.compare(0, 4, "caf#") != 0;
};
auto op = [](size_t tmp, const message::cli_arg& arg) {
return std::max(tmp, arg.helptext.size());
};
// maximum string lenght of all options
auto name_width = std::accumulate(xs.begin(), xs.end(), size_t{0}, op);
// iterators to the vector with respect to partition point
auto first = xs.begin();
auto last = xs.end();
auto sep = std::find_if(first, last, is_no_caf_option);
// output stream
std::ostringstream oss;
oss << std::left;
oss << "CAF Options:" << std::endl;
for (auto i = first; i != sep; ++i) {
oss << " ";
oss.width(static_cast<std::streamsize>(name_width));
oss << i->helptext << " : " << i->text << std::endl;
}
if (sep != last) {
oss << std::endl;
oss << "Application Options:" << std::endl;
for (auto i = sep; i != last; ++i) {
oss << " ";
oss.width(static_cast<std::streamsize>(name_width));
oss << i->helptext << " : " << i->text << std::endl;
}
}
return oss.str();
}
actor_system_config& actor_system_config::parse(int argc, char** argv,
const char* ini_file_cstr) {
init();
auto args = message_builder(argv + 1, argv + argc).move_to_message();
// extract config file name first, since INI files are overruled by CLI args
std::string config_file_name;
if (ini_file_cstr)
config_file_name = ini_file_cstr;
args.extract_opts({
{"caf#config-file", "", config_file_name}
});
......@@ -262,27 +188,39 @@ actor_system_config::actor_system_config(int argc, char** argv)
if (! config_file_name.empty()) {
std::ifstream ini{config_file_name};
if (ini.good()) {
actor_system_config_reader consumer{options_};
actor_system_config_reader consumer{options_, custom_options_};
detail::parse_ini(ini, consumer, std::cerr);
}
}
// (3) CLI options override the content of the INI file
std::vector<message::cli_arg> cargs;
for (auto& x : options_)
cargs.emplace_back(x->to_cli_arg());
cargs.emplace_back(x->to_cli_arg(true));
cargs.emplace_back("caf#dump-config", "print config in INI format to stdout");
cargs.emplace_back("caf#help", "print this text");
//cargs.emplace_back("caf#help", "print this text");
cargs.emplace_back("caf#config-file", "parse INI file", config_file_name);
cargs.emplace_back("caf#slave-mode", "run in slave mode");
cargs.emplace_back("caf#slave-name", "set name for this slave", slave_name);
cargs.emplace_back("caf#bootstrap-node", "set bootstrapping", bootstrap_node);
auto res = args.extract_opts(std::move(cargs), nullptr, true);
for (auto& x : custom_options_)
cargs.emplace_back(x->to_cli_arg(false));
using std::placeholders::_1;
auto res = args.extract_opts(std::move(cargs),
std::bind(&actor_system_config::make_help_text,
this, _1));
using std::cerr;
using std::cout;
using std::endl;
if (res.opts.count("caf#help")) {
args_remainder = std::move(res.remainder);
if (! res.error.empty()) {
cli_helptext_printed = true;
std::cerr << res.error << endl;
return *this;
}
if (res.opts.count("help")) {
cli_helptext_printed = true;
cout << res.helptext << endl;
return *this;
}
if (res.opts.count("caf#slave-mode")) {
slave_mode = true;
......@@ -309,26 +247,19 @@ actor_system_config::actor_system_config(int argc, char** argv)
scheduler_policy, "scheduler.policy ");
if (res.opts.count("caf#dump-config")) {
cli_helptext_printed = true;
cout << std::boolalpha
<< "[scheduler]" << endl
<< "policy=" << deep_to_string(scheduler_policy) << endl
<< "max-threads=" << scheduler_max_threads << endl
<< "max-throughput=" << scheduler_max_throughput << endl
<< "enable-profiling=" << scheduler_enable_profiling << endl;
if (scheduler_enable_profiling)
cout << "profiling-ms-resolution="
<< scheduler_profiling_ms_resolution << endl
<< "profiling_output_file="
<< deep_to_string(scheduler_profiling_output_file) << endl;
cout << "[middleman]" << endl
<< "network-backend="
<< deep_to_string(middleman_network_backend) << endl
<< "enable-automatic-connections="
<< deep_to_string(middleman_enable_automatic_connections) << endl
<< "heartbeat-interval="
<< middleman_heartbeat_interval << endl;
std::string category;
options_vector* all_options[] = { &options_, &custom_options_ };
for (auto& opt_vec : all_options) {
for (auto& opt : *opt_vec) {
if (category != opt->category()) {
category = opt->category();
cout << "[" << category << "]" << endl;
}
args_remainder = std::move(res.remainder);
cout << opt->name() << "=" << opt->to_string() << endl;
}
}
}
return *this;
}
actor_system_config&
......@@ -359,6 +290,10 @@ actor_system_config::set(const char* config_name, config_value config_value) {
return *this;
}
void actor_system_config::init() {
// nop
}
std::string actor_system_config::render_sec(uint8_t x, atom_value,
const message&) {
return "system_error" + deep_to_string_as_tuple(static_cast<sec>(x));
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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,
}
// no value given, try two-argument form below
return skip();
} else if (i->second->flag) {
*i->second->flag = true;
}
insert_opt_name(i->second);
return none;
......@@ -281,6 +283,8 @@ message::cli_res message::extract_opts(std::vector<cli_arg> xs,
}
insert_opt_name(j->second);
return none;
} else if (j->second->flag) {
*j->second->flag = true;
}
insert_opt_name(j->second);
return none;
......@@ -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)
: name(std::move(nstr)),
text(std::move(tstr)) {
text(std::move(tstr)),
flag(nullptr) {
// 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)
: name(std::move(nstr)),
text(std::move(tstr)),
fun(std::move(f)) {
fun(std::move(f)),
flag(nullptr) {
// nop
}
......@@ -338,7 +351,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr, atom_value& arg)
return true;
}
return false;
}) {
}),
flag(nullptr) {
// nop
}
......@@ -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 {
arg = str;
return true;
}) {
}),
flag(nullptr) {
// nop
}
......@@ -359,7 +374,8 @@ message::cli_arg::cli_arg(std::string nstr, std::string tstr,
fun([&arg](const std::string& str) -> bool {
arg.push_back(str);
return true;
}) {
}),
flag(nullptr) {
// nop
}
......
......@@ -145,7 +145,7 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) {
}
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});
CAF_MESSAGE("spawn_client...");
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) {
}
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};
CAF_MESSAGE("spawn peer acceptor");
auto serv = system.middleman().spawn_broker(peer_acceptor_fun,
......
......@@ -34,18 +34,24 @@ namespace {
constexpr char local_host[] = "127.0.0.1";
caf::actor_system_config make_actor_system_config() {
caf::actor_system_config cfg(caf::test::engine::argc(),
caf::test::engine::argv());
cfg.load<caf::io::middleman>();
// see `CAF_TEST(custom_message_type)`
cfg.add_message_type<std::vector<int>>("std::vector<int>");
return cfg;
}
class custom_config : public caf::actor_system_config {
public:
void init() override {
load<caf::io::middleman>();
add_message_type<std::vector<int>>("std::vector<int>");
}
using actor_system_config::parse;
custom_config& parse() {
parse(caf::test::engine::argc(), caf::test::engine::argv());
return *this;
}
};
struct fixture {
caf::actor_system server_side{make_actor_system_config()};
caf::actor_system client_side{make_actor_system_config()};
caf::actor_system server_side{custom_config{}.parse()};
caf::actor_system client_side{custom_config{}.parse()};
caf::io::middleman& server_side_mm = server_side.middleman();
caf::io::middleman& client_side_mm = client_side.middleman();
};
......
......@@ -34,16 +34,24 @@ namespace {
constexpr char local_host[] = "127.0.0.1";
actor_system_config make_actor_system_config() {
actor_system_config cfg(test::engine::argc(), test::engine::argv());
cfg.load<io::middleman>();
cfg.add_message_type<std::vector<actor>>("std::vector<actor>");
return cfg;
}
class custom_config : public caf::actor_system_config {
public:
void init() override {
load<caf::io::middleman>();
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 {
actor_system server_side{make_actor_system_config()};
actor_system client_side{make_actor_system_config()};
caf::actor_system server_side{custom_config{}.parse()};
caf::actor_system client_side{custom_config{}.parse()};
io::middleman& server_side_mm = server_side.middleman();
io::middleman& client_side_mm = client_side.middleman();
};
......
......@@ -106,8 +106,9 @@ behavior server(stateful_actor<server_state>* self) {
}
void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg{argc, argv};
cfg.load<io::middleman>()
actor_system_config cfg;
cfg.parse(argc, argv)
.load<io::middleman>()
.add_actor_type("mirror", mirror);
actor_system system{cfg};
auto serv = system.middleman().remote_actor("localhost", port);
......@@ -115,7 +116,7 @@ void run_client(int argc, char** argv, uint16_t port) {
}
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 port = system.middleman().publish(serv, 0);
CAF_REQUIRE(port != 0);
......
......@@ -159,7 +159,7 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self,
}
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});
CAF_MESSAGE("spawn_client_typed...");
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) {
}
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};
auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong));
std::thread child;
......
......@@ -75,10 +75,11 @@ server_type::behavior_type server() {
}
void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg{argc, argv};
actor_system_config cfg;
cfg.load<io::middleman>()
.add_message_type<ping>("ping")
.add_message_type<pong>("pong");
.add_message_type<pong>("pong")
.parse(argc, argv);
actor_system system{cfg};
// check whether invalid_argument is thrown
// when trying to connect to get an untyped
......@@ -103,10 +104,11 @@ void run_client(int argc, char** argv, uint16_t port) {
}
void run_server(int argc, char** argv) {
actor_system_config cfg{argc, argv};
actor_system_config cfg;
cfg.load<io::middleman>()
.add_message_type<ping>("ping")
.add_message_type<pong>("pong");
.add_message_type<pong>("pong")
.parse(argc, argv);
actor_system system{cfg};
auto port = system.middleman().publish(system.spawn(server), 0, "127.0.0.1");
CAF_REQUIRE(port != 0);
......
......@@ -56,9 +56,10 @@ public:
struct fixture {
fixture() : testee(unsafe_actor_handle_init) {
new (&system) actor_system(actor_system_config{test::engine::argc(),
test::engine::argv()}
.load<io::middleman>());
new (&system) actor_system(actor_system_config{}
.load<io::middleman>()
.parse(test::engine::argc(),
test::engine::argv()));
testee = system.spawn<dummy>();
}
......
......@@ -233,7 +233,8 @@ void bootstrap(actor_system& system,
}
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)
return 0;
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