diff options
Diffstat (limited to 'src/components/utils')
-rw-r--r-- | src/components/utils/include/utils/atomic_object.h | 109 | ||||
-rw-r--r-- | src/components/utils/include/utils/logger/boostlogger.h | 19 | ||||
-rw-r--r-- | src/components/utils/src/logger/boostlogger.cc | 71 | ||||
-rw-r--r-- | src/components/utils/test/atomic_object_test.cc | 80 |
4 files changed, 243 insertions, 36 deletions
diff --git a/src/components/utils/include/utils/atomic_object.h b/src/components/utils/include/utils/atomic_object.h new file mode 100644 index 0000000000..d1cad4b3bd --- /dev/null +++ b/src/components/utils/include/utils/atomic_object.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2022, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "utils/conditional_variable.h" +#include "utils/macro.h" +#include "utils/rwlock.h" + +namespace sync_primitives { + +/** + * @brief Allows to safely change stored value from different threads. + * + * The usage example: + * + * threads::Atomic<int> i; + * + * i = 5; // here SDL is able to guarantee that this value will be safely + * // assigned even in multi threaded environment. + */ +template <typename T> +class Atomic { + public: + /** + * @brief Atomic allows to construct atomic object. + * The operation is not atomic. + * + * @param value the value to initialize object with. + */ + Atomic(const T& value) : value_(value) {} // NOLINT(runtime/explicit) + + /** + * @brief operator = thread safe setter for stored value. + * + * @param val value to assign. + * + * @return mofified value. + */ + T& operator=(const T& val) { + sync_primitives::AutoWriteLock lock(rw_lock_); + value_ = val; + return value_; + } + + /** + * @brief operator T thread safe getter + * + * return stored value. + */ + operator T() const { + sync_primitives::AutoReadLock lock(rw_lock_); + return value_; + } + + /** + * @brief operator T thread safe getter + * + * return stored value. + */ + template <typename U> + operator U() const { + sync_primitives::AutoReadLock lock(rw_lock_); + return static_cast<U>(value_); + } + + private: + T value_; + mutable sync_primitives::RWLock rw_lock_; +}; + +typedef Atomic<int> atomic_int; +typedef Atomic<int32_t> atomic_int32; +typedef Atomic<uint32_t> atomic_uint32; +typedef Atomic<int64_t> atomic_int64; +typedef Atomic<uint64_t> atomic_uint64; +typedef Atomic<size_t> atomic_size_t; +typedef Atomic<bool> atomic_bool; + +} // namespace sync_primitives diff --git a/src/components/utils/include/utils/logger/boostlogger.h b/src/components/utils/include/utils/logger/boostlogger.h index b7eeb7ab61..06bb13049a 100644 --- a/src/components/utils/include/utils/logger/boostlogger.h +++ b/src/components/utils/include/utils/logger/boostlogger.h @@ -32,11 +32,19 @@ #pragma once #define BOOST_LOG_DYN_LINK 1 + #include <boost/date_time/posix_time/posix_time_types.hpp> +#include <boost/log/sources/severity_channel_logger.hpp> +#include <boost/log/sources/severity_logger.hpp> +#include <boost/log/trivial.hpp> #include "utils/ilogger.h" namespace logger { +namespace logging = boost::log; +namespace src = boost::log::sources; +namespace attrs = boost::log::attributes; + class BoostLogger : public ThirdPartyLoggerInterface { public: BoostLogger(const std::string& filename); @@ -47,6 +55,15 @@ class BoostLogger : public ThirdPartyLoggerInterface { void PushLog(const LogMessage& log_message) override; private: + struct LogAttributes { + attrs::mutable_constant<boost::posix_time::ptime> timestamp_; + attrs::mutable_constant<std::thread::id> thread_id_; + attrs::mutable_constant<std::string> component_; + attrs::mutable_constant<std::string> file_name_; + attrs::mutable_constant<int> line_num_; + attrs::mutable_constant<std::string> trace_; + }; + boost::posix_time::ptime GetLocalPosixTime( const logger::TimePoint& timestamp); @@ -54,6 +71,8 @@ class BoostLogger : public ThirdPartyLoggerInterface { const std::string& full_function_signature); std::string filename_; + src::severity_logger<logging::trivial::severity_level> slg_; + LogAttributes lg_attr_; }; } // namespace logger diff --git a/src/components/utils/src/logger/boostlogger.cc b/src/components/utils/src/logger/boostlogger.cc index ea85186aae..d0ef44f6fc 100644 --- a/src/components/utils/src/logger/boostlogger.cc +++ b/src/components/utils/src/logger/boostlogger.cc @@ -32,6 +32,8 @@ #include "utils/logger/boostlogger.h" +#include <boost/date_time/c_local_time_adjustor.hpp> +#include <boost/date_time/local_time_adjustor.hpp> #include <boost/format.hpp> #include <boost/log/core.hpp> #include <boost/log/expressions.hpp> @@ -40,31 +42,31 @@ #include <boost/log/sinks/text_ostream_backend.hpp> #include <boost/log/sources/logger.hpp> #include <boost/log/sources/record_ostream.hpp> -#include <boost/log/sources/severity_channel_logger.hpp> -#include <boost/log/sources/severity_logger.hpp> #include <boost/log/support/date_time.hpp> -#include <boost/log/trivial.hpp> #include <boost/log/utility/setup/common_attributes.hpp> #include <boost/log/utility/setup/file.hpp> #include <boost/log/utility/setup/from_settings.hpp> #include <boost/log/utility/setup/settings_parser.hpp> -#include <fstream> - -#include <boost/date_time/c_local_time_adjustor.hpp> -#include <boost/date_time/local_time_adjustor.hpp> - #include <boost/regex.hpp> +#include <fstream> namespace logger { -namespace logging = boost::log; -namespace src = boost::log::sources; namespace sinks = boost::log::sinks; namespace keywords = boost::log::keywords; namespace expr = boost::log::expressions; -namespace attrs = boost::log::attributes; -BoostLogger::BoostLogger(const std::string& filename) : filename_(filename) {} +BoostLogger::BoostLogger(const std::string& filename) + : filename_(filename) + , slg_() + , lg_attr_({.timestamp_ = attrs::mutable_constant<boost::posix_time::ptime>( + boost::posix_time::not_a_date_time), + .thread_id_ = attrs::mutable_constant<std::thread::id>( + std::this_thread::get_id()), + .component_ = attrs::mutable_constant<std::string>(""), + .file_name_ = attrs::mutable_constant<std::string>(""), + .line_num_ = attrs::mutable_constant<int>(0), + .trace_ = attrs::mutable_constant<std::string>("")}) {} void BoostLogger::Init() { // Add formatting parameters to INI file @@ -92,6 +94,13 @@ void BoostLogger::Init() { std::ifstream file(filename_); boost::log::settings settings = boost::log::parse_settings(file); + slg_.add_attribute("TimeStamp", lg_attr_.timestamp_); + slg_.add_attribute("ThreadId", lg_attr_.thread_id_); + slg_.add_attribute("Component", lg_attr_.component_); + slg_.add_attribute("FileName", lg_attr_.file_name_); + slg_.add_attribute("LineNum", lg_attr_.line_num_); + slg_.add_attribute("Trace", lg_attr_.trace_); + // Custom Settings if (settings.has_section("Sinks")) { @@ -161,17 +170,14 @@ boost::posix_time::ptime BoostLogger::GetLocalPosixTime( std::string BoostLogger::GetFilteredFunctionTrace( const std::string& full_function_signature) { - boost::regex function_pattern("([^\\s]*)\\((.*)\\)"); - boost::smatch results; + auto start_pos = full_function_signature.find(' '); + auto end_pos = full_function_signature.find('(', start_pos); - if (!boost::regex_search( - full_function_signature, results, function_pattern)) { - // Invalid pattern - return std::string(full_function_signature); + if (start_pos == std::string::npos || end_pos == std::string::npos || + start_pos + 1 == full_function_signature.length()) { + return full_function_signature; } - - // Get the function name(including namespaces) from the function signature - return std::string(results[1]); + return full_function_signature.substr(start_pos + 1, end_pos - start_pos - 1); } bool BoostLogger::IsEnabledFor(const std::string& component, @@ -188,21 +194,14 @@ void BoostLogger::PushLog(const LogMessage& log_message) { std::string func_name = GetFilteredFunctionTrace(log_message.location_.function_name); - src::severity_logger<logging::trivial::severity_level> slg; - slg.add_attribute("TimeStamp", - attrs::constant<boost::posix_time::ptime>(local_time)); - slg.add_attribute("ThreadId", - attrs::constant<std::thread::id>(log_message.thread_id_)); - slg.add_attribute("Component", - attrs::constant<std::string>(log_message.component_)); - slg.add_attribute( - "FileName", - attrs::constant<std::string>(log_message.location_.file_name)); - slg.add_attribute("LineNum", - attrs::constant<int>(log_message.location_.line_number)); - slg.add_attribute("Trace", attrs::constant<std::string>(func_name)); - - BOOST_LOG_SEV(slg, getBoostLogLevel(log_message.log_level_)) + lg_attr_.timestamp_.set(local_time); + lg_attr_.thread_id_.set(log_message.thread_id_); + lg_attr_.component_.set(log_message.component_); + lg_attr_.file_name_.set(log_message.location_.file_name); + lg_attr_.line_num_.set(log_message.location_.line_number); + lg_attr_.trace_.set(func_name); + + BOOST_LOG_SEV(slg_, getBoostLogLevel(log_message.log_level_)) << log_message.log_event_; } diff --git a/src/components/utils/test/atomic_object_test.cc b/src/components/utils/test/atomic_object_test.cc new file mode 100644 index 0000000000..96cc4033b1 --- /dev/null +++ b/src/components/utils/test/atomic_object_test.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, Ford Motor Company + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * + * Neither the name of the Ford Motor Company nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "utils/atomic_object.h" + +#include <string> + +#include "gtest/gtest.h" + +namespace test { +namespace utils { + +class AtomicString { + public: + AtomicString(const std::string& str) : atomic_str_(str) {} + + void SetValue(const std::string& str) { + atomic_str_ = str; + } + std::string GetValue() const { + return atomic_str_; + } + + private: + sync_primitives::Atomic<std::string> atomic_str_; +}; + +TEST(AtomicObjectTest, Construct) { + sync_primitives::atomic_int var(5); + EXPECT_EQ(5, static_cast<int>(var)); + + var = 8; + EXPECT_EQ(8, static_cast<int>(var)); + + sync_primitives::atomic_bool flag = true; + + EXPECT_EQ(true, static_cast<bool>(flag)); + + flag = false; + EXPECT_EQ(false, static_cast<bool>(flag)); + + AtomicString atomic_str("string"); + + EXPECT_EQ("string", atomic_str.GetValue()); + + atomic_str.SetValue("string2"); + EXPECT_EQ("string2", atomic_str.GetValue()); +} + +} // namespace utils +} // namespace test |