Add Mrntt component; init globalMind in mrntt.initializeReq

This makes the initialization sequence much cleaner and conceptually
well encapsulated.

We also now dynamically allocate the Mind objects. They're allocated
dynamically by Mrntt inside of initializeReq. This means that we no
longer have to worry about jolting and cleaning up the running threads
of global mind object even when we never explicitly called
Mind.initializeReq.

Along with other conceptual improvements to our abstractions, this
patch also gets us to a real "end of program initialization" point
for the first time.
This commit is contained in:
2025-09-14 22:17:19 -04:00
parent 16865dc36f
commit 91ccd16b33
23 changed files with 681 additions and 252 deletions
+33
View File
@@ -0,0 +1,33 @@
#ifndef _BODY_COMPONENT_H
#define _BODY_COMPONENT_H
#include <component.h>
#include <functional>
namespace smo {
class Mind;
class ComponentThread;
namespace body {
class Body
: public MindComponent
{
public:
Body(Mind &parent, const std::shared_ptr<ComponentThread> &thread);
~Body() = default;
typedef std::function<void(bool)> bodyLifetimeMgmtOpCbFn;
void initializeReq(bodyLifetimeMgmtOpCbFn callback);
void finalizeReq(bodyLifetimeMgmtOpCbFn callback);
private:
class InitializeReq;
class FinalizeReq;
};
} // namespace body
} // namespace smo
#endif // _BODY_COMPONENT_H
+58
View File
@@ -0,0 +1,58 @@
#ifndef COMPONENT_H
#define COMPONENT_H
#include <config.h>
#include <memory>
#include <functional>
namespace smo {
class Mind;
class ComponentThread;
class Component
{
public:
Component(const std::shared_ptr<ComponentThread> &thread);
~Component() = default;
public:
std::shared_ptr<ComponentThread> thread;
public:
};
class MindComponent
: public Component
{
public:
MindComponent(Mind &parent, const std::shared_ptr<ComponentThread> &thread);
~MindComponent() = default;
public:
Mind &parent;
};
namespace mrntt {
class MarionetteComponent
: public Component
{
public:
MarionetteComponent(const std::shared_ptr<ComponentThread> &thread);
~MarionetteComponent() = default;
public:
typedef std::function<void(bool)> mrnttLifetimeMgmtOpCbFn;
void initializeReq(mrnttLifetimeMgmtOpCbFn callback);
void finalizeReq(mrnttLifetimeMgmtOpCbFn callback);
private:
class MrnttLifetimeMgmtOp;
};
} // namespace mrntt
} // namespace smo
#endif // COMPONENT_H
+2 -2
View File
@@ -167,8 +167,8 @@ public:
};
namespace mrntt {
extern std::shared_ptr<MarionetteThread> mrntt;
}
extern std::shared_ptr<MarionetteThread> thread;
} // namespace mrntt
} // namespace smo
+13 -3
View File
@@ -2,16 +2,26 @@
#define DIRECTOR_H
#include <config.h>
#include <component.h>
#include <goal.h>
#include <lruLifo.h>
namespace smo {
class Mind;
class ComponentThread;
namespace director {
class Director {
class Director
: public MindComponent
{
public:
Director() = default;
~Director() = default;
Director(Mind &parent, const std::shared_ptr<ComponentThread> &thread)
: MindComponent(parent, thread)
{}
~Director() = default;
/** EXPLANATION:
* We allow SMO to prioritize negtrins over injected goals, so that it can
+2 -1
View File
@@ -5,6 +5,7 @@
#include <atomic>
#include <memory>
#include <componentThread.h>
#include <component.h>
namespace smo {
@@ -13,8 +14,8 @@ class MarionetteThread;
namespace mrntt {
extern std::atomic<int> exitCode;
void exitMarionetteLoop();
extern mrntt::MarionetteComponent mrntt;
} // namespace mrntt
+14 -13
View File
@@ -8,9 +8,11 @@
#include <unordered_map>
#include <string>
#include <component.h>
#include <componentThread.h>
#include <director/director.h>
#include <simulator/simulator.h>
#include <componentThread.h>
#include <body/body.h>
namespace smo {
@@ -23,8 +25,6 @@ public:
typedef std::function<void(bool)> mindLifetimeMgmtOpCbFn;
void initializeReq(mindLifetimeMgmtOpCbFn callback);
void finalizeReq(mindLifetimeMgmtOpCbFn callback);
void initializeBodyReq(mindLifetimeMgmtOpCbFn callback);
void finalizeBodyReq(mindLifetimeMgmtOpCbFn callback);
// ComponentThread access methods
std::shared_ptr<MindThread> getComponentThread(
@@ -45,15 +45,19 @@ public:
// CPU distribution method
void distributeAndPinThreadsAcrossCpus();
public:
std::thread directorThread;
std::thread simulatorThread;
std::thread subconsciousThread;
private:
// Collection of ComponentThread instances (excluding marionette)
std::vector<std::shared_ptr<MindThread>> componentThreads;
director::Director director;
simulator::Simulator canvas;
public:
director::Director director;
simulator::Simulator canvas;
MindComponent subconscious;
body::Body body;
MindComponent world;
private:
friend class body::Body;
/**
* Indicates whether all mind threads have been JOLTed at least once.
*
@@ -75,13 +79,10 @@ private:
*/
bool threadsHaveBeenJolted = false,
bodyComponentInitialized = false;
// Collection of ComponentThread instances (excluding marionette)
std::vector<std::shared_ptr<MindThread>> componentThreads;
private:
class MindLifetimeMgmtOp;
class MindThreadLifetimeMgmtOp;
class InitializeBodyReq;
class FinalizeBodyReq;
};
// Global Mind instance will be defined in marionette.cpp
+48
View File
@@ -0,0 +1,48 @@
#ifndef _SMO_MIND_MANAGER_H
#define _SMO_MIND_MANAGER_H
#include <config.h>
#include <memory>
#include <vector>
#include <mind.h>
namespace smo {
namespace mind {
/** EXPLANATION:
* MindManager is responsible for managing the lifecycle of all minds.
* It is responsible for creating, destroying, and managing the minds.
*
* For now it does nothing since we haven't yet added support for multiple
* minds.
*/
class MindManager
{
public:
MindManager(void) = default;
~MindManager(void) = default;
static MindManager& getInstance()
{
static MindManager instance;
return instance;
}
public:
void initialize(void) {};
void finalize(void) {};
std::shared_ptr<Mind> getMind(void) const;
void addMind(const std::shared_ptr<Mind>& mind);
void removeMind(const std::shared_ptr<Mind>& mind);
public:
std::vector<std::shared_ptr<Mind>> minds;
};
extern std::shared_ptr<Mind> globalMind;
} // namespace mind
} // namespace smo
#endif // _SMO_MIND_MANAGER_H
+13 -3
View File
@@ -2,15 +2,25 @@
#define SIMULATOR_H
#include <config.h>
#include <component.h>
#include <simulator/scene.h>
namespace smo {
class Mind;
class ComponentThread;
namespace simulator {
class Simulator {
class Simulator
: public MindComponent
{
public:
Simulator() = default;
~Simulator() = default;
Simulator(Mind &parent, const std::shared_ptr<ComponentThread> &thread)
: MindComponent(parent, thread)
{}
~Simulator() = default;
void initialize();
void loadScene(Scene::Id sceneId, Scene &scene);