// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 by Apex.AI Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_posh/testing/roudi_environment/runtime_test_interface.hpp" #include "iceoryx_hoofs/cxx/helplets.hpp" #include "iceoryx_posh/internal/runtime/posh_runtime_impl.hpp" namespace iox { namespace roudi { using runtime::PoshRuntime; thread_local PoshRuntime* RuntimeTestInterface::t_activeRuntime{nullptr}; thread_local std::atomic RuntimeTestInterface::t_currentRouDiContext{0}; std::atomic RuntimeTestInterface::s_currentRouDiContext{0}; std::mutex RuntimeTestInterface::s_runtimeAccessMutex; std::map RuntimeTestInterface::s_runtimes; RuntimeTestInterface::RuntimeTestInterface() { std::lock_guard lock(RuntimeTestInterface::s_runtimeAccessMutex); iox::cxx::Expects(PoshRuntime::getRuntimeFactory() == PoshRuntime::defaultRuntimeFactory && "The RuntimeTestInterface can only be used in combination with the " "PoshRuntime::defaultRuntimeFactory! Someone else already switched the factory!"); PoshRuntime::setRuntimeFactory(RuntimeTestInterface::runtimeFactoryGetInstance); } RuntimeTestInterface::~RuntimeTestInterface() { if (m_doCleanupOnDestruction) { // cleanup holds its own lock cleanupRuntimes(); std::lock_guard lock(RuntimeTestInterface::s_runtimeAccessMutex); PoshRuntime::setRuntimeFactory(PoshRuntime::defaultRuntimeFactory); } } RuntimeTestInterface::RuntimeTestInterface(RuntimeTestInterface&& rhs) { rhs.m_doCleanupOnDestruction = false; } RuntimeTestInterface& RuntimeTestInterface::operator=(RuntimeTestInterface&& rhs) { rhs.m_doCleanupOnDestruction = false; return *this; } void RuntimeTestInterface::cleanupRuntimes() { std::lock_guard lock(RuntimeTestInterface::s_runtimeAccessMutex); for (const auto& e : RuntimeTestInterface::s_runtimes) { delete e.second; } RuntimeTestInterface::s_runtimes.clear(); RuntimeTestInterface::s_currentRouDiContext.operator++(std::memory_order_relaxed); } void RuntimeTestInterface::eraseRuntime(const RuntimeName_t& name) { std::lock_guard lock(RuntimeTestInterface::s_runtimeAccessMutex); auto iter = RuntimeTestInterface::s_runtimes.find(name); if (iter != RuntimeTestInterface::s_runtimes.end()) { delete iter->second; RuntimeTestInterface::s_runtimes.erase(name); } } PoshRuntime& RuntimeTestInterface::runtimeFactoryGetInstance(cxx::optional name) { std::lock_guard lock(RuntimeTestInterface::s_runtimeAccessMutex); auto currentRouDiContext = RuntimeTestInterface::s_currentRouDiContext.load(std::memory_order_relaxed); if (RuntimeTestInterface::t_currentRouDiContext.load(std::memory_order_relaxed) != currentRouDiContext) { RuntimeTestInterface::t_currentRouDiContext.store(currentRouDiContext, std::memory_order_relaxed); RuntimeTestInterface::t_activeRuntime = nullptr; } bool nameIsNullopt{!name.has_value()}; bool invalidGetRuntimeAccess{RuntimeTestInterface::t_activeRuntime == nullptr && nameIsNullopt}; cxx::Expects(!invalidGetRuntimeAccess); if (RuntimeTestInterface::t_activeRuntime != nullptr && nameIsNullopt) { return *RuntimeTestInterface::t_activeRuntime; } auto iter = RuntimeTestInterface::s_runtimes.find(*name.value()); if (iter != RuntimeTestInterface::s_runtimes.end()) { RuntimeTestInterface::t_activeRuntime = iter->second; } else { auto runtimeImpl = new runtime::PoshRuntimeImpl(name, runtime::RuntimeLocation::SAME_PROCESS_LIKE_ROUDI); RuntimeTestInterface::s_runtimes.insert({*name.value(), runtimeImpl}); RuntimeTestInterface::t_activeRuntime = runtimeImpl; } return *RuntimeTestInterface::t_activeRuntime; } } // namespace roudi } // namespace iox