diff --git a/hcore/Makefile.am b/hcore/Makefile.am index 8c63061..6ad78cf 100644 --- a/hcore/Makefile.am +++ b/hcore/Makefile.am @@ -2,4 +2,5 @@ SUBDIRS = deviceManager senseApis AM_CPPFLAGS+= -I"$(top_srcdir)/hcore/include" noinst_LIBRARIES = libhcore.a -libhcore_a_SOURCES = mind.cpp opts.cpp +libhcore_a_SOURCES = mind.cpp opts.cpp componentThreads.cpp + diff --git a/hcore/componentThreads.cpp b/hcore/componentThreads.cpp new file mode 100644 index 0000000..0d9a460 --- /dev/null +++ b/hcore/componentThreads.cpp @@ -0,0 +1,23 @@ +#include + +namespace hk { + +namespace director { +ComponentThread director; +} +namespace simulator { +ComponentThread canvas; +} +namespace subconscious { +ComponentThread subconscious; +} + +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} +}; + +} // namespace hk diff --git a/hcore/include/componentThread.h b/hcore/include/componentThread.h new file mode 100644 index 0000000..8b3dcfc --- /dev/null +++ b/hcore/include/componentThread.h @@ -0,0 +1,61 @@ +#ifndef COMPONENT_THREAD_H +#define COMPONENT_THREAD_H + +#include +#include +#include +#include +#include + +namespace hk { + +class ComponentThread +{ +public: + ComponentThread() + : work(io_service), startupSync() + {} + + boost::asio::io_service& getIoService(void) { return io_service; } + + static boost::asio::io_service& getEventLoop( + std::thread::id id = std::this_thread::get_id()) + { + auto it = componentThreads.find(id); + if (it == componentThreads.end()) + { + throw std::runtime_error(std::string(__func__) + + ": Thread ID not found in componentThreads map"); + } + + return it->second.getIoService(); + } + +public: + boost::asio::io_service io_service; + boost::asio::io_service::work work; + std::thread thread; + struct StartupSync { + std::mutex mutex; + std::condition_variable cv; + bool ready; + + StartupSync() : ready(false) {} + } startupSync; + + static std::unordered_map componentThreads; +}; + +namespace director { +extern ComponentThread director; +} +namespace simulator { +extern ComponentThread canvas; +} +namespace subconscious { +extern ComponentThread subconscious; +} + +} // namespace hk + +#endif // COMPONENT_THREAD_H diff --git a/main.cpp b/main.cpp index d69828c..fb2d9bf 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,61 @@ #include #include +#include +#include +#include +#include +#include #include #include #include #include +#include "componentThread.h" +namespace hk { -int main(int argc, char **argv) +static int initializeHarikoff(int argc, char **argv, char **envp); +void startThreads(); +void signalThreads(); + +} // namespace hk + +int main(int argc, char **argv, char **envp) { - using namespace hk; + try { + std::cout << __func__ << ": Entering main()" << std::endl; -try { + // Print out the keys for each index in the map + for (const auto& [id, componentThread] + : hk::ComponentThread::componentThreads) + { + std::cout << __func__ << ": Thread ID: " << id << std::endl; + } + + int ret = hk::initializeHarikoff(argc, argv, envp); + if (ret != 0) { + return ret; + } + } + catch (const std::exception& e) { + std::cerr << __func__ << ": Exception occurred: " << e.what() << std::endl; + return EXIT_FAILURE; + } + catch (...) { + std::cerr << __func__ << ": Unknown exception occurred" << std::endl; + return EXIT_FAILURE; + } + + std::cout << __func__ << ": Exiting normally" << std::endl; + return 0; +} + +namespace hk { + +static int initializeHarikoff(int argc, char **argv, char **envp) +{ + std::cout << __func__ << ": Entering" << std::endl; + + using namespace hk; OptionParser &options = OptionParser::getOptions(); hk::Mind mind; @@ -20,7 +65,7 @@ try { options.parseArguments(argc, argv); } catch (const std::invalid_argument& e) { - std::cerr << e.what() << '\n' << options.getUsage() << '\n'; + std::cerr << __func__ << ": Exception occurred: " << e.what() << '\n' << options.getUsage() << '\n'; return EXIT_FAILURE; } @@ -34,16 +79,39 @@ try { DeviceManager::getInstance().parseAllDeviceSpecs(); std::cout << DeviceManager::printDeviceSpecs() << std::endl; sense_api::SenseApiManager::getInstance().loadAllSenseApiLibsFromOptions(); -} -catch (const std::exception& e) { - std::cerr << "Exception occurred: " << e.what() << std::endl; - return EXIT_FAILURE; -} -catch (...) { - std::cerr << "Unknown exception occurred" << std::endl; - return EXIT_FAILURE; + + std::cout << __func__ << ": Exiting" << std::endl; + return 0; } - std::cout << "Exiting normally" << std::endl; - return 0; +void startThreads() +{ + for (auto& [id, componentThread] : ComponentThread::componentThreads) { + componentThread.thread = std::thread([&componentThread]() { + // We sleep on spawn until the marionette tells us to continue. + { + std::unique_lock lock( + componentThread.startupSync.mutex); + + componentThread.startupSync.cv.wait(lock, [&componentThread]() { + return componentThread.startupSync.ready; + }); + } + + componentThread.getIoService().run(); + }); + } } + +void signalThreads() +{ + for (auto& [id, componentThread] : ComponentThread::componentThreads) { + { + std::lock_guard lock(componentThread.startupSync.mutex); + componentThread.startupSync.ready = true; + } + componentThread.startupSync.cv.notify_one(); + } +} + +} // namespace hk