Libspinscale: Initial top-level SMO port to coroutine framework
We haven't ported everything. Just the top-level methods. We'll dig in to the leaf stuff later. Surprisingly, this all went without any real difficulties. Runs like a charm on first try.
This commit is contained in:
+42
-152
@@ -2,11 +2,6 @@
|
||||
#include <iostream>
|
||||
#include <opts.h>
|
||||
#include <componentThread.h>
|
||||
#include <spinscale/asynchronousContinuation.h>
|
||||
#include <spinscale/asynchronousLoop.h>
|
||||
#include <spinscale/callback.h>
|
||||
#include <spinscale/callableTracer.h>
|
||||
#include <spinscale/componentThread.h>
|
||||
#include <mind.h>
|
||||
#include <mindThread.h>
|
||||
#include <director/director.h>
|
||||
@@ -63,17 +58,17 @@ Mind::getComponentThread(sscl::ThreadId id) const
|
||||
"getComponentThread");
|
||||
}
|
||||
|
||||
// Search through the vector for the thread with matching id
|
||||
for (auto& thread : componentThreads)
|
||||
// Search through the vector for the thread with matching id
|
||||
for (auto& thread : componentThreads)
|
||||
{
|
||||
if (thread->id == id) {
|
||||
if (thread->id == id) {
|
||||
return std::static_pointer_cast<MindThread>(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Throw exception if no thread found
|
||||
throw std::runtime_error(std::string(__func__) +
|
||||
": No MindThread found with ID "
|
||||
// Throw exception if no thread found
|
||||
throw std::runtime_error(std::string(__func__) +
|
||||
": No MindThread found with ID "
|
||||
+ std::to_string(static_cast<int>(id)));
|
||||
}
|
||||
|
||||
@@ -88,16 +83,16 @@ Mind::getComponentThread(const std::string& name) const
|
||||
"getComponentThread");
|
||||
}
|
||||
|
||||
for (auto& thread : componentThreads)
|
||||
for (auto& thread : componentThreads)
|
||||
{
|
||||
if (thread->name == name) {
|
||||
if (thread->name == name) {
|
||||
return std::static_pointer_cast<MindThread>(thread);
|
||||
}
|
||||
}
|
||||
|
||||
// Throw exception if no thread found
|
||||
throw std::runtime_error(std::string(__func__) +
|
||||
": No MindThread found with name '" + name + "'");
|
||||
// Throw exception if no thread found
|
||||
throw std::runtime_error(std::string(__func__) +
|
||||
": No MindThread found with name '" + name + "'");
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<MindThread>>
|
||||
@@ -111,152 +106,47 @@ Mind::getMindThreads() const
|
||||
return mindThreads;
|
||||
}
|
||||
|
||||
class Mind::MindLifetimeMgmtOp
|
||||
: public sscl::PostedAsynchronousContinuation<mindLifetimeMgmtOpCbFn>
|
||||
mrntt::MrnttViralNonPostingInvokerT<bool> Mind::initializeCReq()
|
||||
{
|
||||
public:
|
||||
MindLifetimeMgmtOp(
|
||||
Mind &parent, const std::shared_ptr<sscl::ComponentThread> &caller,
|
||||
sscl::Callback<mindLifetimeMgmtOpCbFn> callback)
|
||||
: sscl::PostedAsynchronousContinuation<mindLifetimeMgmtOpCbFn>(
|
||||
caller, callback),
|
||||
parent(parent)
|
||||
{}
|
||||
|
||||
public:
|
||||
Mind &parent;
|
||||
|
||||
public:
|
||||
void initializeReq1_posted(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
try
|
||||
{
|
||||
/* Jolt the threads, then start them */
|
||||
parent.joltAllPuppetThreadsReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::initializeReq2,
|
||||
context.get(), context)});
|
||||
distributeAndPinThreadsAcrossCpus();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Salmanoff couldn't distribute the mind threads across "
|
||||
"the CPUs, so performance may be suboptimal.\n"
|
||||
"Error: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
void initializeReq2(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
{
|
||||
std::cout << "Mrntt: All mind threads JOLTed." << "\n";
|
||||
co_await joltAllPuppetThreadsCReq();
|
||||
std::cout << "Mrntt: All mind threads JOLTed." << "\n";
|
||||
|
||||
parent.startAllPuppetThreadsReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::initializeReq3,
|
||||
context.get(), context)});
|
||||
}
|
||||
co_await startAllPuppetThreadsCReq();
|
||||
std::cout << "Mrntt: All mind threads started." << "\n";
|
||||
|
||||
void initializeReq3(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
{
|
||||
std::cout << "Mrntt: All mind threads started." << "\n";
|
||||
bool bodyInitialized = co_await body.initializeCReq();
|
||||
std::cout << "Mrntt: Body component initialized." << "\n";
|
||||
|
||||
parent.body.initializeReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::initializeReq4,
|
||||
context.get(), context, std::placeholders::_1)});
|
||||
}
|
||||
|
||||
void initializeReq4(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context,
|
||||
bool success
|
||||
)
|
||||
{
|
||||
std::cout << "Mrntt: Body component initialized." << "\n";
|
||||
callOriginalCb(success);
|
||||
}
|
||||
|
||||
void finalizeReq1_posted(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
{
|
||||
parent.body.finalizeReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::finalizeReq2,
|
||||
context.get(), context, std::placeholders::_1)});
|
||||
}
|
||||
|
||||
void finalizeReq2(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context,
|
||||
bool success
|
||||
)
|
||||
{
|
||||
if (!success) {
|
||||
std::cerr << "Mrntt: Body component failed to finalize." << "\n";
|
||||
} else {
|
||||
std::cout << "Mrntt: Body component finalized." << "\n";
|
||||
}
|
||||
|
||||
/* If the threads haven't been jolted, we need to do that first, because
|
||||
* otherwise they'll just enter their main loops and wait for control
|
||||
* messages from mrntt after processing the exit request.
|
||||
*/
|
||||
parent.joltAllPuppetThreadsReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::finalizeReq3,
|
||||
context.get(), context)});
|
||||
}
|
||||
|
||||
void finalizeReq3(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
{
|
||||
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
|
||||
|
||||
parent.exitAllPuppetThreadsReq(
|
||||
{context, std::bind(
|
||||
&MindLifetimeMgmtOp::finalizeReq4,
|
||||
context.get(), context)});
|
||||
}
|
||||
|
||||
void finalizeReq4(
|
||||
[[maybe_unused]] std::shared_ptr<MindLifetimeMgmtOp> context
|
||||
)
|
||||
{
|
||||
std::cout << "Mrntt: All mind threads exited." << "\n";
|
||||
callOriginalCb(true);
|
||||
}
|
||||
};
|
||||
|
||||
void Mind::initializeReq(sscl::Callback<mindLifetimeMgmtOpCbFn> callback)
|
||||
{
|
||||
/* Distribute threads across available CPUs */
|
||||
try
|
||||
{
|
||||
distributeAndPinThreadsAcrossCpus();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "Salmanoff couldn't distribute the mind threads across "
|
||||
"the CPUs, so performance may be suboptimal.\n"
|
||||
"Error: " << e.what() << "\n";
|
||||
}
|
||||
|
||||
const auto& caller = sscl::ComponentThread::getSelf();
|
||||
auto request = std::make_shared<MindLifetimeMgmtOp>(
|
||||
*this, caller, callback);
|
||||
|
||||
mrntt::mrntt.thread->getIoService().post(
|
||||
STC(std::bind(
|
||||
&MindLifetimeMgmtOp::initializeReq1_posted,
|
||||
request.get(), request)));
|
||||
co_return bodyInitialized;
|
||||
}
|
||||
|
||||
void Mind::finalizeReq(sscl::Callback<mindLifetimeMgmtOpCbFn> callback)
|
||||
mrntt::MrnttViralNonPostingInvokerT<bool> Mind::finalizeCReq()
|
||||
{
|
||||
const auto& caller = sscl::ComponentThread::getSelf();
|
||||
auto request = std::make_shared<MindLifetimeMgmtOp>(
|
||||
*this, caller, callback);
|
||||
bool bodyFinalized = co_await body.finalizeCReq();
|
||||
if (!bodyFinalized) {
|
||||
std::cerr << "Mrntt: Body component failed to finalize." << "\n";
|
||||
} else {
|
||||
std::cout << "Mrntt: Body component finalized." << "\n";
|
||||
}
|
||||
|
||||
mrntt::mrntt.thread->getIoService().post(
|
||||
STC(std::bind(
|
||||
&MindLifetimeMgmtOp::finalizeReq1_posted,
|
||||
request.get(), request)));
|
||||
co_await joltAllPuppetThreadsCReq();
|
||||
std::cout << "Mrntt: All mind threads JOLTed for finalization." << "\n";
|
||||
|
||||
co_await exitAllPuppetThreadsCReq();
|
||||
std::cout << "Mrntt: All mind threads exited." << "\n";
|
||||
|
||||
co_return bodyFinalized;
|
||||
}
|
||||
|
||||
} // namespace smo
|
||||
|
||||
Reference in New Issue
Block a user