spinscale: Move thread init/jolt/exit logic into PuppetApplication
This commit is contained in:
@@ -3,6 +3,7 @@ add_library(spinscale SHARED
|
|||||||
src/lockerAndInvokerBase.cpp
|
src/lockerAndInvokerBase.cpp
|
||||||
src/componentThread.cpp
|
src/componentThread.cpp
|
||||||
src/component.cpp
|
src/component.cpp
|
||||||
|
src/puppetApplication.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Conditionally add qutexAcquisitionHistoryTracker.cpp only when debug locks
|
# Conditionally add qutexAcquisitionHistoryTracker.cpp only when debug locks
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef PUPPET_APPLICATION_H
|
||||||
|
#define PUPPET_APPLICATION_H
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <spinscale/callback.h>
|
||||||
|
#include <spinscale/componentThread.h>
|
||||||
|
|
||||||
|
namespace smo {
|
||||||
|
|
||||||
|
class PuppetApplication
|
||||||
|
: public std::enable_shared_from_this<PuppetApplication>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PuppetApplication(
|
||||||
|
const std::vector<std::shared_ptr<PuppetThread>> &threads);
|
||||||
|
~PuppetApplication() = default;
|
||||||
|
|
||||||
|
// Thread management methods
|
||||||
|
typedef std::function<void()> puppetThreadLifetimeMgmtOpCbFn;
|
||||||
|
void joltAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback);
|
||||||
|
void startAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback);
|
||||||
|
void pauseAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback);
|
||||||
|
void resumeAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback);
|
||||||
|
void exitAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Collection of PuppetThread instances
|
||||||
|
std::vector<std::shared_ptr<PuppetThread>> componentThreads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether all puppet 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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PuppetThreadLifetimeMgmtOp;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace smo
|
||||||
|
|
||||||
|
#endif // PUPPET_APPLICATION_H
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <spinscale/asynchronousContinuation.h>
|
||||||
|
#include <spinscale/asynchronousLoop.h>
|
||||||
|
#include <spinscale/callback.h>
|
||||||
|
#include <spinscale/puppetApplication.h>
|
||||||
|
#include <spinscale/componentThread.h>
|
||||||
|
|
||||||
|
namespace smo {
|
||||||
|
|
||||||
|
PuppetApplication::PuppetApplication(
|
||||||
|
const std::vector<std::shared_ptr<PuppetThread>> &threads)
|
||||||
|
: componentThreads(threads)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class PuppetApplication::PuppetThreadLifetimeMgmtOp
|
||||||
|
: public NonPostedAsynchronousContinuation<puppetThreadLifetimeMgmtOpCbFn>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PuppetThreadLifetimeMgmtOp(
|
||||||
|
PuppetApplication &parent, unsigned int nThreads,
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback)
|
||||||
|
: NonPostedAsynchronousContinuation<puppetThreadLifetimeMgmtOpCbFn>(callback),
|
||||||
|
loop(nThreads),
|
||||||
|
parent(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
AsynchronousLoop loop;
|
||||||
|
PuppetApplication &parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void joltAllPuppetThreadsReq1(
|
||||||
|
[[maybe_unused]] std::shared_ptr<PuppetThreadLifetimeMgmtOp> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
loop.incrementSuccessOrFailureDueTo(true);
|
||||||
|
if (!loop.isComplete()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.threadsHaveBeenJolted = true;
|
||||||
|
callOriginalCb();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeGenericOpOnAllPuppetThreadsReq1(
|
||||||
|
[[maybe_unused]] std::shared_ptr<PuppetThreadLifetimeMgmtOp> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
loop.incrementSuccessOrFailureDueTo(true);
|
||||||
|
if (!loop.isComplete()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callOriginalCb();
|
||||||
|
}
|
||||||
|
|
||||||
|
void exitAllPuppetThreadsReq1(
|
||||||
|
[[maybe_unused]] std::shared_ptr<PuppetThreadLifetimeMgmtOp> context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
loop.incrementSuccessOrFailureDueTo(true);
|
||||||
|
if (!loop.isComplete()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& thread : parent.componentThreads) {
|
||||||
|
thread->thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
callOriginalCb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void PuppetApplication::joltAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (threadsHaveBeenJolted)
|
||||||
|
{
|
||||||
|
std::cout << "Mrntt: All puppet threads already JOLTed. "
|
||||||
|
<< "Skipping JOLT request." << "\n";
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no threads, set flag and call callback immediately
|
||||||
|
if (componentThreads.size() == 0 && callback.callbackFn)
|
||||||
|
{
|
||||||
|
threadsHaveBeenJolted = true;
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a counter to track when all threads have been jolted
|
||||||
|
auto request = std::make_shared<PuppetThreadLifetimeMgmtOp>(
|
||||||
|
*this, componentThreads.size(), callback);
|
||||||
|
|
||||||
|
for (auto& thread : componentThreads)
|
||||||
|
{
|
||||||
|
thread->joltThreadReq(
|
||||||
|
{request, std::bind(
|
||||||
|
&PuppetThreadLifetimeMgmtOp::joltAllPuppetThreadsReq1,
|
||||||
|
request.get(), request)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PuppetApplication::startAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// If no threads, call callback immediately
|
||||||
|
if (componentThreads.size() == 0 && callback.callbackFn)
|
||||||
|
{
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a counter to track when all threads have started
|
||||||
|
auto request = std::make_shared<PuppetThreadLifetimeMgmtOp>(
|
||||||
|
*this, componentThreads.size(), callback);
|
||||||
|
|
||||||
|
for (auto& thread : componentThreads)
|
||||||
|
{
|
||||||
|
thread->startThreadReq(
|
||||||
|
{request, std::bind(
|
||||||
|
&PuppetThreadLifetimeMgmtOp::executeGenericOpOnAllPuppetThreadsReq1,
|
||||||
|
request.get(), request)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PuppetApplication::pauseAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// If no threads, call callback immediately
|
||||||
|
if (componentThreads.size() == 0 && callback.callbackFn)
|
||||||
|
{
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a counter to track when all threads have paused
|
||||||
|
auto request = std::make_shared<PuppetThreadLifetimeMgmtOp>(
|
||||||
|
*this, componentThreads.size(), callback);
|
||||||
|
|
||||||
|
for (auto& thread : componentThreads)
|
||||||
|
{
|
||||||
|
thread->pauseThreadReq(
|
||||||
|
{request, std::bind(
|
||||||
|
&PuppetThreadLifetimeMgmtOp::executeGenericOpOnAllPuppetThreadsReq1,
|
||||||
|
request.get(), request)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PuppetApplication::resumeAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// If no threads, call callback immediately
|
||||||
|
if (componentThreads.size() == 0 && callback.callbackFn)
|
||||||
|
{
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a counter to track when all threads have resumed
|
||||||
|
auto request = std::make_shared<PuppetThreadLifetimeMgmtOp>(
|
||||||
|
*this, componentThreads.size(), callback);
|
||||||
|
|
||||||
|
for (auto& thread : componentThreads)
|
||||||
|
{
|
||||||
|
thread->resumeThreadReq(
|
||||||
|
{request, std::bind(
|
||||||
|
&PuppetThreadLifetimeMgmtOp::executeGenericOpOnAllPuppetThreadsReq1,
|
||||||
|
request.get(), request)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PuppetApplication::exitAllPuppetThreadsReq(
|
||||||
|
Callback<puppetThreadLifetimeMgmtOpCbFn> callback
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// If no threads, call callback immediately
|
||||||
|
if (componentThreads.size() == 0 && callback.callbackFn)
|
||||||
|
{
|
||||||
|
callback.callbackFn();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a counter to track when all threads have exited
|
||||||
|
auto request = std::make_shared<PuppetThreadLifetimeMgmtOp>(
|
||||||
|
*this, componentThreads.size(), callback);
|
||||||
|
|
||||||
|
for (auto& thread : componentThreads)
|
||||||
|
{
|
||||||
|
thread->exitThreadReq(
|
||||||
|
{request, std::bind(
|
||||||
|
&PuppetThreadLifetimeMgmtOp::executeGenericOpOnAllPuppetThreadsReq1,
|
||||||
|
request.get(), request)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace smo
|
||||||
+4
-40
@@ -2,14 +2,13 @@
|
|||||||
#define _MIND_H
|
#define _MIND_H
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <thread>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <spinscale/callback.h>
|
#include <spinscale/callback.h>
|
||||||
|
|
||||||
#include <spinscale/component.h>
|
#include <spinscale/component.h>
|
||||||
|
#include <spinscale/puppetApplication.h>
|
||||||
#include <componentThread.h>
|
#include <componentThread.h>
|
||||||
#include <mindThread.h>
|
#include <mindThread.h>
|
||||||
#include <director/director.h>
|
#include <director/director.h>
|
||||||
@@ -18,7 +17,8 @@
|
|||||||
|
|
||||||
namespace smo {
|
namespace smo {
|
||||||
|
|
||||||
class Mind : public std::enable_shared_from_this<Mind>
|
class Mind
|
||||||
|
: public PuppetApplication
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mind(void);
|
Mind(void);
|
||||||
@@ -35,24 +35,9 @@ public:
|
|||||||
// Get all this Mind's component threads.
|
// Get all this Mind's component threads.
|
||||||
std::vector<std::shared_ptr<MindThread>> getMindThreads() const;
|
std::vector<std::shared_ptr<MindThread>> getMindThreads() const;
|
||||||
|
|
||||||
// Thread management methods (moved from ComponentThread)
|
|
||||||
typedef std::function<void()> mindThreadLifetimeMgmtOpCbFn;
|
|
||||||
void joltAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);
|
|
||||||
void startAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback);
|
|
||||||
void pauseAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback);
|
|
||||||
void resumeAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback);
|
|
||||||
void exitAllMindThreadsReq(Callback<mindThreadLifetimeMgmtOpCbFn> callback);
|
|
||||||
|
|
||||||
// CPU distribution method
|
// CPU distribution method
|
||||||
void distributeAndPinThreadsAcrossCpus();
|
void distributeAndPinThreadsAcrossCpus();
|
||||||
|
|
||||||
private:
|
|
||||||
// Collection of ComponentThread instances (excluding marionette)
|
|
||||||
std::vector<std::shared_ptr<MindThread>> componentThreads;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
director::Director director;
|
director::Director director;
|
||||||
simulator::Simulator canvas;
|
simulator::Simulator canvas;
|
||||||
@@ -62,31 +47,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend class body::Body;
|
friend class body::Body;
|
||||||
/**
|
bool bodyComponentInitialized = false;
|
||||||
* 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;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MindLifetimeMgmtOp;
|
class MindLifetimeMgmtOp;
|
||||||
class MindThreadLifetimeMgmtOp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace mind {
|
namespace mind {
|
||||||
|
|||||||
+34
-211
@@ -14,24 +14,25 @@
|
|||||||
namespace smo {
|
namespace smo {
|
||||||
|
|
||||||
Mind::Mind(void)
|
Mind::Mind(void)
|
||||||
: componentThreads{
|
: PuppetApplication(
|
||||||
std::make_shared<MindThread>(SmoThreadId::DIRECTOR, *this),
|
std::vector<std::shared_ptr<PuppetThread>>{
|
||||||
std::make_shared<MindThread>(SmoThreadId::SIMULATOR, *this),
|
std::make_shared<MindThread>(SmoThreadId::DIRECTOR, *this),
|
||||||
std::make_shared<MindThread>(SmoThreadId::SUBCONSCIOUS, *this),
|
std::make_shared<MindThread>(SmoThreadId::SIMULATOR, *this),
|
||||||
std::make_shared<MindThread>(SmoThreadId::BODY, *this)
|
std::make_shared<MindThread>(SmoThreadId::SUBCONSCIOUS, *this),
|
||||||
|
std::make_shared<MindThread>(SmoThreadId::BODY, *this)
|
||||||
#ifndef CONFIG_WORLD_USE_BODY_THREAD
|
#ifndef CONFIG_WORLD_USE_BODY_THREAD
|
||||||
, std::make_shared<MindThread>(SmoThreadId::WORLD, *this)
|
, std::make_shared<MindThread>(SmoThreadId::WORLD, *this)
|
||||||
#endif
|
#endif
|
||||||
},
|
}),
|
||||||
director(*this, componentThreads[0]),
|
director(*this, std::static_pointer_cast<MindThread>(componentThreads[0])),
|
||||||
canvas(*this, componentThreads[1]),
|
canvas(*this, std::static_pointer_cast<MindThread>(componentThreads[1])),
|
||||||
subconscious(*this, componentThreads[2]),
|
subconscious(*this, std::static_pointer_cast<MindThread>(componentThreads[2])),
|
||||||
body(*this, componentThreads[3]),
|
body(*this, std::static_pointer_cast<MindThread>(componentThreads[3])),
|
||||||
world(*this,
|
world(*this,
|
||||||
#ifndef CONFIG_WORLD_USE_BODY_THREAD
|
#ifndef CONFIG_WORLD_USE_BODY_THREAD
|
||||||
componentThreads[4]
|
std::static_pointer_cast<MindThread>(componentThreads[4])
|
||||||
#else
|
#else
|
||||||
componentThreads[3]
|
std::static_pointer_cast<MindThread>(componentThreads[3])
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -49,8 +50,11 @@ Mind::getComponentThread(ThreadId id) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search through the vector for the thread with matching id
|
// Search through the vector for the thread with matching id
|
||||||
for (auto& thread : componentThreads) {
|
for (auto& thread : componentThreads)
|
||||||
if (thread->id == id) { return thread; }
|
{
|
||||||
|
if (thread->id == id) {
|
||||||
|
return std::static_pointer_cast<MindThread>(thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw exception if no thread found
|
// Throw exception if no thread found
|
||||||
@@ -70,8 +74,11 @@ Mind::getComponentThread(const std::string& name) const
|
|||||||
"getComponentThread");
|
"getComponentThread");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& thread : componentThreads) {
|
for (auto& thread : componentThreads)
|
||||||
if (thread->name == name) { return thread; }
|
{
|
||||||
|
if (thread->name == name) {
|
||||||
|
return std::static_pointer_cast<MindThread>(thread);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw exception if no thread found
|
// Throw exception if no thread found
|
||||||
@@ -82,7 +89,12 @@ Mind::getComponentThread(const std::string& name) const
|
|||||||
std::vector<std::shared_ptr<MindThread>>
|
std::vector<std::shared_ptr<MindThread>>
|
||||||
Mind::getMindThreads() const
|
Mind::getMindThreads() const
|
||||||
{
|
{
|
||||||
return componentThreads;
|
std::vector<std::shared_ptr<MindThread>> mindThreads;
|
||||||
|
mindThreads.reserve(componentThreads.size());
|
||||||
|
for (auto& thread : componentThreads) {
|
||||||
|
mindThreads.push_back(std::static_pointer_cast<MindThread>(thread));
|
||||||
|
}
|
||||||
|
return mindThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mind::MindLifetimeMgmtOp
|
class Mind::MindLifetimeMgmtOp
|
||||||
@@ -106,7 +118,7 @@ public:
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Jolt the threads, then start them */
|
/* Jolt the threads, then start them */
|
||||||
parent.joltAllMindThreadsReq(
|
parent.joltAllPuppetThreadsReq(
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&MindLifetimeMgmtOp::initializeReq2,
|
&MindLifetimeMgmtOp::initializeReq2,
|
||||||
context.get(), context)});
|
context.get(), context)});
|
||||||
@@ -118,7 +130,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::cout << "Mrntt: All mind threads JOLTed." << "\n";
|
std::cout << "Mrntt: All mind threads JOLTed." << "\n";
|
||||||
|
|
||||||
parent.startAllMindThreadsReq(
|
parent.startAllPuppetThreadsReq(
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&MindLifetimeMgmtOp::initializeReq3,
|
&MindLifetimeMgmtOp::initializeReq3,
|
||||||
context.get(), context)});
|
context.get(), context)});
|
||||||
@@ -170,7 +182,7 @@ public:
|
|||||||
* otherwise they'll just enter their main loops and wait for control
|
* otherwise they'll just enter their main loops and wait for control
|
||||||
* messages from mrntt after processing the exit request.
|
* messages from mrntt after processing the exit request.
|
||||||
*/
|
*/
|
||||||
parent.joltAllMindThreadsReq(
|
parent.joltAllPuppetThreadsReq(
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&MindLifetimeMgmtOp::finalizeReq3,
|
&MindLifetimeMgmtOp::finalizeReq3,
|
||||||
context.get(), context)});
|
context.get(), context)});
|
||||||
@@ -182,7 +194,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
|
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
|
||||||
|
|
||||||
parent.exitAllMindThreadsReq(
|
parent.exitAllPuppetThreadsReq(
|
||||||
{context, std::bind(
|
{context, std::bind(
|
||||||
&MindLifetimeMgmtOp::finalizeReq4,
|
&MindLifetimeMgmtOp::finalizeReq4,
|
||||||
context.get(), context)});
|
context.get(), context)});
|
||||||
@@ -254,193 +266,4 @@ void Mind::distributeAndPinThreadsAcrossCpus()
|
|||||||
<< "across " << cpuCount << " CPUs\n";
|
<< "across " << cpuCount << " CPUs\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mind::MindThreadLifetimeMgmtOp
|
|
||||||
: public NonPostedAsynchronousContinuation<mindThreadLifetimeMgmtOpCbFn>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MindThreadLifetimeMgmtOp(
|
|
||||||
Mind &parent,unsigned int nThreads,
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback)
|
|
||||||
: NonPostedAsynchronousContinuation<mindThreadLifetimeMgmtOpCbFn>(callback),
|
|
||||||
loop(nThreads),
|
|
||||||
parent(parent)
|
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
AsynchronousLoop loop;
|
|
||||||
Mind &parent;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void joltAllMindThreadsReq1(
|
|
||||||
[[maybe_unused]] std::shared_ptr<MindThreadLifetimeMgmtOp> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
loop.incrementSuccessOrFailureDueTo(true);
|
|
||||||
if (!loop.isComplete()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.threadsHaveBeenJolted = true;
|
|
||||||
callOriginalCb();
|
|
||||||
}
|
|
||||||
|
|
||||||
void executeGenericOpOnAllMindThreadsReq1(
|
|
||||||
[[maybe_unused]] std::shared_ptr<MindThreadLifetimeMgmtOp> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
loop.incrementSuccessOrFailureDueTo(true);
|
|
||||||
if (!loop.isComplete()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callOriginalCb();
|
|
||||||
}
|
|
||||||
|
|
||||||
void exitAllMindThreadsReq1(
|
|
||||||
[[maybe_unused]] std::shared_ptr<MindThreadLifetimeMgmtOp> context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
loop.incrementSuccessOrFailureDueTo(true);
|
|
||||||
if (!loop.isComplete()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& thread : parent.componentThreads) {
|
|
||||||
thread->thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
callOriginalCb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Mind::joltAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (threadsHaveBeenJolted)
|
|
||||||
{
|
|
||||||
std::cout << "Mrntt: All mind threads already JOLTed. "
|
|
||||||
<< "Skipping JOLT request." << "\n";
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no threads, set flag and call callback immediately
|
|
||||||
if (componentThreads.size() == 0 && callback.callbackFn)
|
|
||||||
{
|
|
||||||
threadsHaveBeenJolted = true;
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a counter to track when all threads have been jolted
|
|
||||||
auto request = std::make_shared<MindThreadLifetimeMgmtOp>(
|
|
||||||
*this, componentThreads.size(), callback);
|
|
||||||
|
|
||||||
for (auto& thread : componentThreads)
|
|
||||||
{
|
|
||||||
thread->joltThreadReq(
|
|
||||||
{request, std::bind(
|
|
||||||
&MindThreadLifetimeMgmtOp::joltAllMindThreadsReq1,
|
|
||||||
request.get(), request)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread management methods (moved from ComponentThread)
|
|
||||||
void Mind::startAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// If no threads, call callback immediately
|
|
||||||
if (componentThreads.size() == 0 && callback.callbackFn)
|
|
||||||
{
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a counter to track when all threads have started
|
|
||||||
auto request = std::make_shared<MindThreadLifetimeMgmtOp>(
|
|
||||||
*this, componentThreads.size(), callback);
|
|
||||||
|
|
||||||
for (auto& thread : componentThreads)
|
|
||||||
{
|
|
||||||
thread->startThreadReq(
|
|
||||||
{request, std::bind(
|
|
||||||
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
|
|
||||||
request.get(), request)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mind::pauseAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// If no threads, call callback immediately
|
|
||||||
if (componentThreads.size() == 0 && callback.callbackFn)
|
|
||||||
{
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a counter to track when all threads have paused
|
|
||||||
auto request = std::make_shared<MindThreadLifetimeMgmtOp>(
|
|
||||||
*this, componentThreads.size(), callback);
|
|
||||||
|
|
||||||
for (auto& thread : componentThreads)
|
|
||||||
{
|
|
||||||
thread->pauseThreadReq(
|
|
||||||
{request, std::bind(
|
|
||||||
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
|
|
||||||
request.get(), request)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mind::resumeAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// If no threads, call callback immediately
|
|
||||||
if (componentThreads.size() == 0 && callback.callbackFn)
|
|
||||||
{
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a counter to track when all threads have resumed
|
|
||||||
auto request = std::make_shared<MindThreadLifetimeMgmtOp>(
|
|
||||||
*this, componentThreads.size(), callback);
|
|
||||||
|
|
||||||
for (auto& thread : componentThreads)
|
|
||||||
{
|
|
||||||
thread->resumeThreadReq(
|
|
||||||
{request, std::bind(
|
|
||||||
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
|
|
||||||
request.get(), request)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mind::exitAllMindThreadsReq(
|
|
||||||
Callback<mindThreadLifetimeMgmtOpCbFn> callback
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// If no threads, call callback immediately
|
|
||||||
if (componentThreads.size() == 0 && callback.callbackFn)
|
|
||||||
{
|
|
||||||
callback.callbackFn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a counter to track when all threads have exited
|
|
||||||
auto request = std::make_shared<MindThreadLifetimeMgmtOp>(
|
|
||||||
*this, componentThreads.size(), callback);
|
|
||||||
|
|
||||||
for (auto& thread : componentThreads)
|
|
||||||
{
|
|
||||||
thread->exitThreadReq(
|
|
||||||
{request, std::bind(
|
|
||||||
&MindThreadLifetimeMgmtOp::executeGenericOpOnAllMindThreadsReq1,
|
|
||||||
request.get(), request)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace smo
|
} // namespace smo
|
||||||
|
|||||||
Reference in New Issue
Block a user