da0ef64f62
We now allocate globalMind locally inside of marionetteMain. Why? Before now, we had an asymmetric threading situation where the globalMind's threads were initialized at during global constructor invocation and not on demand. This meant that we had to shut down those threads even if we had never got to the point of calling Mind::initializeReq. This significantly complicated our shutdown sequence since we had to factor in the lifetime of the std::thread objects inside of the ComponentThreads which were inside of the globalMind object. Now, if we hadn't called Mind::initializeReq, we don't have to perform any Mind::finalizeReq or adjacent operations. Shutdown is symmetrically mirrored against the operations we actually performed during execution. We introduced some complexity by splitting ComponentThreads into two derivative types (MindThread and MarionetteThread) but I think in the long term we'll be able to massage this split into a much cleaner situation overall.
93 lines
3.0 KiB
C++
93 lines
3.0 KiB
C++
#ifndef _MIND_H
|
|
#define _MIND_H
|
|
|
|
#include <config.h>
|
|
#include <thread>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <unordered_map>
|
|
#include <string>
|
|
|
|
#include <director/director.h>
|
|
#include <simulator/simulator.h>
|
|
#include <componentThread.h>
|
|
|
|
namespace smo {
|
|
|
|
class Mind : public std::enable_shared_from_this<Mind>
|
|
{
|
|
public:
|
|
Mind(void);
|
|
~Mind(void) = default;
|
|
|
|
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(
|
|
ComponentThread::ThreadId id) const;
|
|
std::shared_ptr<MindThread> getComponentThread(
|
|
const std::string& name) const;
|
|
// Get all this Mind's component threads.
|
|
std::vector<std::shared_ptr<MindThread>> getMindThreads() const;
|
|
|
|
// Thread management methods (moved from ComponentThread)
|
|
typedef std::function<void()> mindThreadLifetimeMgmtOpCbFn;
|
|
void joltAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback);
|
|
void startAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback);
|
|
void pauseAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback);
|
|
void resumeAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback);
|
|
void exitAllMindThreadsReq(mindThreadLifetimeMgmtOpCbFn callback);
|
|
|
|
// CPU distribution method
|
|
void distributeAndPinThreadsAcrossCpus();
|
|
|
|
public:
|
|
std::thread directorThread;
|
|
std::thread simulatorThread;
|
|
std::thread subconsciousThread;
|
|
|
|
director::Director director;
|
|
simulator::Simulator canvas;
|
|
|
|
private:
|
|
/**
|
|
* Indicates whether all mind threads have been JOLTed at least once.
|
|
*
|
|
* JOLTing serves two critical purposes:
|
|
*
|
|
* 1. **Global Constructor Sequencing**: Since pthreads begin executing while
|
|
* global constructors are still being executed, globally defined pthreads
|
|
* cannot depend on global objects having been constructed. JOLTing is done
|
|
* by the CRT's main thread within main(), which provides a sequencing
|
|
* guarantee that global constructors have been called.
|
|
*
|
|
* 2. **shared_from_this Safety**: shared_from_this() requires a prior
|
|
* shared_ptr handle to be established. The global list of
|
|
* shared_ptr<ComponentThread> guarantees that at least one shared_ptr to
|
|
* each ComponentThread has been initialized before JOLTing occurs.
|
|
*
|
|
* This flag ensures that JOLTing happens exactly once and provides
|
|
* a synchronization point for the entire system initialization.
|
|
*/
|
|
bool threadsHaveBeenJolted = false,
|
|
bodyComponentInitialized = false;
|
|
// Collection of ComponentThread instances (excluding marionette)
|
|
std::vector<std::shared_ptr<MindThread>> componentThreads;
|
|
|
|
class MindLifetimeMgmtOp;
|
|
class MindThreadLifetimeMgmtOp;
|
|
class InitializeBodyReq;
|
|
class FinalizeBodyReq;
|
|
};
|
|
|
|
// Global Mind instance will be defined in marionette.cpp
|
|
extern std::shared_ptr<Mind> globalMind;
|
|
|
|
} // namespace smo
|
|
|
|
#endif
|