Newer
Older
Martin Christoph Hierholzer
committed
/*
* ApplicationModule.cc
*
* Created on: Jun 17, 2016
* Author: Martin Hierholzer
*/
Martin Christoph Hierholzer
committed
#include "ApplicationCore.h"
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
ApplicationModule::ApplicationModule(EntityOwner *owner, const std::string &name, const std::string &description,
bool eliminateHierarchy, const std::unordered_set<std::string> &tags)
Martin Christoph Hierholzer
committed
: ModuleImpl(owner,name,description,eliminateHierarchy,tags)
Martin Christoph Hierholzer
committed
{
if(!dynamic_cast<ModuleGroup*>(owner) && !dynamic_cast<Application*>(owner)) {
Martin Christoph Hierholzer
committed
throw ChimeraTK::logic_error("ApplicationModules must be owned either by ModuleGroups or the Application!");
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
if(name.find_first_of("/") != std::string::npos) {
throw ChimeraTK::logic_error("Module names must not contain slashes: '"+name+" owned by '"
+owner->getQualifiedName()+"'.");
}
Martin Christoph Hierholzer
committed
}
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
void ApplicationModule::run() {
Martin Christoph Hierholzer
committed
// start the module thread
assert(!moduleThread.joinable());
Martin Christoph Hierholzer
committed
moduleThread = boost::thread(&ApplicationModule::mainLoopWrapper, this);
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
void ApplicationModule::terminate() {
if(moduleThread.joinable()) {
moduleThread.interrupt();
Martin Christoph Hierholzer
committed
// try joining the thread
while(!moduleThread.try_join_for(boost::chrono::milliseconds(10))) {
// if thread is not yet joined, send interrupt() to all variables.
for(auto &var : getAccessorListRecursive()) {
if(var.getDirection() != VariableDirection::consuming) continue;
var.getAppAccessorNoType().getHighLevelImplElement()->interrupt();
}
// it may not suffice to send interrupt() once, as the exception might get overwritten in the queue, thus we
// repeat this until the thread was joined.
Martin Christoph Hierholzer
committed
}
assert(!moduleThread.joinable());
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
ApplicationModule::~ApplicationModule() {
assert(!moduleThread.joinable());
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
/*********************************************************************************************************************/
Martin Christoph Hierholzer
committed
void ApplicationModule::mainLoopWrapper() {
Martin Christoph Hierholzer
committed
Application::registerThread("AM_"+getName());
Application::testableModeLock("start");
Martin Christoph Hierholzer
committed
// enter the main loop
mainLoop();
Application::testableModeUnlock("terminate");
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
} /* namespace ChimeraTK */