Files
salmanoff/smocore/comparatorLibs/comparatorApiManager.cpp
T

198 lines
5.1 KiB
C++

#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <comparatorLibs/comparatorApiManager.h>
#include <loadableLib/loadableLibraryManager.h>
#include <opts.h>
#include <user/comparatorApiDesc.h>
#include <user/smoHooks.h>
namespace smo {
namespace comparator_lib {
namespace {
void registerExportedComparatorTypes(
ComparatorApiManager::Resources& resources,
const cologex::ComparatorLibDesc& libDesc)
{
for (const auto& exportedType : libDesc.exportedComparatorTypes)
{
const uint64_t packedTypeId = exportedType.typeId.pack();
if (resources.typeRegistry.contains(packedTypeId))
{
throw std::runtime_error(
std::string(__func__)
+ ": Duplicate comparator type registration for vendorId=0x"
+ std::to_string(exportedType.typeId.vendorId)
+ " typeId=0x"
+ std::to_string(exportedType.typeId.typeId));
}
auto registeredType =
std::make_shared<cologex::ExportedComparatorTypeDesc>(
exportedType);
resources.typeRegistry.emplace(packedTypeId, registeredType);
}
}
void unregisterExportedComparatorTypes(
ComparatorApiManager::Resources& resources,
const cologex::ComparatorLibDesc& libDesc)
{
for (const auto& exportedType : libDesc.exportedComparatorTypes) {
resources.typeRegistry.erase(exportedType.typeId.pack());
}
}
} // namespace
ComparatorLib& ComparatorApiManager::loadComparatorLib(
const std::string& libraryPath)
{
loadable_lib::LoadableLibraryManager& llm =
loadable_lib::LoadableLibraryManager::getInstance();
if (getComparatorLib(libraryPath))
{
throw std::runtime_error(
std::string(__func__) + ": ComparatorLib already loaded: "
+ libraryPath);
}
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
loadedLibrary = llm.loadSharedLibrary(libraryPath);
auto descFn = loadable_lib::LoadableLibraryManager::resolveSymbol<
SMO_GET_COMPARATOR_LIB_DESC_FN_TYPEDEF *>(
loadedLibrary->getDlopenHandle(),
SMO_GET_COMPARATOR_LIB_DESC_FN_NAME_STR);
const stim_buff::SmoCallbacks& callbacks =
stim_buff::getSmoCallbacks();
const cologex::ComparatorLibDesc& libDesc = descFn(callbacks);
auto lib = std::make_shared<ComparatorLib>(loadedLibrary, descFn);
lib->setComparatorLibDesc(libDesc);
registerExportedComparatorTypes(s.rsrc, lib->comparatorLibDesc);
s.rsrc.libs.push_back(lib);
return *lib;
}
void ComparatorApiManager::unloadComparatorLib(const std::string& libraryPath)
{
auto& libs = s.rsrc.libs;
auto it = std::find_if(
libs.begin(), libs.end(),
[&libraryPath](const std::shared_ptr<ComparatorLib>& lib) {
return lib->loadedSharedLibrary->libraryPath == libraryPath;
});
if (it == libs.end())
{
std::cerr << std::string(__func__) + ": Library not found: "
<< libraryPath << '\n';
return;
}
unregisterExportedComparatorTypes(s.rsrc, (*it)->comparatorLibDesc);
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
loadedLibrary = (*it)->loadedSharedLibrary;
libs.erase(it);
loadable_lib::LoadableLibraryManager::getInstance()
.unloadSharedLibrary(loadedLibrary);
}
void ComparatorApiManager::unloadAllComparatorLibs(void)
{
auto libs = s.rsrc.libs;
s.rsrc.libs.clear();
s.rsrc.typeRegistry.clear();
for (const auto& lib : libs)
{
loadable_lib::LoadableLibraryManager::getInstance()
.unloadSharedLibrary(lib->loadedSharedLibrary);
}
}
void ComparatorApiManager::loadAllComparatorApiLibsFromOptions(void)
{
const auto& options = OptionParser::getOptions();
for (const auto& libPath : options.comparatorLibs) {
loadComparatorLib(libPath);
}
}
std::optional<std::shared_ptr<ComparatorLib>>
ComparatorApiManager::getComparatorLib(const std::string& libraryPath)
{
auto& libs = s.rsrc.libs;
auto it = std::find_if(
libs.begin(), libs.end(),
[&libraryPath](const std::shared_ptr<ComparatorLib>& lib) {
return lib->loadedSharedLibrary->libraryPath == libraryPath;
});
if (it != libs.end()) {
return *it;
}
return std::nullopt;
}
std::shared_ptr<cologex::ExportedComparatorTypeDesc>
ComparatorApiManager::getComparatorType(cologex::ComparatorTypeId typeId)
{
const uint64_t packedTypeId = typeId.pack();
auto it = s.rsrc.typeRegistry.find(packedTypeId);
if (it == s.rsrc.typeRegistry.end()) {
return {};
}
return it->second;
}
std::unique_ptr<cologex::Comparator> ComparatorApiManager::getNewComparatorInstance(
cologex::ComparatorTypeId typeId)
{
return getNewComparatorInstance(getComparatorType(typeId));
}
std::unique_ptr<cologex::Comparator> ComparatorApiManager::getNewComparatorInstance(
const std::shared_ptr<cologex::ExportedComparatorTypeDesc>& comparatorType)
{
if (!comparatorType)
{
throw std::runtime_error(
std::string(__func__) + ": comparatorType is null");
}
if (!comparatorType->getNewInstance)
{
throw std::runtime_error(
std::string(__func__) + ": getNewInstance is null");
}
return comparatorType->getNewInstance();
}
std::string ComparatorApiManager::stringifyLibs() const
{
std::string result;
for (const auto& lib : s.rsrc.libs)
{
if (!result.empty()) {
result += "\n";
}
result += lib->stringify();
}
return result;
}
} // namespace comparator_lib
} // namespace smo