CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
250 lines
8.0 KiB
C++
250 lines
8.0 KiB
C++
// Copyright Advanced Micro Devices, Inc., or its affiliates.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
|
|
#include <rocRoller/Assemblers/Assembler.hpp>
|
|
#include <rocRoller/Utilities/Component.hpp>
|
|
#include <rocRoller/Utilities/Logging.hpp>
|
|
#include <rocRoller/Utilities/Utils.hpp>
|
|
#include <stdexcept>
|
|
|
|
namespace rocRoller
|
|
{
|
|
namespace Component
|
|
{
|
|
|
|
template <ComponentBase Base>
|
|
requires(!CSingleUse<Base>) std::shared_ptr<Base> Get(typename Base::Argument const& arg)
|
|
{
|
|
using Factory = ComponentFactory<Base>;
|
|
auto& factory = Factory::Instance();
|
|
return factory.get(arg);
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
requires(!CSingleUse<Base>) std::shared_ptr<Base> Get(typename Base::Argument&& arg)
|
|
{
|
|
using Factory = ComponentFactory<Base>;
|
|
auto const& factory = Factory::Instance();
|
|
return factory.get(arg);
|
|
}
|
|
|
|
// clang-format off
|
|
template <ComponentBase Base, typename Arg0, typename... Args>
|
|
requires(!CSingleUse<Base>
|
|
&& !std::same_as<typename Base::Argument, Arg0>
|
|
&& std::constructible_from<typename Base::Argument, Arg0, Args...>)
|
|
std::shared_ptr<Base> Get(Arg0 const& arg0, Args const&... args)
|
|
{
|
|
return Get<Base>(typename Base::Argument(arg0, args...));
|
|
}
|
|
// clang-format on
|
|
|
|
template <ComponentBase Base>
|
|
std::shared_ptr<Base> GetNew(typename Base::Argument const& arg)
|
|
{
|
|
using Factory = ComponentFactory<Base>;
|
|
auto& factory = Factory::Instance();
|
|
return factory.getNew(arg);
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
std::shared_ptr<Base> GetNew(typename Base::Argument&& arg)
|
|
{
|
|
using Factory = ComponentFactory<Base>;
|
|
auto& factory = Factory::Instance();
|
|
return factory.getNew(arg);
|
|
}
|
|
|
|
// clang-format off
|
|
template <ComponentBase Base, typename Arg0, typename... Args>
|
|
requires(!std::same_as<typename Base::Argument, Arg0>
|
|
&& std::constructible_from<typename Base::Argument, Arg0, Args...>)
|
|
std::shared_ptr<Base> GetNew(Arg0 const& arg0, Args const&... args)
|
|
{
|
|
return GetNew<Base>(typename Base::Argument(arg0, args...));
|
|
}
|
|
// clang-format on
|
|
|
|
template <Component Comp>
|
|
bool RegisterComponentImpl()
|
|
{
|
|
using Factory = ComponentFactory<typename Comp::Base>;
|
|
auto& factory = Factory::Instance();
|
|
return factory.template registerComponent<Comp>();
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
ComponentFactory<Base>::ComponentFactory()
|
|
{
|
|
ComponentFactory<Base>::registerImplementations();
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
ComponentFactory<Base>& ComponentFactory<Base>::Instance()
|
|
{
|
|
static ComponentFactory instance;
|
|
|
|
return instance;
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <typename T>
|
|
std::shared_ptr<Base> ComponentFactory<Base>::get(T&& arg) const
|
|
{
|
|
WriterLock lock{m_instanceCacheLock};
|
|
|
|
auto iter = m_instanceCache.find(arg);
|
|
|
|
if(iter != m_instanceCache.end())
|
|
{
|
|
return iter->second;
|
|
}
|
|
|
|
auto newInstance = getNew(arg);
|
|
m_instanceCache[std::forward<T>(arg)] = newInstance;
|
|
|
|
return newInstance;
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <typename T>
|
|
std::shared_ptr<Base> ComponentFactory<Base>::getNew(T&& arg) const
|
|
{
|
|
auto const& entry = getEntry(arg);
|
|
|
|
return entry.builder(std::forward<T>(arg));
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <typename T, bool Debug>
|
|
typename ComponentFactory<Base>::Entry const&
|
|
ComponentFactory<Base>::getEntry(T&& arg) const
|
|
{
|
|
WriterLock lock{m_entryCacheLock};
|
|
|
|
auto iter = m_entryCache.find(arg);
|
|
|
|
if(iter != m_entryCache.end())
|
|
{
|
|
return iter->second;
|
|
}
|
|
|
|
Entry const& e = findEntry<T, Debug>(arg);
|
|
|
|
return m_entryCache[std::forward<T>(arg)] = e;
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <typename T, bool Debug>
|
|
typename ComponentFactory<Base>::Entry const&
|
|
ComponentFactory<Base>::findEntry(T&& arg) const
|
|
{
|
|
ReaderLock lock{m_entriesLock};
|
|
|
|
auto foundIter = m_entries.end();
|
|
|
|
for(auto iter = m_entries.begin(); iter != m_entries.end(); iter++)
|
|
{
|
|
if(iter->matcher(std::forward<T>(arg)))
|
|
{
|
|
if(!Debug)
|
|
return *iter;
|
|
|
|
if(foundIter == m_entries.end())
|
|
{
|
|
foundIter = iter;
|
|
}
|
|
else
|
|
{
|
|
rocRoller::Log::warn("Multiple suitable components found for {}: {}, {}",
|
|
Base::Basename,
|
|
foundIter->name,
|
|
iter->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO Investigate why cppcheck isn't ensuring that this macro
|
|
// is expanded correctly, requiring the derefInvalidIterator
|
|
// suppression.
|
|
AssertFatal(foundIter != m_entries.end(),
|
|
Base::Basename,
|
|
": No valid component found: ",
|
|
ShowValue(arg));
|
|
|
|
// cppcheck-suppress derefInvalidIterator
|
|
return *foundIter;
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <Component Comp>
|
|
bool ComponentFactory<Base>::registerComponent()
|
|
{
|
|
return registerComponent(Comp::Name, Comp::Match, Comp::Build);
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
bool ComponentFactory<Base>::registerComponent(std::string const& name,
|
|
Matcher<Base> matcher,
|
|
Builder<Base> builder)
|
|
{
|
|
if(name == "")
|
|
throw std::runtime_error(concatenate("Empty ", Base::Basename, " component name"));
|
|
auto sameName = [&name](auto const& entry) { return entry.name == name; };
|
|
|
|
WriterLock lock{m_entriesLock};
|
|
if(std::any_of(m_entries.begin(), m_entries.end(), sameName))
|
|
throw std::runtime_error(
|
|
concatenate("Duplicate ", Base::Basename, " component names: '", name, "'"));
|
|
|
|
RegisterBase(this);
|
|
|
|
m_entries.push_back({name, matcher, builder});
|
|
|
|
return true;
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
template <typename T>
|
|
void ComponentFactory<Base>::emptyCache(T&& arg)
|
|
{
|
|
{
|
|
WriterLock lock{m_entryCacheLock};
|
|
m_entryCache.erase(arg);
|
|
}
|
|
{
|
|
WriterLock lock{m_instanceCacheLock};
|
|
m_instanceCache.erase(arg);
|
|
}
|
|
}
|
|
|
|
template <ComponentBase Base>
|
|
void ComponentFactory<Base>::emptyCache()
|
|
{
|
|
{
|
|
WriterLock lock{m_entryCacheLock};
|
|
m_entryCache.clear();
|
|
}
|
|
{
|
|
WriterLock lock{m_instanceCacheLock};
|
|
m_instanceCache.clear();
|
|
}
|
|
}
|
|
|
|
inline void ComponentFactoryBase::ClearAllCaches()
|
|
{
|
|
for(auto ins : m_instances)
|
|
ins->emptyCache();
|
|
}
|
|
|
|
inline void ComponentFactoryBase::RegisterBase(ComponentFactoryBase* base)
|
|
{
|
|
m_instances.insert(base);
|
|
}
|
|
|
|
// std::unordered_set<ComponentFactoryBase *> ComponentFactoryBase::m_instances;
|
|
}
|
|
}
|