Wire comparator CLI, marionette threading model, and final load order.

Initialize SmoThreadingModelDesc from marionette before body startup, load
comparator libs before stimbuff via -c/--comparator-lib, and drop the hardcoded
libcomparatorCore.so load path.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-10 21:17:52 -04:00
parent 560e5364a0
commit 8836ab470b
10 changed files with 88 additions and 29 deletions
+7 -9
View File
@@ -27,23 +27,21 @@ BodyViralPostingInvoker<void> Body::initializeCReq()
} }
/** EXPLANATION: /** EXPLANATION:
* The ComponentThread instance we pass in here is the one that will be * Comparator libs are loaded before stim buff API libs so comparator
* used by Senseapi libs to perform device-independent background * types are registered before stimbuff libs can resolve them via
* operations. * SmoCallbacks during getStimBuffApiDesc.
* For example, liblivoxProto1's BroadcastListener will use this thread
* to listen for UDP broadcast dgrams from Livox devices.
* *
* We used to use Marionette, but there's a strong argument for using * SmoThreadingModelDesc is initialized in Mind::initializeCReq before
* Body instead since it's meant to handle device-management operations. * body::initializeCReq is entered.
*/ */
// Upcast to Mind to access Mind-specific members // Upcast to Mind to access Mind-specific members
Mind &mind = static_cast<Mind&>(parent); Mind &mind = static_cast<Mind&>(parent);
comparator_lib::ComparatorApiManager::getInstance() comparator_lib::ComparatorApiManager::getInstance()
.loadComparatorLib("libcomparatorCore.so"); .loadAllComparatorApiLibsFromOptions();
stim_buff::StimBuffApiManager::getInstance() stim_buff::StimBuffApiManager::getInstance()
.loadAllStimBuffApiLibsFromOptions(mind.body.thread); .loadAllStimBuffApiLibsFromOptions();
/** EXPLANATION: /** EXPLANATION:
* Consider body::initializeCReq to have been called if even one of its * Consider body::initializeCReq to have been called if even one of its
@@ -3,6 +3,7 @@
#include <stdexcept> #include <stdexcept>
#include <comparatorLibs/comparatorApiManager.h> #include <comparatorLibs/comparatorApiManager.h>
#include <loadableLib/loadableLibraryManager.h> #include <loadableLib/loadableLibraryManager.h>
#include <opts.h>
#include <user/comparatorApiDesc.h> #include <user/comparatorApiDesc.h>
#include <user/smoHooks.h> #include <user/smoHooks.h>
@@ -118,6 +119,14 @@ void ComparatorApiManager::unloadAllComparatorLibs(void)
} }
} }
void ComparatorApiManager::loadAllComparatorApiLibsFromOptions(void)
{
const auto& options = OptionParser::getOptions();
for (const auto& libPath : options.comparatorLibs) {
loadComparatorLib(libPath);
}
}
std::optional<std::shared_ptr<ComparatorLib>> std::optional<std::shared_ptr<ComparatorLib>>
ComparatorApiManager::getComparatorLib(const std::string& libraryPath) ComparatorApiManager::getComparatorLib(const std::string& libraryPath)
{ {
@@ -39,6 +39,8 @@ public:
void unloadAllComparatorLibs(void); void unloadAllComparatorLibs(void);
void loadAllComparatorApiLibsFromOptions(void);
std::optional<std::shared_ptr<ComparatorLib>> getComparatorLib( std::optional<std::shared_ptr<ComparatorLib>> getComparatorLib(
const std::string& libraryPath); const std::string& libraryPath);
+7
View File
@@ -11,6 +11,7 @@
#include <spinscale/component.h> #include <spinscale/component.h>
#include <spinscale/co/nonViralTaskNursery.h> #include <spinscale/co/nonViralTaskNursery.h>
#include <marionette/marionetteThread.h> #include <marionette/marionetteThread.h>
#include <user/smoHooks.h>
namespace sscl { namespace sscl {
@@ -66,6 +67,12 @@ private:
extern std::shared_ptr<sscl::PuppeteerThread> thread; extern std::shared_ptr<sscl::PuppeteerThread> thread;
extern MarionetteComponent mrntt; extern MarionetteComponent mrntt;
extern stim_buff::SmoThreadingModelDesc smoThreadingModelDesc;
void initializeSmoThreadingModelDesc(
const std::shared_ptr<sscl::ComponentThread>& componentThread);
const stim_buff::SmoThreadingModelDesc& getSmoThreadingModelDesc();
void marionetteInitializeReqCb(bool success); void marionetteInitializeReqCb(bool success);
void marionetteFinalizeReqCb(bool success); void marionetteFinalizeReqCb(bool success);
+1
View File
@@ -41,6 +41,7 @@ public:
std::string argv0; std::string argv0;
std::vector<std::string> senseApiLibPath; std::vector<std::string> senseApiLibPath;
std::vector<std::string> senseApiLibs; std::vector<std::string> senseApiLibs;
std::vector<std::string> comparatorLibs;
std::string dapSpecs; std::string dapSpecs;
std::vector<std::string> dapSpecFiles; std::vector<std::string> dapSpecFiles;
bool verbose, printUsage, traceCallables; bool verbose, printUsage, traceCallables;
@@ -35,9 +35,7 @@ public:
void finalize(void) void finalize(void)
{}; {};
StimBuffApiLib& loadStimBuffApiLib( StimBuffApiLib& loadStimBuffApiLib(const std::string& libraryPath);
const std::string& libraryPath,
const std::shared_ptr<sscl::ComponentThread>& componentThread);
std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByLibraryPath( std::optional<std::shared_ptr<StimBuffApiLib>> findStimBuffApiLibByLibraryPath(
const std::string& libraryPath); const std::string& libraryPath);
@@ -46,8 +44,7 @@ public:
StimBuffApiLib &getStimBuffApiLibByApiName(const std::string& apiName); StimBuffApiLib &getStimBuffApiLibByApiName(const std::string& apiName);
void unloadStimBuffApiLib(const std::string& libraryPath); void unloadStimBuffApiLib(const std::string& libraryPath);
void loadAllStimBuffApiLibsFromOptions( void loadAllStimBuffApiLibsFromOptions(void);
const std::shared_ptr<sscl::ComponentThread>& componentThread);
void unloadAllStimBuffApiLibs(void); void unloadAllStimBuffApiLibs(void);
body::BodyViralPostingInvoker<void> initializeStimBuffApiLibCReq( body::BodyViralPostingInvoker<void> initializeStimBuffApiLibCReq(
+31
View File
@@ -1,3 +1,4 @@
#include <stdexcept>
#include <config.h> #include <config.h>
#include <iostream> #include <iostream>
#include <opts.h> #include <opts.h>
@@ -22,6 +23,36 @@ std::shared_ptr<sscl::PuppeteerThread> thread = std::make_shared<
MarionetteComponent mrntt(thread); MarionetteComponent mrntt(thread);
stim_buff::SmoThreadingModelDesc smoThreadingModelDesc = {
.componentThread = nullptr
};
void initializeSmoThreadingModelDesc(
const std::shared_ptr<sscl::ComponentThread>& componentThread)
{
if (!componentThread)
{
throw std::runtime_error(
std::string(__func__) + ": componentThread must be non-null");
}
if (smoThreadingModelDesc.componentThread
&& smoThreadingModelDesc.componentThread != componentThread)
{
throw std::runtime_error(
std::string(__func__)
+ ": SmoThreadingModelDesc already initialized with a different "
"ComponentThread");
}
smoThreadingModelDesc.componentThread = componentThread;
}
const stim_buff::SmoThreadingModelDesc& getSmoThreadingModelDesc()
{
return smoThreadingModelDesc;
}
void marionetteInitializeReqCb(bool success) void marionetteInitializeReqCb(bool success)
{ {
if (success) if (success)
+2
View File
@@ -125,6 +125,8 @@ mrntt::MrnttViralNonPostingInvokerT<void> Mind::initializeCReq()
co_await startAllPuppetThreadsCReq(); co_await startAllPuppetThreadsCReq();
std::cout << "Mrntt: All mind threads started." << "\n"; std::cout << "Mrntt: All mind threads started." << "\n";
mrntt::initializeSmoThreadingModelDesc(body.thread);
co_await body.initializeCReq(); co_await body.initializeCReq();
std::cout << "Mrntt: Body component initialized." << "\n"; std::cout << "Mrntt: Body component initialized." << "\n";
+14 -1
View File
@@ -43,6 +43,9 @@ struct option OptionParser::longOptions[] = {
{"api-lib-path", required_argument, 0, 'p'}, {"api-lib-path", required_argument, 0, 'p'},
{"apipath", required_argument, 0, 'p'}, {"apipath", required_argument, 0, 'p'},
{"libpath", required_argument, 0, 'p'}, {"libpath", required_argument, 0, 'p'},
{"comparator-lib", required_argument, 0, 'c'},
{"comp-lib", required_argument, 0, 'c'},
{"complib", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'v'}, {"verbose", no_argument, 0, 'v'},
{"trace-callables", no_argument, 0, 't'}, {"trace-callables", no_argument, 0, 't'},
{"call-trace", no_argument, 0, 't'}, {"call-trace", no_argument, 0, 't'},
@@ -62,7 +65,7 @@ void OptionParser::parseArguments(int argc, char *argv[], char **envp)
optind = 1; // Reset optind to 1 before parsing optind = 1; // Reset optind to 1 before parsing
opterr = 0; opterr = 0;
while ((opt = getopt_long( while ((opt = getopt_long(
argc, argv, "s:d:a:p:vht?", longOptions, &optionIndex)) != -1) argc, argv, "s:d:a:p:c:vht?", longOptions, &optionIndex)) != -1)
{ {
switch (opt) switch (opt)
{ {
@@ -92,6 +95,9 @@ void OptionParser::parseArguments(int argc, char *argv[], char **envp)
senseApiLibPath.push_back(optarg); senseApiLibPath.push_back(optarg);
break; break;
} }
case 'c':
comparatorLibs.push_back(optarg);
break;
case 'v': case 'v':
verbose = true; verbose = true;
break; break;
@@ -115,6 +121,7 @@ std::string OptionParser::getUsage() const
return "Usage: " + argv0 + " [-s|--dapspec|--spec <device_spec>] " return "Usage: " + argv0 + " [-s|--dapspec|--spec <device_spec>] "
"[-d|--dapfile <DAP_spec_file>] " "[-d|--dapfile <DAP_spec_file>] "
"[-a|--api-lib|--apilib|--api|--lib <filename>] " "[-a|--api-lib|--apilib|--api|--lib <filename>] "
"[-c|--comparator-lib|--comp-lib|--complib <filename>] "
"[-p|--api-lib-path|--apipath|--libpath <directory>] " "[-p|--api-lib-path|--apipath|--libpath <directory>] "
"[-v|--verbose] " "[-v|--verbose] "
"[-t|--trace-callables|--call-trace|--calltrace] " "[-t|--trace-callables|--call-trace|--calltrace] "
@@ -154,5 +161,11 @@ std::string OptionParser::stringifyOptions(void) const
} }
oss << std::endl; oss << std::endl;
oss << "Comparator Libraries: ";
for (const auto& lib : comparatorLibs) {
oss << lib << " ";
}
oss << std::endl;
return oss.str(); return oss.str();
} }
+13 -14
View File
@@ -10,7 +10,6 @@
#include <componentThread.h> #include <componentThread.h>
#include <opts.h> #include <opts.h>
#include <user/smoHooks.h> #include <user/smoHooks.h>
#include <user/senseApiDesc.h>
#include <mind.h> #include <mind.h>
#include <deviceManager/deviceManager.h> #include <deviceManager/deviceManager.h>
#include <marionette/marionette.h> #include <marionette/marionette.h>
@@ -37,11 +36,13 @@ std::shared_ptr<sscl::ComponentThread> ComponentThread_getSelf()
return sscl::ComponentThread::getSelf(); return sscl::ComponentThread::getSelf();
} }
/* Local static function to wrap OptionParser::getOptions for SmoCallbacks */
OptionParser& OptionParser_getOptions() OptionParser& OptionParser_getOptions()
{ {
return OptionParser::getOptions(); return OptionParser::getOptions();
} }
/* Local static functions to wrap ComputeManager methods for SmoCallbacks */
std::shared_ptr<smo::compute::ClBuffer> std::shared_ptr<smo::compute::ClBuffer>
ComputeManager_createUseHostPtrBuffer( ComputeManager_createUseHostPtrBuffer(
void* hostPtr, size_t size, cl_mem_flags flags) void* hostPtr, size_t size, cl_mem_flags flags)
@@ -108,11 +109,6 @@ SmoCallbacks smoCallbacks =
.Comparator_getNewInstance = Comparator_getNewInstanceHook .Comparator_getNewInstance = Comparator_getNewInstanceHook
}; };
/* Static file-scope threading model object for senseApi libraries */
SmoThreadingModelDesc smoThreadingModelDesc = {
.componentThread = nullptr
};
} // namespace } // namespace
const SmoCallbacks& getSmoCallbacks() const SmoCallbacks& getSmoCallbacks()
@@ -121,8 +117,7 @@ const SmoCallbacks& getSmoCallbacks()
} }
StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib( StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib(
const std::string& libraryPath, const std::string& libraryPath)
const std::shared_ptr<sscl::ComponentThread>& componentThread)
{ {
loadable_lib::LoadableLibraryManager& llm = loadable_lib::LoadableLibraryManager& llm =
loadable_lib::LoadableLibraryManager::getInstance(); loadable_lib::LoadableLibraryManager::getInstance();
@@ -142,12 +137,17 @@ StimBuffApiLib& StimBuffApiManager::loadStimBuffApiLib(
loadedLibrary->getDlopenHandle(), loadedLibrary->getDlopenHandle(),
SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR); SMO_GET_STIM_BUFF_API_DESC_FN_NAME_STR);
if (!smoThreadingModelDesc.componentThread) { const stim_buff::SmoThreadingModelDesc& threadingModel =
smoThreadingModelDesc.componentThread = componentThread; mrntt::getSmoThreadingModelDesc();
if (!threadingModel.componentThread)
{
throw std::runtime_error(
std::string(__func__)
+ ": SmoThreadingModelDesc has not been initialized");
} }
const StimBuffApiDesc& libApiDesc = descFn( const StimBuffApiDesc& libApiDesc = descFn(
smoCallbacks, smoThreadingModelDesc); smoCallbacks, threadingModel);
auto lib = std::make_shared<StimBuffApiLib>(loadedLibrary, descFn); auto lib = std::make_shared<StimBuffApiLib>(loadedLibrary, descFn);
lib->setStimBuffApiDesc(libApiDesc); lib->setStimBuffApiDesc(libApiDesc);
@@ -234,12 +234,11 @@ void StimBuffApiManager::unloadAllStimBuffApiLibs(void)
} }
} }
void StimBuffApiManager::loadAllStimBuffApiLibsFromOptions( void StimBuffApiManager::loadAllStimBuffApiLibsFromOptions(void)
const std::shared_ptr<sscl::ComponentThread>& componentThread)
{ {
const auto& options = OptionParser::getOptions(); const auto& options = OptionParser::getOptions();
for (const auto& libPath : options.senseApiLibs) { for (const auto& libPath : options.senseApiLibs) {
loadStimBuffApiLib(libPath, componentThread); loadStimBuffApiLib(libPath);
} }
} }