Commit bff39e81 authored by Dominik Charousset's avatar Dominik Charousset

Merge branch 'issue/802'

parents a104e7c9 0fbe9d15
......@@ -100,6 +100,7 @@ set(LIBCAF_CORE_SRCS
src/sequencer.cpp
src/serializer.cpp
src/set_thread_name.cpp
src/settings.cpp
src/shared_spinlock.cpp
src/simple_actor_clock.cpp
src/skip.cpp
......
......@@ -31,7 +31,6 @@
#include "caf/actor_marker.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/actor_control_block.hpp"
#include "caf/unsafe_actor_handle_init.hpp"
#include "caf/detail/comparable.hpp"
#include "caf/detail/type_traits.hpp"
......@@ -82,8 +81,6 @@ public:
actor(const scoped_actor&);
explicit actor(const unsafe_actor_handle_init_t&) CAF_DEPRECATED;
template <class T,
class = typename std::enable_if<
std::is_base_of<dynamically_typed_actor_base, T>::value
......@@ -143,12 +140,6 @@ public:
/// Exchange content of `*this` and `other`.
void swap(actor& other) noexcept;
/// Queries whether this object was constructed using
/// `unsafe_actor_handle_init` or is in moved-from state.
bool unsafe() const CAF_DEPRECATED {
return !ptr_;
}
/// @cond PRIVATE
inline abstract_actor* operator->() const noexcept {
......
......@@ -26,7 +26,6 @@
#include "caf/fwd.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/actor_control_block.hpp"
#include "caf/unsafe_actor_handle_init.hpp"
#include "caf/detail/comparable.hpp"
......@@ -57,7 +56,6 @@ public:
actor_addr& operator=(const actor_addr&) = default;
actor_addr(std::nullptr_t);
actor_addr(const unsafe_actor_handle_init_t&);
actor_addr& operator=(std::nullptr_t);
......
......@@ -35,6 +35,7 @@
#include "caf/fwd.hpp"
#include "caf/is_typed_actor.hpp"
#include "caf/named_actor_config.hpp"
#include "caf/settings.hpp"
#include "caf/stream.hpp"
#include "caf/thread_hook.hpp"
#include "caf/type_erased_value.hpp"
......@@ -103,7 +104,7 @@ public:
// -- properties -------------------------------------------------------------
/// @private
dictionary<config_value::dictionary> content;
settings content;
/// Sets a config by using its INI name `config_name` to `config_value`.
template <class T>
......@@ -113,30 +114,23 @@ public:
// -- modifiers --------------------------------------------------------------
/// Parses `args` as tuple of strings containing CLI options
/// and `ini_stream` as INI formatted input stream.
actor_system_config& parse(string_list args, std::istream& ini);
/// Parses `args` as tuple of strings containing CLI options and `ini_stream`
/// as INI formatted input stream.
error parse(string_list args, std::istream& ini);
/// Parses `args` as tuple of strings containing CLI options and tries to
/// open `ini_file_cstr` as INI formatted config file. The parsers tries to
/// open `caf-application.ini` if `ini_file_cstr` is `nullptr`.
actor_system_config& parse(string_list args,
const char* ini_file_cstr = nullptr);
error parse(string_list args, const char* ini_file_cstr = nullptr);
/// Parses the CLI options `{argc, argv}` and
/// `ini_stream` as INI formatted input stream.
actor_system_config& parse(int argc, char** argv, std::istream& ini);
/// Parses the CLI options `{argc, argv}` and `ini_stream` as INI formatted
/// input stream.
error parse(int argc, char** argv, std::istream& ini);
/// Parses the CLI options `{argc, argv}` and tries to open `ini_file_cstr`
/// as INI formatted config file. The parsers tries to open
/// `caf-application.ini` if `ini_file_cstr` is `nullptr`.
actor_system_config& parse(int argc, char** argv,
const char* ini_file_cstr = nullptr);
actor_system_config&
parse(message& args, const char* ini_file_cstr = nullptr) CAF_DEPRECATED;
actor_system_config& parse(message& args, std::istream& ini) CAF_DEPRECATED;
error parse(int argc, char** argv, const char* ini_file_cstr = nullptr);
/// Allows other nodes to spawn actors created by `fun`
/// dynamically by using `name` as identifier.
......@@ -248,9 +242,6 @@ public:
/// and instead return from `main` immediately.
bool cli_helptext_printed;
/// Stores CLI arguments that were not consumed by CAF.
message args_remainder CAF_DEPRECATED;
/// Stores CLI arguments that were not consumed by CAF.
string_list remainder;
......@@ -279,49 +270,6 @@ public:
/// @private
timespan stream_tick_duration() const noexcept;
timespan streaming_credit_round_interval() const noexcept CAF_DEPRECATED;
// -- scheduling parameters --------------------------------------------------
atom_value scheduler_policy CAF_DEPRECATED;
size_t scheduler_max_threads CAF_DEPRECATED;
size_t scheduler_max_throughput CAF_DEPRECATED;
bool scheduler_enable_profiling CAF_DEPRECATED;
size_t scheduler_profiling_ms_resolution CAF_DEPRECATED;
std::string scheduler_profiling_output_file CAF_DEPRECATED;
// -- work-stealing parameters -----------------------------------------------
size_t work_stealing_aggressive_poll_attempts CAF_DEPRECATED;
size_t work_stealing_aggressive_steal_interval CAF_DEPRECATED;
size_t work_stealing_moderate_poll_attempts CAF_DEPRECATED;
size_t work_stealing_moderate_steal_interval CAF_DEPRECATED;
size_t work_stealing_moderate_sleep_duration_us CAF_DEPRECATED;
size_t work_stealing_relaxed_steal_interval CAF_DEPRECATED;
size_t work_stealing_relaxed_sleep_duration_us CAF_DEPRECATED;
// -- logger parameters ------------------------------------------------------
std::string logger_file_name CAF_DEPRECATED;
std::string logger_file_format CAF_DEPRECATED;
atom_value logger_console CAF_DEPRECATED;
std::string logger_console_format CAF_DEPRECATED;
std::string logger_component_filter CAF_DEPRECATED;
atom_value logger_verbosity CAF_DEPRECATED;
bool logger_inline_output CAF_DEPRECATED;
// -- middleman parameters ---------------------------------------------------
atom_value middleman_network_backend CAF_DEPRECATED;
std::string middleman_app_identifier CAF_DEPRECATED;
bool middleman_enable_automatic_connections CAF_DEPRECATED;
size_t middleman_max_consecutive_reads CAF_DEPRECATED;
size_t middleman_heartbeat_interval CAF_DEPRECATED;
bool middleman_detach_utility_actors CAF_DEPRECATED;
bool middleman_detach_multiplexer CAF_DEPRECATED;
size_t middleman_cached_udp_buffers CAF_DEPRECATED;
size_t middleman_max_pending_msgs CAF_DEPRECATED;
// -- OpenCL parameters ------------------------------------------------------
std::string opencl_device_ids;
......@@ -388,8 +336,37 @@ private:
static std::string render_exit_reason(uint8_t, atom_value, const message&);
static std::string render_pec(uint8_t, atom_value, const message&);
void extract_config_file_path(string_list& args);
};
} // namespace caf
/// @private
const settings& content(const actor_system_config& cfg);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
optional<T> get_if(const actor_system_config* cfg, string_view name) {
return get_if<T>(&content(*cfg), name);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
T get(const actor_system_config& cfg, string_view name) {
return get<T>(content(cfg), name);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
template <class K, class V>
auto get_or(const actor_system_config& cfg, K&& name, V&& default_value)
-> decltype(get_or(content(cfg), std::forward<K>(name),
std::forward<V>(default_value))) {
return get_or(content(cfg), std::forward<K>(name),
std::forward<V>(default_value));
}
} // namespace caf
......@@ -33,7 +33,7 @@
namespace caf {
/// A set of `config_option` objects that parses CLI arguments into a
/// `config_value::dictionary`.
/// `settings` object.
class config_option_set {
public:
// -- member types -----------------------------------------------------------
......@@ -56,12 +56,6 @@ public:
/// An iterator over ::config_option unique pointers.
using const_iterator = option_vector::const_iterator;
/// Maps string keys to arbitrary (config) values.
using dictionary = caf::dictionary<config_value>;
/// Categorized settings.
using config_map = caf::dictionary<dictionary>;
// -- properties -------------------------------------------------------------
/// Returns the first `config_option` that matches the CLI name.
......@@ -174,11 +168,11 @@ public:
// -- parsing ----------------------------------------------------------------
/// Parses a given range as CLI arguments into `config`.
parse_result parse(config_map& config, argument_iterator begin,
parse_result parse(settings& config, argument_iterator begin,
argument_iterator end) const;
/// Parses a given range as CLI arguments into `config`.
parse_result parse(config_map& config,
parse_result parse(settings& config,
const std::vector<std::string>& args) const;
private:
......
......@@ -22,6 +22,7 @@
#include <cstdint>
#include <map>
#include <string>
#include <type_traits>
#include <vector>
#include "caf/atom.hpp"
......@@ -32,6 +33,7 @@
#include "caf/optional.hpp"
#include "caf/raise_error.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/string_view.hpp"
#include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp"
#include "caf/sum_type_token.hpp"
......@@ -111,6 +113,12 @@ public:
/// already is a list.
void convert_to_list();
/// Returns the value as a list, converting it to one if needed.
list& as_list();
/// Returns the value as a dictionary, converting it to one if needed.
dictionary& as_dictionary();
/// Appends `x` to a list. Converts this config value to a list first by
/// calling `convert_to_list` if needed.
void append(config_value x);
......@@ -174,12 +182,6 @@ private:
variant_type data_;
};
// -- related type aliases -----------------------------------------------------
/// Organizes config values into categories.
/// @relates config_value
using config_value_map = dictionary<config_value::dictionary>;
// -- SumType-like access ------------------------------------------------------
/// @relates config_value
......@@ -401,168 +403,6 @@ struct config_value_access<dictionary<V>> {
// -- SumType-like access of dictionary values ---------------------------------
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const config_value::dictionary* xs, string_view name) {
// Split the name into a path.
std::vector<string_view> path;
split(path, name, ".");
// Sanity check.
if (path.size() == 0)
return none;
// Resolve path, i.e., find the requested submap.
auto current = xs;
auto leaf = path.end() - 1;
for (auto i = path.begin(); i != leaf; ++i) {
auto j = current->find(*i);
if (j == current->end())
return none;
current = caf::get_if<config_value::dictionary>(&j->second);
if (current == nullptr)
return none;
}
// Get the leaf value.
auto j = current->find(*leaf);
if (j == current->end())
return none;
auto result = caf::get_if<T>(&j->second);
if (result)
return *result;
return none;
}
/// Retrieves the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
T get(const config_value::dictionary& xs, string_view name) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
CAF_RAISE_ERROR("invalid type or name found");
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const config_value::dictionary& xs, string_view name,
const T& default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
std::string get_or(const config_value::dictionary& xs, string_view name,
const char* default_value);
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const config_value_map* xs, string_view name) {
// Get the category.
auto pos = name.find('.');
if (pos == std::string::npos) {
auto i = xs->find("global");
if (i == xs->end())
return none;
return get_if<T>(&i->second, name);
}
auto i = xs->find(name.substr(0, pos));
if (i == xs->end())
return none;
return get_if<T>(&i->second, name.substr(pos + 1));
}
/// Retrieves the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
T get(const config_value_map& xs, string_view name) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
CAF_RAISE_ERROR("invalid type or name found");
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const config_value_map& xs, string_view name, const T& default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
std::string get_or(const config_value_map& xs, string_view name,
const char* default_value);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
optional<T> get_if(const actor_system_config* cfg, string_view name) {
return get_if<T>(&content(*cfg), name);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
T get(const actor_system_config& cfg, string_view name) {
return get<T>(content(cfg), name);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const actor_system_config& cfg, string_view name,
const T& default_value) {
return get_or(content(cfg), name, default_value);
}
std::string get_or(const actor_system_config& cfg, string_view name,
const char* default_value);
/// @private
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value);
/// @private
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value);
/// @private
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// @param dict Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template <class T>
void put(dictionary<config_value::dictionary>& dict, string_view key,
T&& value) {
config_value tmp{std::forward<T>(value)};
put_impl(dict, key, tmp);
}
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::list& put_list(config_value::dictionary& xs, std::string name);
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::dictionary& put_dictionary(config_value::dictionary& xs,
std::string name);
/// @relates config_value
bool operator<(const config_value& x, const config_value& y);
......@@ -595,4 +435,3 @@ typename Inspector::result_type inspect(Inspector& f, config_value& x) {
}
} // namespace caf
......@@ -22,6 +22,7 @@
#include <cstddef>
#include "caf/atom.hpp"
#include "caf/string_view.hpp"
#include "caf/timestamp.hpp"
// -- hard-coded default values for various CAF options ------------------------
......@@ -40,7 +41,7 @@ extern const timespan credit_round_interval;
namespace scheduler {
extern const atom_value policy;
extern const char* profiling_output_file;
extern string_view profiling_output_file;
extern const size_t max_threads;
extern const size_t max_throughput;
extern const timespan profiling_resolution;
......@@ -61,19 +62,19 @@ extern const timespan relaxed_sleep_duration;
namespace logger {
extern const char* component_filter;
extern string_view component_filter;
extern const atom_value console;
extern const char* console_format;
extern string_view console_format;
extern const atom_value console_verbosity;
extern const char* file_format;
extern const char* file_name;
extern string_view file_format;
extern string_view file_name;
extern const atom_value file_verbosity;
} // namespace logger
namespace middleman {
extern const char* app_identifier;
extern string_view app_identifier;
extern const atom_value network_backend;
extern const size_t max_consecutive_reads;
extern const size_t heartbeat_interval;
......
......@@ -23,6 +23,7 @@
#include "caf/config_option_set.hpp"
#include "caf/config_value.hpp"
#include "caf/dictionary.hpp"
#include "caf/settings.hpp"
namespace caf {
namespace detail {
......@@ -191,7 +192,7 @@ public:
// -- constructors, destructors, and assignment operators --------------------
ini_consumer(config_option_set& options, config_map& cfg);
ini_consumer(config_option_set& options, settings& cfg);
ini_consumer(ini_consumer&&) = default;
......@@ -207,7 +208,7 @@ private:
// -- member variables -------------------------------------------------------
config_option_set& options_;
config_map& cfg_;
settings& cfg_;
std::string current_key;
std::vector<error> warnings_;
};
......
......@@ -366,13 +366,4 @@ bool operator>=(const dictionary<T>& xs, const dictionary<T>& ys) {
return xs.container() >= ys.container();
}
// -- free functions -----------------------------------------------------------
/// Convenience function for calling `dict.insert_or_assign(key, value)`.
// @relates dictionary
template <class T, class V>
void put(dictionary<T>& dict, string_view key, V&& value) {
dict.insert_or_assign(key, std::forward<V>(value));
}
} // namespace caf
......@@ -122,7 +122,7 @@ struct function_view_result {
template <class... Ts>
struct function_view_result<typed_actor<Ts...>> {
typed_actor<Ts...> value{unsafe_actor_handle_init};
typed_actor<Ts...> value{nullptr};
};
/// A function view for an actor hides any messaging from the caller.
......
......@@ -174,12 +174,12 @@ using ip_address = ipv6_address;
using ip_subnet = ipv6_subnet;
using stream_slot = uint16_t;
using config_value_map = dictionary<dictionary<config_value>>;
using settings = dictionary<config_value>;
// -- functions ----------------------------------------------------------------
/// @relates actor_system_config
const dictionary<dictionary<config_value>>& content(const actor_system_config&);
const settings& content(const actor_system_config&);
// -- intrusive containers -----------------------------------------------------
......
......@@ -200,12 +200,6 @@ public:
return f(meta::type_name("message_id"), x.value_);
}
// -- deprecated functions ---------------------------------------------------
template <class... Ts>
static message_id make(Ts&&... xs)
CAF_DEPRECATED_MSG("use make_message_id instead");
private:
// -- member variables -------------------------------------------------------
......@@ -241,13 +235,6 @@ constexpr message_id make_message_id(message_priority p) {
return message_id{static_cast<uint64_t>(p) << message_id::category_offset};
}
// -- deprecated functions -----------------------------------------------------
template <class... Ts>
message_id message_id::make(Ts&&... xs) {
return make_message_id(std::forward<Ts>(xs)...);
}
} // namespace caf
namespace std {
......
......@@ -65,10 +65,18 @@ enum class pec : uint8_t {
illegal_category,
};
/// Returns an error object from given error code.
error make_error(pec code);
/// Returns an error object from given error code with additional context
/// information for where the parser stopped in the input.
error make_error(pec code, size_t line, size_t column);
/// Returns an error object from given error code with additional context
/// information for where the parser stopped in the argument.
error make_error(pec code, std::string argument);
/// @relates pec
const char* to_string(pec x);
} // namespace caf
......@@ -142,10 +142,6 @@ public:
detail::test_actor_clock& clock() noexcept override;
std::pair<size_t, size_t>
run_dispatch_loop(timespan cycle_duration = timespan{1})
CAF_DEPRECATED_MSG("use the testing DSL's run() instead");
protected:
void start() override;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* 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. *
******************************************************************************/
#pragma once
#include "caf/config_value.hpp"
#include "caf/dictionary.hpp"
#include "caf/optional.hpp"
#include "caf/raise_error.hpp"
#include "caf/string_view.hpp"
namespace caf {
/// Software options stored as key-value pairs.
/// @relates config_value
using settings = dictionary<config_value>;
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const settings* xs, string_view name) {
// Access the key directly unless the user specified a dot-separated path.
auto pos = name.find('.');
if (pos == std::string::npos) {
auto i = xs->find(name);
if (i == xs->end())
return none;
// We can't simply return the result here, because it might be a pointer.
auto result = get_if<T>(&i->second);
if (result)
return *result;
return none;
}
// We're dealing with a `<category>.<key>`-formatted string, extract the
// sub-settings by category and recurse.
auto i = xs->find(name.substr(0, pos));
if (i == xs->end() || !holds_alternative<config_value::dictionary>(i->second))
return none;
return get_if<T>(&get<config_value::dictionary>(i->second),
name.substr(pos + 1));
}
template <class T>
T get(const settings& xs, string_view name) {
auto result = get_if<T>(&xs, name);
CAF_ASSERT(result != none);
return std::move(*result);
}
template <class T, class = typename std::enable_if<
!std::is_pointer<T>::value
&& !std::is_convertible<T, string_view>::value>::type>
T get_or(const settings& xs, string_view name, T default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return std::move(default_value);
}
std::string get_or(const settings& xs, string_view name,
string_view default_value);
/// @private
config_value& put_impl(settings& dict, const std::vector<string_view>& path,
config_value& value);
/// @private
config_value& put_impl(settings& dict, string_view key, config_value& value);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// @param dict Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template <class T>
config_value& put(settings& dict, string_view key, T&& value) {
config_value tmp{std::forward<T>(value)};
return put_impl(dict, key, tmp);
}
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::list& put_list(settings& xs, std::string name);
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::dictionary& put_dictionary(settings& xs, std::string name);
} // namespace caf
......@@ -63,10 +63,6 @@ constexpr spawn_options detached = spawn_options::detach_flag;
/// Causes the runtime to ignore the new actor in `await_all_actors_done()`.
constexpr spawn_options hidden = spawn_options::hide_flag;
/// Causes the new actor to evaluate message priorities.
constexpr spawn_options priority_aware CAF_DEPRECATED =
spawn_options::priority_aware_flag;
/// Causes the new actor to delay its
/// initialization until a message arrives.
constexpr spawn_options lazy_init = spawn_options::lazy_init_flag;
......
......@@ -31,7 +31,6 @@
#include "caf/stateful_actor.hpp"
#include "caf/typed_behavior.hpp"
#include "caf/typed_response_promise.hpp"
#include "caf/unsafe_actor_handle_init.hpp"
#include "caf/detail/mpi_splice.hpp"
#include "caf/decorator/splitter.hpp"
......@@ -172,10 +171,6 @@ class typed_actor : detail::comparable<typed_actor<Sigs...>>,
return *this;
}
explicit typed_actor(const unsafe_actor_handle_init_t&) CAF_DEPRECATED {
// nop
}
/// Queries whether this actor handle is valid.
inline explicit operator bool() const {
return static_cast<bool>(ptr_);
......@@ -211,12 +206,6 @@ class typed_actor : detail::comparable<typed_actor<Sigs...>>,
ptr_.swap(other.ptr_);
}
/// Queries whether this object was constructed using
/// `unsafe_actor_handle_init` or is in moved-from state.
bool unsafe() const CAF_DEPRECATED {
return !ptr_;
}
/// @cond PRIVATE
abstract_actor* operator->() const noexcept {
......
......@@ -43,10 +43,6 @@ actor::actor(const scoped_actor& x) : ptr_(actor_cast<strong_actor_ptr>(x)) {
// nop
}
actor::actor(const unsafe_actor_handle_init_t&) : ptr_(nullptr) {
// nop
}
actor::actor(actor_control_block* ptr) : ptr_(ptr) {
// nop
}
......
......@@ -31,10 +31,6 @@ actor_addr::actor_addr(std::nullptr_t) {
// nop
}
actor_addr::actor_addr(const unsafe_actor_handle_init_t&) {
// nop
}
actor_addr& actor_addr::operator=(std::nullptr_t) {
ptr_.reset();
return *this;
......
......@@ -32,8 +32,6 @@
#include "caf/detail/parser/read_string.hpp"
#include "caf/message_builder.hpp"
CAF_PUSH_DEPRECATED_WARNING
namespace caf {
actor_system_config::~actor_system_config() {
......@@ -57,152 +55,86 @@ actor_system_config::actor_system_config()
add_message_type_impl<std::vector<actor_addr>>("std::vector<@addr>");
add_message_type_impl<std::vector<atom_value>>("std::vector<@atom>");
add_message_type_impl<std::vector<message>>("std::vector<@message>");
add_message_type_impl<config_value_map>("config_value_map");
add_message_type_impl<config_value::list>("config_value::list");
add_message_type_impl<config_value::dictionary>("config_value::dictionary");
add_message_type_impl<settings>("settings");
add_message_type_impl<config_value::list>("std::vector<@config_value>");
add_message_type_impl<config_value::dictionary>("dictionary<@config_value>");
// (1) hard-coded defaults
stream_desired_batch_complexity = defaults::stream::desired_batch_complexity;
stream_max_batch_delay = defaults::stream::max_batch_delay;
stream_credit_round_interval = defaults::stream::credit_round_interval;
namespace sr = defaults::scheduler;
auto to_ms = [](timespan x) {
return static_cast<size_t>(x.count() / 1000000);
};
scheduler_policy = sr::policy;
scheduler_max_threads = sr::max_threads;
scheduler_max_throughput = sr::max_throughput;
scheduler_enable_profiling = false;
scheduler_profiling_ms_resolution = to_ms(sr::profiling_resolution);
namespace ws = defaults::work_stealing;
auto to_us = [](timespan x) {
return static_cast<size_t>(x.count() / 1000);
};
work_stealing_aggressive_poll_attempts = ws::aggressive_poll_attempts;
work_stealing_aggressive_steal_interval = ws::aggressive_steal_interval;
work_stealing_moderate_poll_attempts = ws::moderate_poll_attempts;
work_stealing_moderate_steal_interval = ws::moderate_steal_interval;
work_stealing_moderate_sleep_duration_us = to_us(ws::moderate_sleep_duration);
work_stealing_relaxed_steal_interval = ws::relaxed_steal_interval;
work_stealing_relaxed_sleep_duration_us = to_us(ws::relaxed_sleep_duration);
namespace lg = defaults::logger;
logger_file_name = lg::file_name;
logger_file_format = lg::file_format;
logger_console = lg::console;
logger_console_format = lg::console_format;
logger_inline_output = false;
logger_verbosity = lg::file_verbosity;
namespace mm = defaults::middleman;
middleman_network_backend = mm::network_backend;
middleman_enable_automatic_connections = false;
middleman_max_consecutive_reads = mm::max_consecutive_reads;
middleman_heartbeat_interval = mm::heartbeat_interval;
middleman_detach_utility_actors = true;
middleman_detach_multiplexer = true;
middleman_cached_udp_buffers = mm::cached_udp_buffers;
middleman_max_pending_msgs = mm::max_pending_msgs;
// fill our options vector for creating INI and CLI parsers
using std::string;
opt_group{custom_options_, "global"}
.add<bool>("help,h?", "print help and exit")
.add<bool>("long-help", "print all help options and exit")
.add<bool>("dump-config", "print configuration in INI format and exit");
.add<bool>("help,h?", "print help text to STDERR and exit")
.add<bool>("long-help", "print long help text to STDERR and exit")
.add<bool>("dump-config", "print configuration to STDERR and exit");
opt_group{custom_options_, "stream"}
.add(stream_desired_batch_complexity, "desired-batch-complexity",
"sets the desired timespan for a single batch")
.add(stream_max_batch_delay, "max-batch-delay",
"sets the maximum delay for sending underfull batches")
.add(stream_credit_round_interval, "credit-round-interval",
"sets the length of credit intervals");
.add<timespan>(stream_desired_batch_complexity, "desired-batch-complexity",
"processing time per batch")
.add<timespan>(stream_max_batch_delay, "max-batch-delay",
"maximum delay for partial batches")
.add<timespan>(stream_credit_round_interval, "credit-round-interval",
"time between emitting credit");
opt_group{custom_options_, "scheduler"}
.add(scheduler_policy, "policy",
"sets the scheduling policy to either 'stealing' (default) or 'sharing'")
.add(scheduler_max_threads, "max-threads",
"sets a fixed number of worker threads for the scheduler")
.add(scheduler_max_throughput, "max-throughput",
"sets the maximum number of messages an actor consumes before yielding")
.add(scheduler_enable_profiling, "enable-profiling",
"enables or disables profiler output")
.add_ms(scheduler_profiling_ms_resolution, "profiling-ms-resolution",
"deprecated (use profiling-resolution instead)")
.add_ms(scheduler_profiling_ms_resolution, "profiling-resolution",
"sets the rate in ms in which the profiler collects data")
.add(scheduler_profiling_output_file, "profiling-output-file",
"sets the output file for the profiler");
.add<atom_value>("policy", "'stealing' (default) or 'sharing'")
.add<size_t>("max-threads", "maximum number of worker threads")
.add<size_t>("max-throughput", "nr. of messages actors can consume per run")
.add<bool>("enable-profiling", "enables profiler output")
.add<timespan>("profiling-resolution", "data collection rate")
.add<string>("profiling-output-file", "output file for the profiler");
opt_group(custom_options_, "work-stealing")
.add(work_stealing_aggressive_poll_attempts, "aggressive-poll-attempts",
"number of zero-sleep-interval polling attempts")
.add(work_stealing_aggressive_steal_interval, "aggressive-steal-interval",
"frequency of steal attempts during aggressive polling")
.add(work_stealing_moderate_poll_attempts, "moderate-poll-attempts",
"number of moderately aggressive polling attempts")
.add(work_stealing_moderate_steal_interval, "moderate-steal-interval",
"frequency of steal attempts during moderate polling")
.add_us(work_stealing_moderate_sleep_duration_us, "moderate-sleep-duration",
"sleep duration between poll attempts during moderate polling")
.add(work_stealing_relaxed_steal_interval, "relaxed-steal-interval",
"frequency of steal attempts during relaxed polling")
.add_us(work_stealing_relaxed_sleep_duration_us, "relaxed-sleep-duration",
"sleep duration between poll attempts during relaxed polling");
.add<size_t>("aggressive-poll-attempts", "nr. of aggressive steal attempts")
.add<size_t>("aggressive-steal-interval",
"frequency of aggressive steal attempts")
.add<size_t>("moderate-poll-attempts", "nr. of moderate steal attempts")
.add<size_t>("moderate-steal-interval",
"frequency of moderate steal attempts")
.add<timespan>("moderate-sleep-duration",
"sleep duration between moderate steal attempts")
.add<size_t>("relaxed-steal-interval",
"frequency of relaxed steal attempts")
.add<timespan>("relaxed-sleep-duration",
"sleep duration between relaxed steal attempts");
opt_group{custom_options_, "logger"}
.add(logger_file_name, "file-name",
"sets the filesystem path of the log file")
.add(logger_file_format, "file-format",
"sets the line format for individual log file entires")
.add<atom_value>("file-verbosity",
"sets the file output verbosity (quiet|error|warning|info|debug|trace)")
.add(logger_console, "console",
"sets the type of output to std::clog (none|colored|uncolored)")
.add(logger_console_format, "console-format",
"sets the line format for printing individual log entires")
.add<atom_value>("console-verbosity",
"sets the console output verbosity "
"(quiet|error|warning|info|debug|trace)")
.add(logger_component_filter, "component-filter",
"DEPRECATED/IGNORED, use component-blacklist instead")
.add<std::vector<atom_value>>("component-blacklist",
"exclude all listed components from logging")
.add(logger_verbosity, "verbosity",
"set file and console verbosity (deprecated)")
.add(logger_inline_output, "inline-output",
"sets whether a separate thread is used for I/O");
.add<atom_value>("verbosity", "default verbosity for file and console")
.add<string>("file-name", "filesystem path of the log file")
.add<string>("file-format", "line format for individual log file entires")
.add<atom_value>("file-verbosity", "file output verbosity")
.add<atom_value>("console", "std::clog output: none, colored, or uncolored")
.add<string>("console-format", "line format for printed log entires")
.add<atom_value>("console-verbosity", "console output verbosity")
.add<std::vector<atom_value>>("component-blacklist",
"excluded components for logging")
.add<bool>("inline-output", "disable logger thread (for testing only!)");
opt_group{custom_options_, "middleman"}
.add(middleman_network_backend, "network-backend",
"sets the network backend to either 'default' or 'asio' (if available)")
.add(middleman_app_identifier, "app-identifier",
"sets the application identifier of this node")
.add(middleman_enable_automatic_connections, "enable-automatic-connections",
"enables automatic connection management")
.add(middleman_max_consecutive_reads, "max-consecutive-reads",
"sets the maximum number of consecutive I/O reads per broker")
.add(middleman_heartbeat_interval, "heartbeat-interval",
"sets the interval (ms) of heartbeat, 0 (default) means disabling it")
.add(middleman_detach_utility_actors, "detach-utility-actors",
"deprecated, see attach-utility-actors instead")
.add_neg(middleman_detach_utility_actors, "attach-utility-actors",
"schedule utility actors instead of dedicating individual threads")
.add(middleman_detach_multiplexer, "detach-multiplexer",
"deprecated, see manual-multiplexing instead")
.add_neg(middleman_detach_multiplexer, "manual-multiplexing",
"disables background activity of the multiplexer")
.add(middleman_cached_udp_buffers, "cached-udp-buffers",
"sets the maximum for cached UDP send buffers (default: 10)")
.add(middleman_max_pending_msgs, "max-pending-messages",
"sets the maximum for reordering of UDP receive buffers (default: 10)")
.add<bool>("disable-tcp", "disables communication via TCP")
.add<bool>("enable-udp", "enable communication via UDP");
.add<atom_value>("network-backend",
"either 'default' or 'asio' (if available)")
.add<string>("app-identifier", "application identifier of this node")
.add<bool>("enable-automatic-connections",
"enables automatic connection management")
.add<size_t>("max-consecutive-reads",
"max. number of consecutive reads per broker")
.add<timespan>("heartbeat-interval", "interval of heartbeat messages")
.add<bool>("attach-utility-actors",
"schedule utility actors instead of dedicating threads")
.add<bool>("manual-multiplexing",
"disables background activity of the multiplexer")
.add<size_t>("cached-udp-buffers",
"maximum for cached UDP send buffers (default: 10)")
.add<size_t>("max-pending-messages",
"maximum for reordering of UDP receive buffers (default: 10)")
.add<bool>("disable-tcp", "disables communication via TCP")
.add<bool>("enable-udp", "enable communication via UDP");
opt_group(custom_options_, "opencl")
.add(opencl_device_ids, "device-ids",
"restricts which OpenCL devices are accessed by CAF");
.add<std::vector<size_t>>("device-ids", "whitelist for OpenCL devices");
opt_group(custom_options_, "openssl")
.add(openssl_certificate, "certificate",
"sets the path to the file containining the certificate for this node PEM format")
.add(openssl_key, "key",
"sets the path to the file containting the private key for this node")
.add(openssl_passphrase, "passphrase",
"sets the passphrase to decrypt the private key, if needed")
.add(openssl_capath, "capath",
"sets the path to an OpenSSL-style directory of trusted certificates")
.add(openssl_cafile, "cafile",
"sets the path to a file containing trusted certificates concatenated together in PEM format");
.add<string>("certificate", "path to the PEM-formatted certificate file")
.add<string>("key", "path to the private key file for this node")
.add<string>("passphrase", "passphrase to decrypt the private key")
.add<string>("capath",
"path to an OpenSSL-style directory of trusted certificates")
.add<string>("cafile",
"path to a file of concatenated PEM-formatted certificates");
// add renderers for default error categories
error_renderers.emplace(atom("system"), render_sec);
error_renderers.emplace(atom("exit"), render_exit_reason);
......@@ -243,16 +175,15 @@ actor_system_config::make_help_text(const std::vector<message::cli_arg>& xs) {
return oss.str();
}
actor_system_config& actor_system_config::parse(int argc, char** argv,
const char* ini_file_cstr) {
error actor_system_config::parse(int argc, char** argv,
const char* ini_file_cstr) {
string_list args;
if (argc > 1)
args.assign(argv + 1, argv + argc);
return parse(std::move(args), ini_file_cstr);
}
actor_system_config& actor_system_config::parse(int argc, char** argv,
std::istream& ini) {
error actor_system_config::parse(int argc, char** argv, std::istream& ini) {
string_list args;
if (argc > 1)
args.assign(argv + 1, argv + argc);
......@@ -295,16 +226,7 @@ bool operator!=(ini_iter iter, ini_sentinel) {
} // namespace <anonymous>
actor_system_config& actor_system_config::parse(string_list args,
std::istream& ini) {
// Insert possibly user-defined values into the map to respect overrides to
// member variables.
// TODO: remove with CAF 0.17
for (auto& opt : custom_options_) {
auto val = opt.get();
if (val)
content[opt.category()][opt.long_name()] = std::move(*val);
}
error actor_system_config::parse(string_list args, std::istream& ini) {
// Content of the INI file overrides hard-coded defaults.
if (ini.good()) {
detail::ini_consumer consumer{custom_options_, content};
......@@ -312,14 +234,14 @@ actor_system_config& actor_system_config::parse(string_list args,
res.i = ini_iter{&ini};
detail::parser::read_ini(res, consumer);
if (res.i != res.e)
std::cerr << "*** error in config file [line " << res.line << " col "
<< res.column << "]: " << to_string(res.code) << std::endl;
return make_error(res.code, res.line, res.column);
}
// CLI options override the content of the INI file.
using std::make_move_iterator;
auto res = custom_options_.parse(content, args);
if (res.second != args.end()) {
if (res.first != pec::success) {
return make_error(res.first, *res.second);
std::cerr << "error: at argument \"" << *res.second
<< "\": " << to_string(res.first) << std::endl;
cli_helptext_printed = true;
......@@ -328,8 +250,6 @@ actor_system_config& actor_system_config::parse(string_list args,
first += std::distance(args.cbegin(), res.second);
remainder.insert(remainder.end(), make_move_iterator(first),
make_move_iterator(args.end()));
args_remainder = message_builder{remainder.begin(), remainder.end()}
.move_to_message();
} else {
cli_helptext_printed = get_or(content, "global.help", false)
|| get_or(content, "global.long-help", false);
......@@ -342,19 +262,20 @@ actor_system_config& actor_system_config::parse(string_list args,
// Generate INI dump if needed.
if (!cli_helptext_printed && get_or(content, "global.dump-config", false)) {
for (auto& category : content) {
std::cout << '[' << category.first << "]\n";
for (auto& kvp : category.second)
if (kvp.first != "dump-config")
std::cout << kvp.first << '=' << to_string(kvp.second) << '\n';
if (auto dict = get_if<config_value::dictionary>(&category.second)) {
std::cout << '[' << category.first << "]\n";
for (auto& kvp : *dict)
if (kvp.first != "dump-config")
std::cout << kvp.first << '=' << to_string(kvp.second) << '\n';
}
}
std::cout << std::flush;
cli_helptext_printed = true;
}
return *this;
return none;
}
actor_system_config& actor_system_config::parse(string_list args,
const char* ini_file_cstr) {
error actor_system_config::parse(string_list args, const char* ini_file_cstr) {
// Override default config file name if set by user.
if (ini_file_cstr != nullptr)
config_file_path = ini_file_cstr;
......@@ -364,24 +285,6 @@ actor_system_config& actor_system_config::parse(string_list args,
return parse(std::move(args), ini);
}
actor_system_config& actor_system_config::parse(message& msg,
const char* ini_file_cstr) {
string_list args;
for (size_t i = 0; i < msg.size(); ++i)
if (msg.match_element<std::string>(i))
args.emplace_back(msg.get_as<std::string>(i));
return parse(std::move(args), ini_file_cstr);
}
actor_system_config& actor_system_config::parse(message& msg,
std::istream& ini) {
string_list args;
for (size_t i = 0; i < msg.size(); ++i)
if (msg.match_element<std::string>(i))
args.emplace_back(msg.get_as<std::string>(i));
return parse(std::move(args), ini);
}
actor_system_config&
actor_system_config::add_actor_factory(std::string name, actor_factory fun) {
actor_factories.emplace(std::move(name), std::move(fun));
......@@ -399,7 +302,8 @@ actor_system_config& actor_system_config::set_impl(string_view name,
auto opt = custom_options_.qualified_name_lookup(name);
if (opt != nullptr && opt->check(value) == none) {
opt->store(value);
content[opt->category()][opt->long_name()] = std::move(value);
auto& dict = content[opt->category()].as_dictionary();
dict[opt->long_name()] = std::move(value);
}
return *this;
}
......@@ -410,10 +314,6 @@ timespan actor_system_config::stream_tick_duration() const noexcept {
return timespan{ns_count};
}
timespan actor_system_config::streaming_credit_round_interval() const noexcept {
return stream_credit_round_interval;
}
std::string actor_system_config::render_sec(uint8_t x, atom_value,
const message& xs) {
auto tmp = static_cast<sec>(x);
......@@ -428,6 +328,13 @@ std::string actor_system_config::render_exit_reason(uint8_t x, atom_value,
meta::omittable_if_empty(), xs);
}
std::string actor_system_config::render_pec(uint8_t x, atom_value,
const message& xs) {
auto tmp = static_cast<exit_reason>(x);
return deep_to_string(meta::type_name("parser_error"), tmp,
meta::omittable_if_empty(), xs);
}
void actor_system_config::extract_config_file_path(string_list& args) {
static constexpr const char needle[] = "--caf#config-file=";
auto last = args.end();
......@@ -465,11 +372,8 @@ void actor_system_config::extract_config_file_path(string_list& args) {
args.erase(i);
}
const dictionary<dictionary<config_value>>&
content(const actor_system_config& cfg) {
const settings& content(const actor_system_config& cfg) {
return cfg.content;
}
} // namespace caf
CAF_POP_WARNINGS
......@@ -111,7 +111,7 @@ std::string config_option_set::help_text(bool global_only) const {
return std::move(builder.result);
}
auto config_option_set::parse(config_map& config, argument_iterator first,
auto config_option_set::parse(settings& config, argument_iterator first,
argument_iterator last) const
-> std::pair<pec, argument_iterator> {
// Sanity check.
......@@ -124,7 +124,10 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
auto opt_name = opt.long_name();
auto opt_ctg = opt.category();
// Try inserting a new submap into the config or fill existing one.
auto& submap = config[opt_ctg];
auto& entry = config[opt_ctg];
if (!holds_alternative<config_value::dictionary>(entry))
entry = config_value::dictionary{};
auto& submap = get<config_value::dictionary>(entry);
// Flags only consume the current element.
if (opt.is_flag()) {
if (arg_begin != arg_end)
......@@ -223,7 +226,7 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
}
config_option_set::parse_result
config_option_set::parse(config_map& config,
config_option_set::parse(settings& config,
const std::vector<string>& args) const {
return parse(config, args.begin(), args.end());
}
......
......@@ -100,6 +100,17 @@ void config_value::convert_to_list() {
data_ = std::vector<config_value>{std::move(tmp)};
}
config_value::list& config_value::as_list() {
convert_to_list();
return get<list>(*this);
}
config_value::dictionary& config_value::as_dictionary() {
if (!holds_alternative<dictionary>(*this))
*this = dictionary{};
return get<dictionary>(*this);
}
void config_value::append(config_value x) {
convert_to_list();
get<list>(data_).emplace_back(std::move(x));
......@@ -125,81 +136,5 @@ std::string to_string(const config_value& x) {
return deep_to_string(x.get_data());
}
std::string get_or(const config_value::dictionary& xs, const std::string& name,
const char* default_value) {
auto result = get_if<std::string>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
std::string get_or(const dictionary<config_value::dictionary>& xs,
string_view name, const char* default_value) {
auto result = get_if<std::string>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
std::string get_or(const actor_system_config& cfg, string_view name,
const char* default_value) {
return get_or(content(cfg), name, default_value);
}
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value) {
// Sanity check.
if (path.empty())
return;
// Navigate path.
auto last = path.end();
auto back = last - 1;
auto current = &dict;
// Resolve path by navigating the map-of-maps of create the necessary layout
// when needed.
for (auto i = path.begin(); i != back; ++i) {
auto iter = current->emplace(*i, config_value::dictionary{}).first;
if (auto val = get_if<config_value::dictionary>(&iter->second)) {
current = val;
} else {
iter->second = config_value::dictionary{};
current = &get<config_value::dictionary>(iter->second);
}
}
// Set key-value pair on the leaf.
current->insert_or_assign(*back, std::move(value));
}
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value) {
std::vector<string_view> path;
split(path, key, ".");
put_impl(dict, path, value);
}
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value) {
// Split the name into a path.
std::vector<string_view> path;
split(path, key, ".");
// Sanity check. At the very least, we need a category and a key.
if (path.size() < 2)
return;
auto category = path.front();
path.erase(path.begin());
put_impl(dict[category], path, value);
}
config_value::list& put_list(config_value::dictionary& xs, std::string name) {
auto i = xs.insert_or_assign(std::move(name), config_value::list{});
return get<config_value::list>(i.first->second);
}
config_value::dictionary& put_dictionary(config_value::dictionary& xs,
std::string name) {
auto i = xs.insert_or_assign(std::move(name), config_value::dictionary{});
return get<config_value::dictionary>(i.first->second);
}
} // namespace caf
......@@ -53,7 +53,7 @@ const timespan credit_round_interval = ms(10);
namespace scheduler {
const atom_value policy = atom("stealing");
const char* profiling_output_file = "";
string_view profiling_output_file = "";
const size_t max_threads = std::max(std::thread::hardware_concurrency(), 4u);
const size_t max_throughput = std::numeric_limits<size_t>::max();
const timespan profiling_resolution = ms(100);
......@@ -74,19 +74,19 @@ const timespan relaxed_sleep_duration = ms(10);
namespace logger {
const char* component_filter = "";
string_view component_filter = "";
const atom_value console = atom("none");
const char* console_format = "%m";
string_view console_format = "%m";
const atom_value console_verbosity = atom("trace");
const char* file_format = "%r %c %p %a %t %C %M %F:%L %m%n";
const char* file_name = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
string_view file_format = "%r %c %p %a %t %C %M %F:%L %m%n";
string_view file_name = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
const atom_value file_verbosity = atom("trace");
} // namespace logger
namespace middleman {
const char* app_identifier = "";
string_view app_identifier = "";
const atom_value network_backend = atom("default");
const size_t max_consecutive_reads = 50;
const size_t heartbeat_interval = 0;
......
......@@ -153,7 +153,7 @@ ini_consumer* ini_category_consumer::dparent() {
// -- ini_consumer -------------------------------------------------------------
ini_consumer::ini_consumer(config_option_set& options, config_map& cfg)
ini_consumer::ini_consumer(config_option_set& options, settings& cfg)
: options_(options),
cfg_(cfg) {
// nop
......@@ -168,13 +168,15 @@ void ini_consumer::key(std::string name) {
}
void ini_consumer::value_impl(config_value&& x) {
auto dict = get_if<config_value::dictionary>(&x);
if (dict != nullptr && !dict->empty()) {
using dict_type = config_value::dictionary;
auto dict = get_if<dict_type>(&x);
auto& dst = cfg_.emplace(current_key, dict_type{}).first->second;
if (dict != nullptr && !dict->empty() && holds_alternative<dict_type>(dst)) {
auto& dst_dict = get<dict_type>(dst);
// We need to "merge" values into the destination, because it can already
// contain any number of unrelated entries.
auto& dst = cfg_[current_key];
for (auto& entry : *dict)
dst.insert_or_assign(entry.first, std::move(entry.second));
dst_dict.insert_or_assign(entry.first, std::move(entry.second));
}
}
......
......@@ -18,6 +18,7 @@
#include "caf/pec.hpp"
#include "caf/config_value.hpp"
#include "caf/error.hpp"
#include "caf/make_message.hpp"
......@@ -53,9 +54,18 @@ error make_error(pec code) {
}
error make_error(pec code, size_t line, size_t column) {
config_value::dictionary context;
context["line"] = line;
context["column"] = column;
return {static_cast<uint8_t>(code), atom("parser"),
make_message(static_cast<uint32_t>(line),
static_cast<uint32_t>(column))};
make_message(std::move(context))};
}
error make_error(pec code, std::string argument) {
config_value::dictionary context;
context["argument"] = std::move(argument);
return {static_cast<uint8_t>(code), atom("parser"),
make_message(std::move(context))};
}
const char* to_string(pec x) {
......
......@@ -16,15 +16,58 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/settings.hpp"
namespace caf {
/// Tag type to select the unsafe constructor of actor handles.
struct unsafe_actor_handle_init_t { };
std::string get_or(const settings& xs, string_view name,
string_view default_value) {
auto result = get_if<std::string>(&xs, name);
if (result)
return std::move(*result);
return std::string{default_value.begin(), default_value.end()};
}
static constexpr unsafe_actor_handle_init_t unsafe_actor_handle_init
= unsafe_actor_handle_init_t{};
config_value& put_impl(settings& dict, const std::vector<string_view>& path,
config_value& value) {
// Sanity check.
CAF_ASSERT(!path.empty());
// Navigate path.
auto last = path.end();
auto back = last - 1;
auto current = &dict;
// Resolve path by navigating the map-of-maps of create the necessary layout
// when needed.
for (auto i = path.begin(); i != back; ++i) {
auto iter = current->emplace(*i, settings{}).first;
if (auto val = get_if<settings>(&iter->second)) {
current = val;
} else {
iter->second = settings{};
current = &get<settings>(iter->second);
}
}
// Set key-value pair on the leaf.
auto iter = current->insert_or_assign(*back, std::move(value)).first;
return iter->second;
}
} // namespace caf
config_value& put_impl(settings& dict, string_view key, config_value& value) {
std::vector<string_view> path;
split(path, key, ".");
return put_impl(dict, path, value);
}
config_value::list& put_list(settings& xs, std::string name) {
config_value tmp{config_value::list{}};
auto& result = put_impl(xs, name, tmp);
return get<config_value::list>(result);
}
config_value::dictionary& put_dictionary(settings& xs, std::string name) {
config_value tmp{settings{}};
auto& result = put_impl(xs, name, tmp);
return get<config_value::dictionary>(result);
}
} // namespace caf
......@@ -161,17 +161,6 @@ void test_coordinator::inline_all_enqueues_helper() {
after_next_enqueue([=] { inline_all_enqueues_helper(); });
}
std::pair<size_t, size_t>
test_coordinator::run_dispatch_loop(timespan cycle_duration) {
size_t messages = 0;
size_t timeouts = 0;
while (has_job() || has_pending_timeout()) {
messages += run();
timeouts += advance_time(cycle_duration);
}
return {messages, timeouts};
}
} // namespace caf
} // namespace scheduler
......@@ -26,6 +26,7 @@
#include "caf/test/dsl.hpp"
#include "caf/config_option_set.hpp"
#include "caf/settings.hpp"
using std::string;
using std::vector;
......@@ -75,7 +76,7 @@ CAF_TEST(parse with ref syncing) {
.add<string>(bar_s, "bar", "s,s", "")
.add<vector<string>>(bar_l, "bar", "l,l", "")
.add<dictionary<string>>(bar_d, "bar", "d,d", "");
dictionary<config_value::dictionary> cfg;
settings cfg;
vector<string> args{"-i42",
"-f",
"1e12",
......@@ -103,7 +104,7 @@ CAF_TEST(parse with ref syncing) {
CAF_TEST(implicit global) {
opts.add<int>("value", "some value").add<bool>("help", "print help text");
CAF_MESSAGE("test long option with argument");
dictionary<config_value::dictionary> cfg;
settings cfg;
auto res = opts.parse(cfg, {"--value=42"});
CAF_CHECK_EQUAL(res.first, pec::success);
CAF_CHECK_EQUAL(get_if<int>(&cfg, "global.value"), 42);
......@@ -118,7 +119,7 @@ CAF_TEST(atom parameters) {
opts.add<atom_value>("value,v", "some value");
CAF_MESSAGE("test atom option without quotes");
auto parse_args = [&](std::vector<std::string> args) -> expected<atom_value> {
dictionary<config_value::dictionary> cfg;
settings cfg;
auto res = opts.parse(cfg, std::move(args));
if (res.first != pec::success)
return res.first;
......
......@@ -250,17 +250,3 @@ CAF_TEST(unsuccessful parsing) {
CAF_CHECK_EQUAL(parse("{a=1,"), pec::unexpected_eof);
CAF_CHECK_EQUAL(parse("{a=1 b=2}"), pec::unexpected_character);
}
CAF_TEST(put values) {
using v = config_value;
using d = config_value::dictionary;
using dd = caf::dictionary<d>;
dd content;
put(content, "a.b", 42);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{42}}})}}));
put(content, "a.b.c", 1);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{d({{"c", v{1}}})}}})}}));
put(content, "a.b.d", 2);
CAF_CHECK_EQUAL(content,
dd({{"a", d({{"b", v{d({{"c", v{1}}, {"d", v{2}}})}}})}}));
}
......@@ -48,7 +48,7 @@ impl = 'foo';some atom
struct fixture {
detail::parser::state<std::string::const_iterator> res;
config_option_set options;
config_option_set::config_map config;
settings config;
fixture() {
options.add<bool>("global", "is_server", "enables server mode")
......
......@@ -535,9 +535,16 @@ struct fixture {
return *static_cast<entity*>(actor_cast<abstract_actor*>(hdl));
}
static actor_system_config& init_config(actor_system_config& cfg) {
if (auto err = cfg.parse(caf::test::engine::argc(),
caf::test::engine::argv()))
CAF_FAIL("parsing the config failed: " << to_string(err));
cfg.set("scheduler.policy", caf::atom("testing"));
return cfg;
}
fixture()
: sys(cfg.parse(caf::test::engine::argc(), caf::test::engine::argv())
.set("scheduler.policy", caf::atom("testing"))),
: sys(init_config(cfg)),
sched(dynamic_cast<scheduler_type&>(sys.scheduler())),
alice_hdl(spawn(sys, 0, "alice", tc)),
bob_hdl(spawn(sys, 1, "bob", tc)),
......
......@@ -33,6 +33,8 @@ using atomic_count = std::atomic<size_t>;
size_t assumed_thread_count;
size_t assumed_init_calls;
std::mutex mx;
struct dummy_thread_hook : thread_hook {
void init(actor_system&) override {
// nop
......
......@@ -20,9 +20,10 @@
#include <algorithm>
#include "caf/logger.hpp"
#include "caf/defaults.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/config_value.hpp"
#include "caf/defaults.hpp"
#include "caf/logger.hpp"
#include "caf/io/network/default_multiplexer.hpp"
......
......@@ -20,11 +20,11 @@
#include <algorithm>
#include "caf/logger.hpp"
#include "caf/defaults.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/config_value.hpp"
#include "caf/defaults.hpp"
#include "caf/io/network/default_multiplexer.hpp"
#include "caf/logger.hpp"
namespace caf {
namespace io {
......
......@@ -148,7 +148,10 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) {
void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)};
cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client...");
auto cl = unbox(system.middleman().spawn_client(peer_fun,
......@@ -160,7 +163,10 @@ void run_client(int argc, char** argv, uint16_t port) {
void run_server(int argc, char** argv) {
actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)};
cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
scoped_actor self{system};
CAF_MESSAGE("spawn peer acceptor");
auto serv = system.middleman().spawn_broker(peer_acceptor_fun,
......
......@@ -40,6 +40,8 @@ public:
config() {
load<io::middleman>();
add_message_type<std::vector<int>>("std::vector<int>");
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
}
};
......@@ -55,11 +57,9 @@ struct fixture {
io::middleman& client_side_mm;
fixture()
: server_side(server_side_config.parse(test::engine::argc(),
test::engine::argv())),
: server_side(server_side_config),
server_side_mm(server_side.middleman()),
client_side(client_side_config.parse(test::engine::argc(),
test::engine::argv())),
client_side(client_side_config),
client_side_mm(client_side.middleman()) {
// nop
}
......
......@@ -41,6 +41,8 @@ public:
load<io::middleman>();
set("middleman.enable-udp", true);
add_message_type<std::vector<int>>("std::vector<int>");
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
}
};
......@@ -56,11 +58,9 @@ struct fixture {
io::middleman& client_side_mm;
fixture()
: server_side(server_side_config.parse(test::engine::argc(),
test::engine::argv())),
: server_side(server_side_config),
server_side_mm(server_side.middleman()),
client_side(client_side_config.parse(test::engine::argc(),
test::engine::argv())),
client_side(client_side_config),
client_side_mm(client_side.middleman()) {
// nop
}
......
......@@ -164,7 +164,10 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self,
void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)};
cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client_typed...");
auto cl = unbox(system.middleman().spawn_client(peer_fun,
......@@ -176,7 +179,10 @@ void run_client(int argc, char** argv, uint16_t port) {
void run_server(int argc, char** argv) {
actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)};
cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
scoped_actor self{system};
auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong));
std::thread child;
......@@ -199,7 +205,5 @@ void run_server(int argc, char** argv) {
} // namespace <anonymous>
CAF_TEST(test_typed_broker) {
auto argc = test::engine::argc();
auto argv = test::engine::argv();
run_server(argc, argv);
run_server(test::engine::argc(), test::engine::argv());
}
......@@ -77,8 +77,9 @@ void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg;
cfg.load<io::middleman>()
.add_message_type<ping>("ping")
.add_message_type<pong>("pong")
.parse(argc, argv);
.add_message_type<pong>("pong");
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system sys{cfg};
// check whether invalid_argument is thrown
// when trying to connect to get an untyped
......
......@@ -53,11 +53,17 @@ public:
}
};
struct config : actor_system_config {
config() {
load<io::middleman>();
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
}
};
struct fixture {
fixture() {
new (&system) actor_system(cfg.load<io::middleman>()
.parse(test::engine::argc(),
test::engine::argv()));
new (&system) actor_system(cfg);
testee = system.spawn<dummy>();
}
......@@ -90,7 +96,7 @@ struct fixture {
return result;
}
actor_system_config cfg;
config cfg;
union { actor_system system; }; // manually control ctor/dtor
actor testee;
};
......
......@@ -556,13 +556,20 @@ public:
// -- constructors, destructors, and assignment operators --------------------
static Config& init_config(Config& cfg) {
if (auto err = cfg.parse(caf::test::engine::argc(),
caf::test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
cfg.set("scheduler.policy", caf::atom("testing"));
cfg.set("logger.inline-output", true);
cfg.set("middleman.network-backend", caf::atom("testing"));
return cfg;
}
template <class... Ts>
explicit test_coordinator_fixture(Ts&&... xs)
: cfg(std::forward<Ts>(xs)...),
sys(cfg.parse(caf::test::engine::argc(), caf::test::engine::argv())
.set("scheduler.policy", caf::atom("testing"))
.set("logger.inline-output", true)
.set("middleman.network-backend", caf::atom("testing"))),
sys(init_config(cfg)),
self(sys, true),
sched(dynamic_cast<scheduler_type&>(sys.scheduler())) {
// Configure the clock to measure each batch item with 1us.
......@@ -570,7 +577,6 @@ public:
caf::timespan{1000});
// Make sure the current time isn't 0.
sched.clock().current_time += std::chrono::hours(1);
credit_round_interval = cfg.stream_credit_round_interval;
}
virtual ~test_coordinator_fixture() {
......@@ -741,36 +747,8 @@ public:
/// Deterministic scheduler.
scheduler_type& sched;
// -- deprecated functionality -----------------------------------------------
void run_exhaustively() CAF_DEPRECATED_MSG("use run() instead");
void run_exhaustively_until(std::function<bool()> f)
CAF_DEPRECATED_MSG("use run_until() instead");
void loop_after_next_enqueue()
CAF_DEPRECATED_MSG("use run_after_next_ready_event() instead");
caf::timespan credit_round_interval CAF_DEPRECATED;
};
template <class Config>
void test_coordinator_fixture<Config>::run_exhaustively() {
run();
}
template <class Config>
void test_coordinator_fixture<Config>::run_exhaustively_until(
std::function<bool()> f) {
run_until(std::move(f));
}
template <class Config>
void test_coordinator_fixture<Config>::loop_after_next_enqueue() {
sched.after_next_enqueue([=] { run(); });
}
/// Unboxes an expected value or fails the test if it doesn't exist.
template <class T>
T unbox(caf::expected<T> x) {
......
......@@ -104,12 +104,6 @@ public:
/// Callback for triggering all nodes when simulating a network of CAF nodes.
run_all_nodes_fun run_all_nodes;
// -- deprecated functions ---------------------------------------------------
void exec_all() CAF_DEPRECATED_MSG("use run() instead") {
this->run();
}
// -- overriding member functions --------------------------------------------
bool consume_message() override {
......
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