Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
6b81e98e
Commit
6b81e98e
authored
Aug 13, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix output of --dump-config
parent
ee33f93d
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
276 additions
and
44 deletions
+276
-44
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+4
-0
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+43
-7
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+81
-9
libcaf_core/caf/settings.hpp
libcaf_core/caf/settings.hpp
+21
-19
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+108
-9
libcaf_core/src/settings.cpp
libcaf_core/src/settings.cpp
+19
-0
No files found.
libcaf_core/caf/actor_system_config.hpp
View file @
6b81e98e
...
...
@@ -106,6 +106,10 @@ public:
/// @private
settings
content
;
/// Extracts all parameters from the config, including entries with default
/// values.
virtual
settings
dump_content
()
const
;
/// Sets a config by using its INI name `config_name` to `config_value`.
template
<
class
T
>
actor_system_config
&
set
(
string_view
name
,
T
&&
value
)
{
...
...
libcaf_core/caf/config_value.hpp
View file @
6b81e98e
...
...
@@ -127,22 +127,22 @@ public:
const
char
*
type_name
()
const
noexcept
;
/// Returns the underlying variant.
inline
variant_type
&
get_data
()
{
variant_type
&
get_data
()
{
return
data_
;
}
/// Returns the underlying variant.
inline
const
variant_type
&
get_data
()
const
{
const
variant_type
&
get_data
()
const
{
return
data_
;
}
/// Returns a pointer to the underlying variant.
inline
variant_type
*
get_data_ptr
()
{
variant_type
*
get_data_ptr
()
{
return
&
data_
;
}
/// Returns a pointer to the underlying variant.
inline
const
variant_type
*
get_data_ptr
()
const
{
const
variant_type
*
get_data_ptr
()
const
{
return
&
data_
;
}
...
...
@@ -153,18 +153,22 @@ private:
// -- auto conversion of related types ---------------------------------------
inline
void
set
(
bool
x
)
{
void
set
(
bool
x
)
{
data_
=
x
;
}
inline
void
set
(
float
x
)
{
void
set
(
float
x
)
{
data_
=
static_cast
<
double
>
(
x
);
}
inline
void
set
(
const
char
*
x
)
{
void
set
(
const
char
*
x
)
{
data_
=
std
::
string
{
x
};
}
void
set
(
string_view
x
)
{
data_
=
std
::
string
{
x
.
begin
(),
x
.
end
()};
}
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
is_one_of
<
T
,
real
,
atom
,
timespan
,
uri
,
string
,
list
,
dictionary
>::
value
>
...
...
@@ -172,6 +176,38 @@ private:
data_
=
std
::
move
(
x
);
}
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
list_like
<
detail
::
decay_t
<
T
>>
()
&&
!
detail
::
same
<
detail
::
decay_t
<
T
>
,
list
>
()
>
set
(
T
&&
xs
)
{
// Move values from the old list into the new list if `xs` is an rvalue.
using
namespace
detail
;
using
xs_type
=
decltype
(
xs
);
using
value_type
=
typename
decay_t
<
T
>::
value_type
;
using
fwd_type
=
conditional_t
<
std
::
is_rvalue_reference
<
xs_type
>::
value
,
value_type
&&
,
const
value_type
&>
;
auto
&
lst
=
as_list
();
lst
.
clear
();
for
(
auto
&
x
:
xs
)
lst
.
emplace_back
(
config_value
{
static_cast
<
fwd_type
>
(
x
)});
}
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
map_like
<
detail
::
decay_t
<
T
>>
()
&&
!
detail
::
same
<
detail
::
decay_t
<
T
>
,
dictionary
>
()
>
set
(
T
&&
xs
)
{
// Move values from the old list into the new list if `xs` is an rvalue.
using
namespace
detail
;
using
xs_type
=
decltype
(
xs
);
using
mapped_type
=
typename
decay_t
<
T
>::
mapped_type
;
using
fwd_type
=
conditional_t
<
std
::
is_rvalue_reference
<
xs_type
>::
value
,
mapped_type
&&
,
const
mapped_type
&>
;
auto
&
dict
=
as_dictionary
();
dict
.
clear
();
for
(
auto
&
kvp
:
xs
)
dict
.
emplace
(
kvp
.
first
,
static_cast
<
fwd_type
>
(
kvp
.
second
));
}
template
<
class
T
>
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>
set
(
T
x
)
{
data_
=
static_cast
<
int64_t
>
(
x
);
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
6b81e98e
...
...
@@ -33,27 +33,52 @@
#include "caf/detail/type_list.hpp"
#define CAF_HAS_MEMBER_TRAIT(name) \
template <class T> \
struct has_##name##_member { \
template <class U> \
static auto sfinae(U* x) -> decltype(x->name(), std::true_type()); \
template <class T> \
class has_##name##_member { \
private: \
template <class U> \
static auto sfinae(U* x) -> decltype(x->name(), std::true_type()); \
\
template <class U>
\
static auto sfinae(...) -> std::false_type;
\
template <class U>
\
static auto sfinae(...) -> std::false_type;
\
\
using type = decltype(sfinae<T>(nullptr)); \
static constexpr bool value = type::value; \
}
using sfinae_type = decltype(sfinae<T>(nullptr)); \
\
public: \
static constexpr bool value = sfinae_type::value; \
}
#define CAF_HAS_ALIAS_TRAIT(name) \
template <class T> \
class has_##name##_alias { \
private: \
template <class C> \
static std::true_type sfinae(C* ptr, typename C::name* arg = nullptr); \
\
static std::false_type sfinae(void* ptr); \
\
using sfinae_type = decltype(sfinae(static_cast<T*>(nullptr))); \
\
public: \
static constexpr bool value = sfinae_type::value; \
}
namespace
caf
{
namespace
detail
{
// -- backport of C++14 additions ----------------------------------------------
template
<
class
T
>
using
decay_t
=
typename
std
::
decay
<
T
>::
type
;
template
<
bool
B
,
class
T
,
class
F
>
using
conditional_t
=
typename
std
::
conditional
<
B
,
T
,
F
>::
type
;
template
<
bool
V
,
class
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
V
,
T
>::
type
;
// -- custom traits ------------------------------------------------------------
template
<
class
Trait
,
class
T
=
void
>
using
enable_if_tt
=
typename
std
::
enable_if
<
Trait
::
value
,
T
>::
type
;
...
...
@@ -708,6 +733,53 @@ struct is_same_ish
template
<
class
>
struct
always_false
:
std
::
false_type
{};
// -- traits to check for STL-style type aliases -------------------------------
namespace
trait
{
CAF_HAS_ALIAS_TRAIT
(
value_type
);
CAF_HAS_ALIAS_TRAIT
(
key_type
);
CAF_HAS_ALIAS_TRAIT
(
mapped_type
);
}
// namespace trait
// -- constexpr functions for use in enable_if & friends -----------------------
/// Checks whether T behaves like a `std::map`.
template
<
class
T
>
constexpr
bool
is_container_type
()
{
return
is_iterable
<
T
>::
value
;
}
/// Checks whether T behaves like a `std::map` or a `std::unordered_map`.
template
<
class
T
>
constexpr
bool
map_like
()
{
return
is_container_type
<
T
>
()
&&
trait
::
has_key_type_alias
<
T
>::
value
&&
trait
::
has_mapped_type_alias
<
T
>::
value
;
}
/// Checks whether T behaves like a `std::vector` or a `std::list`.
template
<
class
T
>
constexpr
bool
list_like
()
{
return
is_container_type
<
T
>
()
&&
trait
::
has_value_type_alias
<
T
>::
value
&&
!
trait
::
has_key_type_alias
<
T
>::
value
&&
!
trait
::
has_mapped_type_alias
<
T
>::
value
;
}
template
<
class
A
,
class
B
>
constexpr
bool
same
()
{
return
std
::
is_same
<
A
,
B
>::
value
;
}
template
<
class
T
,
class
...
Ts
>
constexpr
bool
one_of
()
{
return
is_one_of
<
T
,
Ts
...
>::
value
;
}
}
// namespace detail
}
// namespace caf
#undef CAF_HAS_MEMBER_TRAIT
#undef CAF_HAS_ALIAS_TRAIT
libcaf_core/caf/settings.hpp
View file @
6b81e98e
...
...
@@ -30,29 +30,18 @@ namespace caf {
/// @relates config_value
using
settings
=
dictionary
<
config_value
>
;
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
const
config_value
*
get_if
(
const
settings
*
xs
,
string_view
name
);
/// 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
));
if
(
auto
value
=
get_if
(
xs
,
name
))
if
(
auto
ptr
=
get_if
<
T
>
(
value
))
return
*
ptr
;
return
none
;
}
template
<
class
T
>
...
...
@@ -92,6 +81,19 @@ config_value& put(settings& dict, string_view key, T&& value) {
return
put_impl
(
dict
,
key
,
tmp
);
}
/// Converts `value` to a `config_value` and assigns it to `key` if `value` is
/// currently missing in `xs`.
/// @param xs 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_missing
(
settings
&
xs
,
string_view
key
,
T
&&
value
)
{
if
(
get_if
(
&
xs
,
key
)
!=
nullptr
)
return
;
config_value
tmp
{
std
::
forward
<
T
>
(
value
)};
put_impl
(
xs
,
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
);
...
...
libcaf_core/src/actor_system_config.cpp
View file @
6b81e98e
...
...
@@ -148,6 +148,73 @@ actor_system_config::actor_system_config()
error_renderers
.
emplace
(
atom
(
"exit"
),
render_exit_reason
);
}
settings
actor_system_config
::
dump_content
()
const
{
settings
result
=
content
;
// -- streaming parameters
auto
&
stream_group
=
result
[
"stream"
].
as_dictionary
();
put_missing
(
stream_group
,
"desired-batch-complexity"
,
defaults
::
stream
::
desired_batch_complexity
);
put_missing
(
stream_group
,
"max-batch-delay"
,
defaults
::
stream
::
max_batch_delay
);
put_missing
(
stream_group
,
"credit-round-interval"
,
defaults
::
stream
::
credit_round_interval
);
// -- scheduler parameters
auto
&
scheduler_group
=
result
[
"scheduler"
].
as_dictionary
();
put_missing
(
scheduler_group
,
"policy"
,
defaults
::
scheduler
::
policy
);
put_missing
(
scheduler_group
,
"max-threads"
,
defaults
::
scheduler
::
max_threads
);
put_missing
(
scheduler_group
,
"max-throughput"
,
defaults
::
scheduler
::
max_throughput
);
put_missing
(
scheduler_group
,
"enable-profiling"
,
false
);
put_missing
(
scheduler_group
,
"profiling-resolution"
,
defaults
::
scheduler
::
profiling_resolution
);
put_missing
(
scheduler_group
,
"profiling-output-file"
,
std
::
string
{});
// -- work-stealing parameters
auto
&
work_stealing_group
=
result
[
"work-stealing"
].
as_dictionary
();
put_missing
(
work_stealing_group
,
"aggressive-poll-attempts"
,
defaults
::
work_stealing
::
aggressive_poll_attempts
);
put_missing
(
work_stealing_group
,
"aggressive-steal-interval"
,
defaults
::
work_stealing
::
aggressive_steal_interval
);
put_missing
(
work_stealing_group
,
"moderate-poll-attempts"
,
defaults
::
work_stealing
::
moderate_poll_attempts
);
put_missing
(
work_stealing_group
,
"moderate-steal-interval"
,
defaults
::
work_stealing
::
moderate_steal_interval
);
put_missing
(
work_stealing_group
,
"moderate-sleep-duration"
,
defaults
::
work_stealing
::
moderate_sleep_duration
);
put_missing
(
work_stealing_group
,
"relaxed-steal-interval"
,
defaults
::
work_stealing
::
relaxed_steal_interval
);
put_missing
(
work_stealing_group
,
"relaxed-sleep-duration"
,
defaults
::
work_stealing
::
relaxed_sleep_duration
);
// -- logger parameters
auto
&
logger_group
=
result
[
"logger"
].
as_dictionary
();
put_missing
(
logger_group
,
"file-name"
,
defaults
::
logger
::
file_name
);
put_missing
(
logger_group
,
"file-format"
,
defaults
::
logger
::
file_format
);
put_missing
(
logger_group
,
"file-verbosity"
,
defaults
::
logger
::
file_verbosity
);
put_missing
(
logger_group
,
"console"
,
defaults
::
logger
::
console
);
put_missing
(
logger_group
,
"console-format"
,
defaults
::
logger
::
console_format
);
put_missing
(
logger_group
,
"console-verbosity"
,
defaults
::
logger
::
console_verbosity
);
put_missing
(
logger_group
,
"component-blacklist"
,
std
::
vector
<
atom_value
>
{});
put_missing
(
logger_group
,
"inline-output"
,
false
);
// -- middleman parameters
auto
&
middleman_group
=
result
[
"middleman"
].
as_dictionary
();
put_missing
(
middleman_group
,
"app-identifiers"
,
defaults
::
middleman
::
app_identifiers
);
put_missing
(
middleman_group
,
"enable-automatic-connections"
,
false
);
put_missing
(
middleman_group
,
"max-consecutive-reads"
,
defaults
::
middleman
::
max_consecutive_reads
);
put_missing
(
middleman_group
,
"heartbeat-interval"
,
defaults
::
middleman
::
heartbeat_interval
);
put_missing
(
middleman_group
,
"workers"
,
defaults
::
middleman
::
workers
);
// -- opencl parameters
auto
&
openssl_group
=
result
[
"openssl"
].
as_dictionary
();
put_missing
(
openssl_group
,
"certificate"
,
std
::
string
{});
put_missing
(
openssl_group
,
"key"
,
std
::
string
{});
put_missing
(
openssl_group
,
"passphrase"
,
std
::
string
{});
put_missing
(
openssl_group
,
"capath"
,
std
::
string
{});
put_missing
(
openssl_group
,
"cafile"
,
std
::
string
{});
return
result
;
}
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
)
{
...
...
@@ -232,6 +299,45 @@ bool operator!=(ini_iter iter, ini_sentinel) {
return
!
iter
.
ini
->
fail
();
}
struct
indentation
{
size_t
size
;
};
indentation
operator
+
(
indentation
x
,
size_t
y
)
noexcept
{
return
{
x
.
size
+
y
};
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
indentation
indent
)
{
for
(
size_t
i
=
0
;
i
<
indent
.
size
;
++
i
)
out
.
put
(
' '
);
return
out
;
}
void
print
(
const
config_value
::
dictionary
&
xs
,
indentation
indent
)
{
using
std
::
cout
;
for
(
const
auto
&
kvp
:
xs
)
{
if
(
kvp
.
first
==
"dump-config"
)
continue
;
if
(
auto
submap
=
get_if
<
config_value
::
dictionary
>
(
&
kvp
.
second
))
{
cout
<<
indent
<<
kvp
.
first
<<
" {
\n
"
;
print
(
*
submap
,
indent
+
2
);
cout
<<
indent
<<
"}
\n
"
;
}
else
if
(
auto
lst
=
get_if
<
config_value
::
list
>
(
&
kvp
.
second
))
{
if
(
lst
->
empty
())
{
cout
<<
indent
<<
kvp
.
first
<<
" = []
\n
"
;
}
else
{
cout
<<
indent
<<
kvp
.
first
<<
" = [
\n
"
;
auto
list_indent
=
indent
+
2
;
for
(
auto
&
x
:
*
lst
)
cout
<<
list_indent
<<
to_string
(
x
)
<<
",
\n
"
;
cout
<<
indent
<<
"]
\n
"
;
}
}
else
{
cout
<<
indent
<<
kvp
.
first
<<
" = "
<<
to_string
(
kvp
.
second
)
<<
'\n'
;
}
}
};
}
// namespace <anonymous>
error
actor_system_config
::
parse
(
string_list
args
,
std
::
istream
&
ini
)
{
...
...
@@ -263,16 +369,9 @@ error actor_system_config::parse(string_list args, std::istream& ini) {
bool
long_help
=
get_or
(
content
,
"long-help"
,
false
);
std
::
cout
<<
custom_options_
.
help_text
(
!
long_help
)
<<
std
::
endl
;
}
// Generate
INI
dump if needed.
// Generate
config
dump if needed.
if
(
!
cli_helptext_printed
&&
get_or
(
content
,
"dump-config"
,
false
))
{
for
(
auto
&
category
:
content
)
{
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'
;
}
}
print
(
dump_content
(),
indentation
{
0
});
std
::
cout
<<
std
::
flush
;
cli_helptext_printed
=
true
;
}
...
...
libcaf_core/src/settings.cpp
View file @
6b81e98e
...
...
@@ -22,6 +22,25 @@
namespace
caf
{
const
config_value
*
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
nullptr
;
// We can't simply return the result here, because it might be a pointer.
return
&
i
->
second
;
}
// 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
nullptr
;
return
get_if
(
&
get
<
config_value
::
dictionary
>
(
i
->
second
),
name
.
substr
(
pos
+
1
));
}
std
::
string
get_or
(
const
settings
&
xs
,
string_view
name
,
string_view
default_value
)
{
auto
result
=
get_if
<
std
::
string
>
(
&
xs
,
name
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment