Add ComparatorApiManager with SmoCallbacks hooks and startup load.

Register comparator types via a dedicated manager and expose lookup/create
hooks through SmoCallbacks so stimbuff libs can resolve comparators at load time.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-10 21:16:05 -04:00
parent 7eda755c15
commit ab930a2df3
7 changed files with 358 additions and 1 deletions
+11
View File
@@ -8,6 +8,7 @@
#include <memory>
#include <vector>
#include <preprocessor.h>
#include <user/comparatorApiDesc.h>
#include <user/deviceAttachmentSpec.h>
#include <spinscale/co/dynamicPostingInvoker.h>
#include <spinscale/co/invokers.h>
@@ -137,8 +138,18 @@ struct SmoCallbacks
*/
void (*ComputeManager_releaseDevice)(
std::shared_ptr<smo::compute::ComputeDevice> device);
std::shared_ptr<cologex::ExportedComparatorTypeDesc>
(*ComparatorManager_getComparatorType)(
cologex::ComparatorTypeId typeId);
std::unique_ptr<cologex::Comparator> (*Comparator_getNewInstance)(
const std::shared_ptr<cologex::ExportedComparatorTypeDesc>&
comparatorType);
};
const SmoCallbacks& getSmoCallbacks();
struct Sal_Mgmt_LibOps
{
/* When Salmanoff loads a stim buff API lib, it calls this function to initialize
+3
View File
@@ -39,6 +39,9 @@ add_library(smocore STATIC
# Loadable shared libraries
loadableLib/loadableLibraryManager.cpp
# Comparator libs
comparatorLibs/comparatorApiManager.cpp
# ComputeManager
computeManager/computeManager.cpp
+9
View File
@@ -7,6 +7,7 @@
#include <deviceManager/deviceManager.h>
#include <mind.h>
#include <stimBuffApis/stimBuffApiManager.h>
#include <comparatorLibs/comparatorApiManager.h>
namespace smo {
namespace body {
@@ -37,6 +38,10 @@ BodyViralPostingInvoker<void> Body::initializeCReq()
*/
// Upcast to Mind to access Mind-specific members
Mind &mind = static_cast<Mind&>(parent);
comparator_lib::ComparatorApiManager::getInstance()
.loadComparatorLib("libcomparatorCore.so");
stim_buff::StimBuffApiManager::getInstance()
.loadAllStimBuffApiLibsFromOptions(mind.body.thread);
@@ -99,6 +104,10 @@ BodyViralPostingInvoker<void> Body::finalizeCReq()
std::cout << "Mrntt: About to unload all stim buff api libs." << "\n";
stim_buff::StimBuffApiManager::getInstance().unloadAllStimBuffApiLibs();
std::cout << "Mrntt: About to unload all comparator libs." << "\n";
comparator_lib::ComparatorApiManager::getInstance()
.unloadAllComparatorLibs();
co_return;
}
@@ -0,0 +1,175 @@
#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <comparatorLibs/comparatorApiManager.h>
#include <loadableLib/loadableLibraryManager.h>
#include <user/comparatorApiDesc.h>
#include <user/senseApiDesc.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);
}
}
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();
}
} // namespace comparator_lib
} // namespace smo
@@ -0,0 +1,72 @@
#ifndef COMPARATOR_API_MANAGER_H
#define COMPARATOR_API_MANAGER_H
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
#include <user/comparator.h>
#include <user/comparatorApiDesc.h>
#include <comparatorLibs/comparatorLib.h>
#include <spinscale/co/coQutex.h>
#include <spinscale/sharedResourceGroup.h>
namespace smo {
namespace comparator_lib {
class ComparatorApiManager
{
public:
struct Resources
{
std::vector<std::shared_ptr<ComparatorLib>> libs;
std::unordered_map<
uint64_t, std::shared_ptr<cologex::ExportedComparatorTypeDesc>>
typeRegistry;
};
static ComparatorApiManager& getInstance()
{
static ComparatorApiManager instance;
return instance;
}
ComparatorLib& loadComparatorLib(const std::string& libraryPath);
void unloadComparatorLib(const std::string& libraryPath);
void unloadAllComparatorLibs(void);
std::optional<std::shared_ptr<ComparatorLib>> getComparatorLib(
const std::string& libraryPath);
std::shared_ptr<cologex::ExportedComparatorTypeDesc> getComparatorType(
cologex::ComparatorTypeId typeId);
std::unique_ptr<cologex::Comparator> getNewComparatorInstance(
cologex::ComparatorTypeId typeId);
std::unique_ptr<cologex::Comparator> getNewComparatorInstance(
const std::shared_ptr<cologex::ExportedComparatorTypeDesc>&
comparatorType);
public:
sscl::SharedResourceGroup<sscl::co::CoQutex, Resources> s;
private:
ComparatorApiManager()
: s("ComparatorApiManager")
{}
~ComparatorApiManager() = default;
ComparatorApiManager(const ComparatorApiManager&) = delete;
ComparatorApiManager& operator=(const ComparatorApiManager&) = delete;
};
} // namespace comparator_lib
} // namespace smo
#endif // COMPARATOR_API_MANAGER_H
@@ -0,0 +1,64 @@
#ifndef COMPARATOR_LIB_H
#define COMPARATOR_LIB_H
#include <functional>
#include <memory>
#include <string>
#include <user/comparatorApiDesc.h>
#include <loadableLib/loadableLibraryManager.h>
#include <spinscale/co/coQutex.h>
#include <spinscale/sharedResourceGroup.h>
namespace smo {
namespace comparator_lib {
class ComparatorApiManager;
class ComparatorLib
{
private:
friend class ComparatorApiManager;
public:
ComparatorLib(
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
_loadedSharedLibrary,
SMO_GET_COMPARATOR_LIB_DESC_FN_TYPEDEF descFn)
: loadedSharedLibrary(std::move(_loadedSharedLibrary)),
SMO_GET_COMPARATOR_LIB_DESC_FN_NAME(descFn),
s("ComparatorLib-" + loadedSharedLibrary->libraryPath)
{}
void setComparatorLibDesc(const cologex::ComparatorLibDesc &desc)
{
if (!cologex::ComparatorLibDesc::sanityCheck(desc))
{
throw std::runtime_error(
std::string(__func__) + ": Sanity check failed for comparator "
"library descriptor in library '"
+ loadedSharedLibrary->libraryPath + "'");
}
comparatorLibDesc = desc;
}
public:
std::shared_ptr<loadable_lib::LoadableLibraryManager::LoadedSharedLibrary>
loadedSharedLibrary;
std::function<SMO_GET_COMPARATOR_LIB_DESC_FN_TYPEDEF>
SMO_GET_COMPARATOR_LIB_DESC_FN_NAME;
cologex::ComparatorLibDesc comparatorLibDesc;
struct ComparatorLibResources
{};
sscl::SharedResourceGroup<
sscl::co::CoQutex, ComparatorLibResources> s;
};
} // namespace comparator_lib
} // namespace smo
#endif // COMPARATOR_LIB_H
+24 -1
View File
@@ -4,6 +4,7 @@
#include <algorithm>
#include <stimBuffApis/stimBuffApiManager.h>
#include <stimBuffApis/stimBuffApiLib.h>
#include <comparatorLibs/comparatorApiManager.h>
#include <loadableLib/loadableLibraryManager.h>
#include <body/bodyThread.h>
#include <componentThread.h>
@@ -73,6 +74,20 @@ std::optional<std::string> searchForLibInSmoSearchPathsHook(
.searchForLibInSmoSearchPaths(libraryPath);
}
std::shared_ptr<cologex::ExportedComparatorTypeDesc>
ComparatorManager_getComparatorTypeHook(cologex::ComparatorTypeId typeId)
{
return comparator_lib::ComparatorApiManager::getInstance()
.getComparatorType(typeId);
}
std::unique_ptr<cologex::Comparator> Comparator_getNewInstanceHook(
const std::shared_ptr<cologex::ExportedComparatorTypeDesc>& comparatorType)
{
return comparator_lib::ComparatorApiManager::getInstance()
.getNewComparatorInstance(comparatorType);
}
/* Hooks to be provided to stimBuffApiLibs, enabling them to call into Salmanoff
* code.
*/
@@ -86,7 +101,10 @@ SmoCallbacks smoCallbacks =
.ComputeManager_releaseUseHostPtrBuffer =
ComputeManager_releaseUseHostPtrBuffer,
.ComputeManager_getDevice = ComputeManager_getDevice,
.ComputeManager_releaseDevice = ComputeManager_releaseDevice
.ComputeManager_releaseDevice = ComputeManager_releaseDevice,
.ComparatorManager_getComparatorType =
ComparatorManager_getComparatorTypeHook,
.Comparator_getNewInstance = Comparator_getNewInstanceHook
};
/* Static file-scope threading model object for senseApi libraries */
@@ -96,6 +114,11 @@ SmoThreadingModelDesc smoThreadingModelDesc = {
} // namespace
const SmoCallbacks& getSmoCallbacks()
{
return smoCallbacks;
}
StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib(
const std::string& libraryPath,
const std::shared_ptr<sscl::ComponentThread>& componentThread)