Files
salmanoff/smocore/include/componentThread.h
T
hayodea 5845f1a41d Bug:Boost: Use shlibs instead of header-only for call_stack::top_
This symbol is defined as a static member object inside of a
boost detail header. When boost headers are used in a project
that uses Boost in both the main binary as well as dlopen()'d
shlibs, the top_ symbol gets duplicated and the metadata gets
partitioned.

We use the Boost shlib to unify both the main binary and the
shlibs to use the same memory address for top_.

This involves marking the templated object call_stack::top_ as
"extern" and then declaring to Boost that we intend to use the
shlibs.
2025-11-03 22:59:52 -04:00

178 lines
3.7 KiB
C++

#ifndef COMPONENT_THREAD_H
#define COMPONENT_THREAD_H
#include <boostAsioLinkageFix.h>
#include <atomic>
#include <thread>
#include <unordered_map>
#include <boost/asio/io_service.hpp>
#include <stdexcept>
#include <queue>
#include <functional>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>
#include <memory>
#include <callback.h>
namespace smo {
class Mind; // Forward declaration
class MarionetteThread;
class MindThread;
class ComponentThread
{
public:
enum ThreadId
{
MRNTT = 0,
DIRECTOR,
SIMULATOR,
SUBCONSCIOUS,
BODY,
WORLD,
N_ITEMS
};
protected:
ComponentThread(ThreadId _id)
: id(_id), name(getThreadName(_id)),
work(io_service)
{}
public:
virtual ~ComponentThread() = default;
void cleanup(void);
boost::asio::io_service& getIoService(void) { return io_service; }
static const std::shared_ptr<ComponentThread> getSelf(void);
static std::shared_ptr<MarionetteThread> getMrntt();
typedef void (mainFn)(ComponentThread &self);
// CPU management methods
static int getAvailableCpuCount();
typedef std::function<void()> mindShutdownIndOpCbFn;
// Intentionally doesn't take a callback.
void exceptionInd(const std::shared_ptr<ComponentThread> &faultyThread);
// Intentionally doesn't take a callback.
void userShutdownInd();
public:
ThreadId id;
std::string name;
boost::asio::io_service io_service;
boost::asio::io_service::work work;
std::atomic<bool> keepLooping;
static const std::string getThreadName(ThreadId id)
{
if (id < 0 || id >= ComponentThread::N_ITEMS)
{
throw std::runtime_error(std::string(__func__)
+ ": Invalid thread ID");
}
// Use function-local static to ensure proper initialization order
static const std::string threadNames[N_ITEMS] = {
"mrntt",
"director",
"simulator",
"subconscious",
"body",
"world"
};
return threadNames[id];
}
};
class MarionetteThread
: public std::enable_shared_from_this<MarionetteThread>,
public ComponentThread
{
public:
MarionetteThread()
: ComponentThread(MRNTT),
thread(main, std::ref(*this))
{
}
static void main(MarionetteThread& self);
void initializeTls(void);
public:
std::thread thread;
};
class MindThread
: public std::enable_shared_from_this<MindThread>, public ComponentThread
{
public:
enum class ThreadOp
{
START,
PAUSE,
RESUME,
EXIT,
JOLT,
N_ITEMS
};
MindThread(ThreadId _id, Mind& parent)
: ComponentThread(_id),
pinnedCpuId(-1),
pause_work(pause_io_service),
parent(parent),
thread(main, std::ref(*this))
{
}
static void main(MindThread& self);
void initializeTls(void);
Mind& getParent() const { return parent; }
// Thread management methods
typedef std::function<void()> threadLifetimeMgmtOpCbFn;
void startThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void exitThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void pauseThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
void resumeThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
/**
* JOLTs this thread to begin processing after global initialization.
*
* JOLTing is the mechanism that allows threads to enter their main
* event loops and set up TLS vars after all global constructors have
* completed. This prevents race conditions during system startup.
*/
void joltThreadReq(Callback<threadLifetimeMgmtOpCbFn> callback);
// CPU management methods
void pinToCpu(int cpuId);
public:
int pinnedCpuId;
boost::asio::io_service pause_io_service;
boost::asio::io_service::work pause_work;
Mind& parent;
std::thread thread;
public:
class ThreadLifetimeMgmtOp;
class MindShutdownIndOp;
};
namespace mrntt {
extern std::shared_ptr<MarionetteThread> thread;
} // namespace mrntt
} // namespace smo
#endif // COMPONENT_THREAD_H