#include #include namespace hk { namespace director { /* The director is the seat of volition in Harikoff. It receives sensor * events from the body and world, and uses them to direct its implexors * to implex new menties. It then loads the menties into canvas for simulation * and correlation with intrins, in order to form new attrimotions and * menties. */ ComponentThread director; } namespace simulator { /* The canvas is the simulation engine in Harikoff. It receives menties and * simulates them in accordance with the instructions from director. It then * re-renders them into perception for director to get feedback. */ ComponentThread canvas; } namespace subconscious { /* The subconscious is the seat of memory in Harikoff. It receives menties * from director and stores them in memory for later recall. */ ComponentThread subconscious; } namespace body { /* The body is a thread that polls, processes, and sends interoceptive sensor * events to director. It enables these events to occur asynchronously, * indepdendent any actions that the other threads are taking. */ ComponentThread body; } namespace world { /* The world performs the same functions as the body, but for extrospective * sensor events. */ ComponentThread world; } std::unordered_map ComponentThread::componentThreads = { {director::director.thread.get_id(), director::director}, {simulator::canvas.thread.get_id(), simulator::canvas}, {subconscious::subconscious.thread.get_id(), subconscious::subconscious}, {body::body.thread.get_id(), body::body}, {world::world.thread.get_id(), world::world} }; void ComponentThread::signalThread(std::thread::id id) { auto it = componentThreads.find(id); if (it == componentThreads.end()) { throw std::runtime_error(std::string(__func__) + ": Thread ID not found in componentThreads map"); } ComponentThread& componentThread = it->second; { std::lock_guard lock(componentThread.startupSync.mutex); componentThread.startupSync.ready = true; } componentThread.startupSync.cv.notify_one(); } void ComponentThread::main(ComponentThread& self) { // We sleep on spawn until the main thread tells us to continue. { std::unique_lock lock(self.startupSync.mutex); self.startupSync.cv.wait(lock, [&self]() { return self.startupSync.ready; }); } std::cout << __func__ << ": Starting event loop." << std::endl; self.getIoService().run(); std::cout << __func__ << ": Exiting." << std::endl; } void ComponentThread::validateThreadIds(void) { for (const auto& [id, componentThread] : componentThreads) { // std::thread::id() is usable as an invalid ID. if (id == std::thread::id()) { throw std::runtime_error( std::string(__func__) + ": Invalid Thread ID."); } } } } // namespace hk