SRSLOG: Avoid calling unordered_map::emplace if element already exists since it will allocate even if the insertion is not going to take place.

master
faluco 4 years ago committed by faluco
parent af97538448
commit a474a0f293

@ -98,6 +98,9 @@ template <typename T, typename... Args>
inline T& fetch_logger(const std::string& id, Args&&... args) inline T& fetch_logger(const std::string& id, Args&&... args)
{ {
static_assert(detail::is_logger<T>::value, "T should be a logger type"); static_assert(detail::is_logger<T>::value, "T should be a logger type");
if (auto *logger = find_logger<T>(id)) {
return *logger;
}
auto logger = detail::make_any<T>(id, std::forward<Args>(args)...); auto logger = detail::make_any<T>(id, std::forward<Args>(args)...);
detail::any* p = detail::fetch_logger(id, std::move(logger)); detail::any* p = detail::fetch_logger(id, std::move(logger));

@ -28,13 +28,10 @@ static std::string remove_sharp_chars(const std::string& s)
/// Generic argument function that fetches a log channel from the repository. /// Generic argument function that fetches a log channel from the repository.
template <typename... Args> template <typename... Args>
static log_channel& fetch_log_channel_helper(const std::string& id, static log_channel& fetch_log_channel_helper(const std::string& id, Args&&... args)
Args&&... args)
{ {
return srslog_instance::get().get_channel_repo().emplace( return srslog_instance::get().get_channel_repo().emplace(
std::piecewise_construct, std::piecewise_construct, std::forward_as_tuple(id), std::forward_as_tuple(id, std::forward<Args>(args)...));
std::forward_as_tuple(id),
std::forward_as_tuple(id, std::forward<Args>(args)...));
} }
/// ///
@ -51,21 +48,27 @@ log_channel& srslog::fetch_log_channel(const std::string& id)
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
std::string clean_id = remove_sharp_chars(id); std::string clean_id = remove_sharp_chars(id);
if (auto* c = find_log_channel(clean_id)) {
return *c;
}
srslog_instance& instance = srslog_instance::get(); srslog_instance& instance = srslog_instance::get();
return fetch_log_channel_helper( return fetch_log_channel_helper(clean_id, instance.get_default_sink(), instance.get_backend());
clean_id, instance.get_default_sink(), instance.get_backend());
} }
log_channel& srslog::fetch_log_channel(const std::string& id, log_channel& srslog::fetch_log_channel(const std::string& id, sink& s, log_channel_config config)
sink& s,
log_channel_config config)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
std::string clean_id = remove_sharp_chars(id); std::string clean_id = remove_sharp_chars(id);
if (auto* c = find_log_channel(clean_id)) {
return *c;
}
srslog_instance& instance = srslog_instance::get(); srslog_instance& instance = srslog_instance::get();
return fetch_log_channel_helper( return fetch_log_channel_helper(clean_id, s, instance.get_backend(), std::move(config));
clean_id, s, instance.get_backend(), std::move(config));
} }
/// ///
@ -112,40 +115,46 @@ sink* srslog::find_sink(const std::string& id)
return (ptr) ? ptr->get() : nullptr; return (ptr) ? ptr->get() : nullptr;
} }
sink& srslog::fetch_stdout_sink(const std::string& id, sink& srslog::fetch_stdout_sink(const std::string& id, std::unique_ptr<log_formatter> f)
std::unique_ptr<log_formatter> f)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
if (auto* s = find_sink(id)) {
return *s;
}
auto& s = srslog_instance::get().get_sink_repo().emplace( auto& s = srslog_instance::get().get_sink_repo().emplace(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(id), std::forward_as_tuple(id),
std::forward_as_tuple( std::forward_as_tuple(new stream_sink(sink_stream_type::stdout, std::move(f))));
new stream_sink(sink_stream_type::stdout, std::move(f))));
return *s; return *s;
} }
sink& srslog::fetch_stderr_sink(const std::string& id, sink& srslog::fetch_stderr_sink(const std::string& id, std::unique_ptr<log_formatter> f)
std::unique_ptr<log_formatter> f)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
if (auto* s = find_sink(id)) {
return *s;
}
auto& s = srslog_instance::get().get_sink_repo().emplace( auto& s = srslog_instance::get().get_sink_repo().emplace(
std::piecewise_construct, std::piecewise_construct,
std::forward_as_tuple(id), std::forward_as_tuple(id),
std::forward_as_tuple( std::forward_as_tuple(new stream_sink(sink_stream_type::stderr, std::move(f))));
new stream_sink(sink_stream_type::stderr, std::move(f))));
return *s; return *s;
} }
sink& srslog::fetch_file_sink(const std::string& path, sink& srslog::fetch_file_sink(const std::string& path, size_t max_size, std::unique_ptr<log_formatter> f)
size_t max_size,
std::unique_ptr<log_formatter> f)
{ {
assert(!path.empty() && "Empty path string"); assert(!path.empty() && "Empty path string");
if (auto* s = find_sink(path)) {
return *s;
}
//:TODO: GCC5 or lower versions emits an error if we use the new() expression //:TODO: GCC5 or lower versions emits an error if we use the new() expression
// directly, use redundant piecewise_construct instead. // directly, use redundant piecewise_construct instead.
auto& s = srslog_instance::get().get_sink_repo().emplace( auto& s = srslog_instance::get().get_sink_repo().emplace(
@ -160,9 +169,8 @@ bool srslog::install_custom_sink(const std::string& id, std::unique_ptr<sink> s)
{ {
assert(!id.empty() && "Empty path string"); assert(!id.empty() && "Empty path string");
sink* input_sink = s.get(); sink* input_sink = s.get();
sink* returned_sink = sink* returned_sink = srslog_instance::get().get_sink_repo().emplace(id, std::move(s)).get();
srslog_instance::get().get_sink_repo().emplace(id, std::move(s)).get();
// Successful insertion occurs when the returned object is the same one as the // Successful insertion occurs when the returned object is the same one as the
// input object. // input object.
@ -190,7 +198,7 @@ void srslog::flush()
// The backend will set this shared variable when done. // The backend will set this shared variable when done.
detail::shared_variable<bool> completion_flag(false); detail::shared_variable<bool> completion_flag(false);
auto sink_ptrs = instance.get_sink_repo().contents(); auto sink_ptrs = instance.get_sink_repo().contents();
std::vector<sink*> sinks; std::vector<sink*> sinks;
sinks.reserve(sink_ptrs.size()); sinks.reserve(sink_ptrs.size());
for (const auto& s : sink_ptrs) { for (const auto& s : sink_ptrs) {
@ -199,8 +207,8 @@ void srslog::flush()
detail::log_entry cmd; detail::log_entry cmd;
cmd.metadata.store = nullptr; cmd.metadata.store = nullptr;
cmd.flush_cmd = std::unique_ptr<detail::flush_backend_cmd>( cmd.flush_cmd =
new detail::flush_backend_cmd{completion_flag, std::move(sinks)}); std::unique_ptr<detail::flush_backend_cmd>(new detail::flush_backend_cmd{completion_flag, std::move(sinks)});
// Make sure the flush command gets into the backend, otherwise we will be // Make sure the flush command gets into the backend, otherwise we will be
// stuck waiting forever for the command to succeed. // stuck waiting forever for the command to succeed.
@ -227,12 +235,10 @@ detail::any* srslog::detail::find_logger(const std::string& id)
return srslog_instance::get().get_logger_repo().find(id); return srslog_instance::get().get_logger_repo().find(id);
} }
detail::any* srslog::detail::fetch_logger(const std::string& id, detail::any* srslog::detail::fetch_logger(const std::string& id, detail::any&& logger)
detail::any&& logger)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
return &srslog_instance::get().get_logger_repo().emplace(id, return &srslog_instance::get().get_logger_repo().emplace(id, std::move(logger));
std::move(logger));
} }
/// Builds a logger name out of the id and tag. /// Builds a logger name out of the id and tag.
@ -242,9 +248,7 @@ static std::string build_logger_name(const std::string& id, char tag)
} }
/// Fetches a logger with all its log channels. /// Fetches a logger with all its log channels.
static basic_logger& fetch_basic_logger_helper(const std::string& id, static basic_logger& fetch_basic_logger_helper(const std::string& id, sink& s, bool should_print_context)
sink& s,
bool should_print_context)
{ {
static constexpr char basic_logger_chan_tags[] = {'E', 'W', 'I', 'D'}; static constexpr char basic_logger_chan_tags[] = {'E', 'W', 'I', 'D'};
@ -253,43 +257,48 @@ static basic_logger& fetch_basic_logger_helper(const std::string& id,
// User created log channels cannot have ids with a # character, encode the // User created log channels cannot have ids with a # character, encode the
// ids here with a # to ensure all channels are unique. // ids here with a # to ensure all channels are unique.
log_channel& error = fetch_log_channel_helper( log_channel& error =
build_logger_name(id, basic_logger_chan_tags[0]), fetch_log_channel_helper(build_logger_name(id, basic_logger_chan_tags[0]),
s, s,
instance.get_backend(), instance.get_backend(),
log_channel_config{id, basic_logger_chan_tags[0], should_print_context}); log_channel_config{id, basic_logger_chan_tags[0], should_print_context});
log_channel& warning = fetch_log_channel_helper( log_channel& warning =
build_logger_name(id, basic_logger_chan_tags[1]), fetch_log_channel_helper(build_logger_name(id, basic_logger_chan_tags[1]),
s, s,
instance.get_backend(), instance.get_backend(),
log_channel_config{id, basic_logger_chan_tags[1], should_print_context}); log_channel_config{id, basic_logger_chan_tags[1], should_print_context});
log_channel& info = fetch_log_channel_helper( log_channel& info = fetch_log_channel_helper(build_logger_name(id, basic_logger_chan_tags[2]),
build_logger_name(id, basic_logger_chan_tags[2]), s,
s, instance.get_backend(),
instance.get_backend(), log_channel_config{id, basic_logger_chan_tags[2], should_print_context});
log_channel_config{id, basic_logger_chan_tags[2], should_print_context}); log_channel& debug =
log_channel& debug = fetch_log_channel_helper( fetch_log_channel_helper(build_logger_name(id, basic_logger_chan_tags[3]),
build_logger_name(id, basic_logger_chan_tags[3]), s,
s, instance.get_backend(),
instance.get_backend(), log_channel_config{id, basic_logger_chan_tags[3], should_print_context});
log_channel_config{id, basic_logger_chan_tags[3], should_print_context});
return fetch_logger<basic_logger>(id, error, warning, info, debug); return fetch_logger<basic_logger>(id, error, warning, info, debug);
} }
basic_logger& srslog::fetch_basic_logger(const std::string& id, basic_logger& srslog::fetch_basic_logger(const std::string& id, bool should_print_context)
bool should_print_context)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
return fetch_basic_logger_helper(
id, srslog_instance::get().get_default_sink(), should_print_context); if (auto* logger = find_logger<basic_logger>(id)) {
return *logger;
}
return fetch_basic_logger_helper(id, srslog_instance::get().get_default_sink(), should_print_context);
} }
basic_logger& srslog::fetch_basic_logger(const std::string& id, basic_logger& srslog::fetch_basic_logger(const std::string& id, sink& s, bool should_print_context)
sink& s,
bool should_print_context)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
if (auto* logger = find_logger<basic_logger>(id)) {
return *logger;
}
return fetch_basic_logger_helper(id, s, should_print_context); return fetch_basic_logger_helper(id, s, should_print_context);
} }
@ -299,33 +308,28 @@ basic_logger& srslog::fetch_basic_logger(const std::string& id,
/// Creates and registers a log channel. Returns a pointer to the newly created /// Creates and registers a log channel. Returns a pointer to the newly created
/// channel on success, otherwise nullptr. /// channel on success, otherwise nullptr.
static log_channel* create_and_register_log_channel(const std::string& id, static log_channel* create_and_register_log_channel(const std::string& id, sink& s)
sink& s)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
srslog_instance& instance = srslog_instance::get(); srslog_instance& instance = srslog_instance::get();
auto& p = instance.get_channel_repo().emplace( auto& p = instance.get_channel_repo().emplace(
std::piecewise_construct, std::piecewise_construct, std::forward_as_tuple(id), std::forward_as_tuple(id, s, instance.get_backend()));
std::forward_as_tuple(id),
std::forward_as_tuple(id, s, instance.get_backend()));
return &p; return &p;
} }
static log_channel* create_and_register_log_channel(const std::string& id, static log_channel* create_and_register_log_channel(const std::string& id, log_channel_config config, sink& s)
log_channel_config config,
sink& s)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
srslog_instance& instance = srslog_instance::get(); srslog_instance& instance = srslog_instance::get();
auto& p = instance.get_channel_repo().emplace( auto& p =
std::piecewise_construct, instance.get_channel_repo().emplace(std::piecewise_construct,
std::forward_as_tuple(id), std::forward_as_tuple(id),
std::forward_as_tuple(id, s, instance.get_backend(), std::move(config))); std::forward_as_tuple(id, s, instance.get_backend(), std::move(config)));
return &p; return &p;
} }
@ -364,16 +368,11 @@ sink* srslog::create_file_sink(const std::string& path, size_t max_size)
.get_sink_repo() .get_sink_repo()
.emplace(std::piecewise_construct, .emplace(std::piecewise_construct,
std::forward_as_tuple(path), std::forward_as_tuple(path),
std::forward_as_tuple(new file_sink( std::forward_as_tuple(new file_sink(path, max_size, std::unique_ptr<log_formatter>(new text_formatter))))
path,
max_size,
std::unique_ptr<log_formatter>(new text_formatter))))
.get(); .get();
} }
basic_logger* srslog::create_basic_logger(const std::string& id, basic_logger* srslog::create_basic_logger(const std::string& id, sink& s, bool should_print_context)
sink& s,
bool should_print_context)
{ {
assert(!id.empty() && "Empty id string"); assert(!id.empty() && "Empty id string");
@ -391,24 +390,16 @@ basic_logger* srslog::create_basic_logger(const std::string& id,
// without any id clashes. // without any id clashes.
log_channel* error = create_and_register_log_channel( log_channel* error = create_and_register_log_channel(
build_logger_name(id, basic_logger_chan_tags[0]), build_logger_name(id, basic_logger_chan_tags[0]), {id, basic_logger_chan_tags[0], should_print_context}, s);
{id, basic_logger_chan_tags[0], should_print_context},
s);
assert(error && "Could not create channel"); assert(error && "Could not create channel");
log_channel* warning = create_and_register_log_channel( log_channel* warning = create_and_register_log_channel(
build_logger_name(id, basic_logger_chan_tags[1]), build_logger_name(id, basic_logger_chan_tags[1]), {id, basic_logger_chan_tags[1], should_print_context}, s);
{id, basic_logger_chan_tags[1], should_print_context},
s);
assert(warning && "Could not create channel"); assert(warning && "Could not create channel");
log_channel* info = create_and_register_log_channel( log_channel* info = create_and_register_log_channel(
build_logger_name(id, basic_logger_chan_tags[2]), build_logger_name(id, basic_logger_chan_tags[2]), {id, basic_logger_chan_tags[2], should_print_context}, s);
{id, basic_logger_chan_tags[2], should_print_context},
s);
assert(info && "Could not create channel"); assert(info && "Could not create channel");
log_channel* debug = create_and_register_log_channel( log_channel* debug = create_and_register_log_channel(
build_logger_name(id, basic_logger_chan_tags[3]), build_logger_name(id, basic_logger_chan_tags[3]), {id, basic_logger_chan_tags[3], should_print_context}, s);
{id, basic_logger_chan_tags[3], should_print_context},
s);
assert(debug && "Could not create channel"); assert(debug && "Could not create channel");
return create_logger<basic_logger>(id, *error, *warning, *info, *debug); return create_logger<basic_logger>(id, *error, *warning, *info, *debug);

Loading…
Cancel
Save