summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladSemenyuk <VSemenyuk@luxoft.com>2022-06-30 00:14:53 +0300
committerGitHub <noreply@github.com>2022-06-29 17:14:53 -0400
commit483859c24bbf54fe7418f194e1e57bec9ab42b39 (patch)
treef5bf8c0642d89af4b69235cdac40f7a36ff80c7f
parentcc0ab6d75b7bef33864b8aadc1beeedc592e829e (diff)
downloadsdl_core-483859c24bbf54fe7418f194e1e57bec9ab42b39.tar.gz
Make shared pointer atomic (#3920)
* Make shared pointer atomic * Add std::string case to unit test
-rw-r--r--src/components/application_manager/include/application_manager/hmi_state.h37
-rw-r--r--src/components/application_manager/src/hmi_state.cc2
-rw-r--r--src/components/utils/include/utils/atomic_object.h109
-rw-r--r--src/components/utils/test/atomic_object_test.cc80
4 files changed, 210 insertions, 18 deletions
diff --git a/src/components/application_manager/include/application_manager/hmi_state.h b/src/components/application_manager/include/application_manager/hmi_state.h
index 8271edcbd8..745c135bde 100644
--- a/src/components/application_manager/include/application_manager/hmi_state.h
+++ b/src/components/application_manager/include/application_manager/hmi_state.h
@@ -37,6 +37,7 @@
#include <list>
#include <memory>
#include "interfaces/MOBILE_API.h"
+#include "utils/atomic_object.h"
#include "utils/macro.h"
namespace application_manager {
@@ -116,13 +117,13 @@ class HmiState {
* @return return hmi level member
*/
virtual mobile_apis::HMILevel::eType hmi_level() const {
- if (parent_) {
+ if (parent()) {
if (mobile_apis::HMILevel::INVALID_ENUM == hmi_level_) {
- return parent_->hmi_level();
+ return parent()->hmi_level();
}
// Higher values correlate to lower states
// (FULL = 0, LIMITED = 1, etc.)
- return std::max(parent_->max_hmi_level(), hmi_level_);
+ return std::max(parent()->max_hmi_level(), hmi_level_);
}
return hmi_level_;
}
@@ -132,8 +133,8 @@ class HmiState {
* @return return maximum hmi level for app
*/
virtual mobile_apis::HMILevel::eType max_hmi_level() const {
- if (parent_) {
- return parent_->max_hmi_level();
+ if (parent()) {
+ return parent()->max_hmi_level();
}
return mobile_apis::HMILevel::HMI_FULL;
}
@@ -152,14 +153,14 @@ class HmiState {
*/
virtual mobile_apis::AudioStreamingState::eType audio_streaming_state()
const {
- if (parent_) {
+ if (parent()) {
if (mobile_apis::AudioStreamingState::INVALID_ENUM ==
audio_streaming_state_) {
- return parent_->audio_streaming_state();
+ return parent()->audio_streaming_state();
}
// Higher values correlate to lower states
// (AUDIBLE = 0, ATTENUATED = 1, etc.)
- return std::max(parent_->max_audio_streaming_state(),
+ return std::max(parent()->max_audio_streaming_state(),
audio_streaming_state_);
}
return audio_streaming_state_;
@@ -171,8 +172,8 @@ class HmiState {
*/
virtual mobile_apis::AudioStreamingState::eType max_audio_streaming_state()
const {
- if (parent_) {
- return parent_->max_audio_streaming_state();
+ if (parent()) {
+ return parent()->max_audio_streaming_state();
}
return mobile_apis::AudioStreamingState::AUDIBLE;
}
@@ -183,14 +184,14 @@ class HmiState {
*/
virtual mobile_apis::VideoStreamingState::eType video_streaming_state()
const {
- if (parent_) {
+ if (parent()) {
if (mobile_apis::VideoStreamingState::INVALID_ENUM ==
video_streaming_state_) {
- return parent_->video_streaming_state();
+ return parent()->video_streaming_state();
}
// Higher values correlate to lower states
// (STREAMABLE = 0, NOT_STREAMABLE = 1)
- return std::max(parent_->max_video_streaming_state(),
+ return std::max(parent()->max_video_streaming_state(),
video_streaming_state_);
}
return video_streaming_state_;
@@ -202,8 +203,8 @@ class HmiState {
*/
virtual mobile_apis::VideoStreamingState::eType max_video_streaming_state()
const {
- if (parent_) {
- return parent_->max_video_streaming_state();
+ if (parent()) {
+ return parent()->max_video_streaming_state();
}
return mobile_apis::VideoStreamingState::STREAMABLE;
}
@@ -232,9 +233,9 @@ class HmiState {
*/
virtual mobile_apis::SystemContext::eType system_context() const {
// Parent's context should be used if not available for current state
- if (parent_ &&
+ if (parent() &&
system_context_ == mobile_apis::SystemContext::INVALID_ENUM) {
- return parent_->system_context();
+ return parent()->system_context();
}
return system_context_;
}
@@ -280,7 +281,7 @@ class HmiState {
uint32_t hmi_app_id_;
StateID state_id_;
const ApplicationManager& app_mngr_;
- HmiStatePtr parent_;
+ sync_primitives::Atomic<HmiStatePtr> parent_;
mobile_apis::WindowType::eType window_type_;
mobile_apis::HMILevel::eType hmi_level_;
mobile_apis::AudioStreamingState::eType audio_streaming_state_;
diff --git a/src/components/application_manager/src/hmi_state.cc b/src/components/application_manager/src/hmi_state.cc
index 07200af6cd..6dc3264ac0 100644
--- a/src/components/application_manager/src/hmi_state.cc
+++ b/src/components/application_manager/src/hmi_state.cc
@@ -50,6 +50,7 @@ HmiState::HmiState(std::shared_ptr<Application> app,
: hmi_app_id_(app->hmi_app_id())
, state_id_(state_id)
, app_mngr_(app_mngr)
+ , parent_(HmiStatePtr())
, window_type_(mobile_apis::WindowType::INVALID_ENUM)
, hmi_level_(mobile_apis::HMILevel::INVALID_ENUM)
, audio_streaming_state_(mobile_apis::AudioStreamingState::INVALID_ENUM)
@@ -63,6 +64,7 @@ HmiState::HmiState(std::shared_ptr<Application> app,
: hmi_app_id_(app->hmi_app_id())
, state_id_(STATE_ID_REGULAR)
, app_mngr_(app_mngr)
+ , parent_(HmiStatePtr())
, window_type_(mobile_apis::WindowType::INVALID_ENUM)
, hmi_level_(mobile_apis::HMILevel::INVALID_ENUM)
, audio_streaming_state_(mobile_apis::AudioStreamingState::INVALID_ENUM)
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/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