1deb92a416
This allows us to execute an op on all mind threads without having to repeatedly write loops. We've implemented wrappers to handle start, pause, resume, exit and JOLT sequences.
155 lines
3.9 KiB
C++
155 lines
3.9 KiB
C++
#ifndef COMPONENT_THREAD_H
|
|
#define COMPONENT_THREAD_H
|
|
|
|
#include <atomic>
|
|
#include <thread>
|
|
#include <unordered_map>
|
|
#include <boost/asio.hpp>
|
|
#include <stdexcept>
|
|
#include <queue>
|
|
#include <functional>
|
|
|
|
namespace smo {
|
|
|
|
class ComponentThread
|
|
: public std::enable_shared_from_this<ComponentThread>
|
|
{
|
|
public:
|
|
enum ThreadId
|
|
{
|
|
MRNTT = 0,
|
|
DIRECTOR,
|
|
SIMULATOR,
|
|
SUBCONSCIOUS,
|
|
BODY,
|
|
WORLD,
|
|
N_ITEMS
|
|
};
|
|
|
|
ComponentThread(ThreadId id)
|
|
: id(id), name(getThreadName(id)),
|
|
work(io_service), pause_work(pause_io_service),
|
|
thread(
|
|
((id == MRNTT) ? marionetteMain : main),
|
|
std::ref(*this))
|
|
{}
|
|
|
|
void cleanup(void);
|
|
|
|
boost::asio::io_service& getIoService(void) { return io_service; }
|
|
|
|
void initializeTls(void);
|
|
static const std::shared_ptr<ComponentThread> getSelf(void);
|
|
|
|
static std::shared_ptr<ComponentThread> getComponentThread(
|
|
ThreadId id = N_ITEMS)
|
|
{
|
|
if (id < 0 || id > N_ITEMS)
|
|
{
|
|
throw std::runtime_error(std::string(__func__)
|
|
+ ": Invalid thread ID");
|
|
}
|
|
return componentThreads[id];
|
|
}
|
|
|
|
// Overload: search by name
|
|
static std::shared_ptr<ComponentThread> getComponentThread(
|
|
const std::string& name)
|
|
{
|
|
for (auto& thread : componentThreads) {
|
|
if (thread->name == name) { return thread; }
|
|
}
|
|
throw std::runtime_error(std::string(__func__)
|
|
+ ": Thread name not found in componentThreads map");
|
|
}
|
|
|
|
static boost::asio::io_service& getEventLoop(
|
|
ThreadId id = MRNTT)
|
|
{
|
|
return getComponentThread(id)->getIoService();
|
|
}
|
|
|
|
|
|
typedef void (mainFn)(ComponentThread &self);
|
|
static mainFn main, marionetteMain;
|
|
|
|
// Thread management methods
|
|
void startThreadReq(std::function<void()> callback = nullptr);
|
|
void exitThreadReq(std::function<void()> callback = nullptr);
|
|
void pauseThreadReq(std::function<void()> callback = nullptr);
|
|
void resumeThreadReq(std::function<void()> callback = nullptr);
|
|
void joltThreadReq(std::function<void()> callback = nullptr);
|
|
|
|
// Convenience wrappers
|
|
static void startAllMindThreadsReq(std::function<void()> callback = nullptr);
|
|
static void pauseAllMindThreadsReq(std::function<void()> callback = nullptr);
|
|
static void resumeAllMindThreadsReq(std::function<void()> callback = nullptr);
|
|
static void exitAllMindThreadsReq(std::function<void()> callback = nullptr);
|
|
static void joltAllMindThreadsReq(std::function<void()> callback = nullptr);
|
|
|
|
enum class ThreadOp
|
|
{
|
|
START,
|
|
PAUSE,
|
|
RESUME,
|
|
EXIT,
|
|
JOLT,
|
|
N_ITEMS
|
|
};
|
|
static void execOpOnAllMindThreadsReq(
|
|
ThreadOp op, std::function<void()> callback = nullptr);
|
|
|
|
// Intentionally doesn't take a callback.
|
|
void exceptionInd(ComponentThread& thread);
|
|
|
|
public:
|
|
ThreadId id;
|
|
std::string name;
|
|
boost::asio::io_service io_service;
|
|
boost::asio::io_service::work work;
|
|
boost::asio::io_service pause_io_service;
|
|
boost::asio::io_service::work pause_work;
|
|
std::atomic<bool> keepLooping;
|
|
|
|
/* Always ensure that this is last so that the thread is spawned after
|
|
* everything else is constructed.
|
|
*/
|
|
std::thread thread;
|
|
static std::array<std::shared_ptr<ComponentThread>, ComponentThread::N_ITEMS>
|
|
componentThreads;
|
|
|
|
static const std::string threadNames[ComponentThread::N_ITEMS];
|
|
static const std::string getThreadName(ThreadId id)
|
|
{
|
|
if (id < 0 || id >= ComponentThread::N_ITEMS)
|
|
{
|
|
throw std::runtime_error(std::string(__func__)
|
|
+ ": Invalid thread ID");
|
|
}
|
|
return threadNames[id];
|
|
}
|
|
};
|
|
|
|
namespace mrntt {
|
|
extern std::shared_ptr<ComponentThread> mrntt;
|
|
}
|
|
namespace director {
|
|
extern std::shared_ptr<ComponentThread> director;
|
|
}
|
|
namespace simulator {
|
|
extern std::shared_ptr<ComponentThread> canvas;
|
|
}
|
|
namespace subconscious {
|
|
extern std::shared_ptr<ComponentThread> subconscious;
|
|
}
|
|
namespace body {
|
|
extern std::shared_ptr<ComponentThread> body;
|
|
}
|
|
namespace world {
|
|
extern std::shared_ptr<ComponentThread> world;
|
|
}
|
|
|
|
} // namespace smo
|
|
|
|
#endif // COMPONENT_THREAD_H
|