void RuntimeSystem::addModule(const std::string& moduleClassName, int moduleID) { IModule* newModule = moduleFactory.buildNewModule(moduleClassName, typeFactory); newModule->setID(moduleID); ModuleControlBlockPtr newBlock ( new ModuleControlBlock(newModule) ); m_modules[moduleID] = newBlock; // no output or notdeterministic => module is a sink if (( newModule->getOutputs().size() == 0 ) || ( !newModule->isDeterministic()) ) m_sinks.push_front(newBlock); #if (ENGINE_VERBOSITY > 0) std::cout << "Added new Module (id " << moduleID << ") of Class " << moduleClassName << std::endl; #endif }
void RuntimeSystem::deleteModule(int moduleID) { // get the control block for the moduleid ControlBlockMap::iterator it = m_modules.find(moduleID); if (it == m_modules.end()) { // a module with that id doesnt exist throw std::runtime_error("Module does not exist at " "RuntimeSystem::deleteModule()"); } // a module with that id must exist assert(it != m_modules.end()); ModuleControlBlockPtr block = it->second; IModule* n = block->module(); // disconnect all modules that are connected to an output for (ControlBlockMap::iterator i = m_modules.begin(); i != m_modules.end(); ++i) { // is this possible? // if (i->second == 0) continue; assert(i->second != 0); ModuleControlBlockPtr block = i->second; IModule* m = block->module(); // check all inputs of that module for (unsigned int j = 0; j < m->getInputs().size(); ++j) { IModule::IInputPtr in = m->getInputs()[j]; // is it connected? if (in->getConnectedModule() == n) { // yes, the unplug it in->unPlug(); // and signal change block->hasChanged(j); } } } // disconnect all modules that are connected to an input for (unsigned int j = 0; j < n->getInputs().size(); ++j) { IModule::IInputPtr in = n->getInputs()[j]; if (in->getConnectedModule() != 0) in->unPlug(); } // remove the module from the sink list if (n->getOutputs().size() == 0 || !n->isDeterministic()) m_sinks.remove(block); // remove it from the module set // the module control block should be deleted here by its autoptr m_modules.erase(it); #if (ENGINE_VERBOSITY > 0) std::cout << "Deleted Module # " << moduleID << std::endl; #endif }
void RuntimeSystem::update(IControlValueReceiver* cvr, IModuleStatisticsReceiver* msr) { std::stack<ModuleControlBlockPtr> stack; // push the sinks (modules with no output) on the stack for (std::list<ModuleControlBlockPtr>::iterator sink = m_sinks.begin(); sink != m_sinks.end(); ++sink) { (*sink)->activate(); stack.push(*sink); } #if (ENGINE_VERBOSITY > 2) std::cout << " ***** update begins\n"; std::cout << "Pushed all m_sinks onto the stack." << std::endl; std::cout << "Number of m_sinks: " << m_sinks.size() << std::endl; #endif while (!stack.empty()) { ModuleControlBlockPtr block = stack.top(); IModule* m = block->module(); assert (block->isActive()); #if (ENGINE_VERBOSITY > 3) std::cout << "On Stack: " << m->getID() << "\n"; #endif IInput* dep = m->dependencies(); // is there a not satisfied dependency left? if (dep != 0) { IModule* temp = dep->getConnectedModule(); // is the input connected to an other module? if (temp != 0) { #if (ENGINE_VERBOSITY > 3) std::cout << " Following connection to " << temp->getID() << "\n"; #endif // check that module ModuleControlBlockPtr current = getControlBlock(temp); // 1. in case the module is on the stack we detected a cycle // the solution is to use the old value of that output // 2. the module is already updatet in this cycle // we dont want do update it again if (current->isActive()||(current->lastUpdated()==frameCount)) { // it could be that the value changed (conservative) block->setChanged(dep->getIndex()); #if (ENGINE_VERBOSITY > 3) std::cout << " [already done]" << temp->getID() << "\n"; #endif } else { #if (ENGINE_VERBOSITY > 3) std::cout << " [pushed on stack]" << temp->getID() << "\n"; #endif // we must update this module current->activate(); stack.push(current); } } } else { // all dependencies are satisfied // is a update necessary? if (!m->isDeterministic() || block->hasChanged()) { #if (ENGINE_VERBOSITY > 3) std::cout << " Updating...\n"; #endif // lets update the module unsigned long startTime = utils::Timing::getTimeInMillis(); //TODO: if an exception is caught, remove the module! try { m->update(); } catch (std::exception& e){ std::ostringstream os; os << "error at update: " << e.what() << "\n" << "module id = " << m->getID() << "\n" << "module class = " << m->module_class_name() << "\n"; m_logger->error("Runtimesystem", os.str()); } catch (...) { std::ostringstream os; os << "error at update\n" << "module id = " << m->getID() << "\n" << "module class = " << m->module_class_name() << "\n"; m_logger->error("Runtimesystem", os.str()); } unsigned long stopTime = utils::Timing::getTimeInMillis(); block->addTime(stopTime-startTime); // should we send the statistic data? // is there a receiver? // is it the right time? if (msr != 0 && (frameCount & 7) == 7) { // send statistic data msr->modExecTimeSignal(m->getID(),block->avgTime()); } // send the changes values to the controlValueReceiver // and set them there to changed sendInputValues(block,cvr,m_modules,frameCount); } else { #if (ENGINE_VERBOSITY > 3) std::cout << " Skipping update (deterministic and no " << "needed input changed)...\n"; #endif } // this module is now updated stack.pop(); block->reset(); block->updated(frameCount); } } // all sinks are uptodate we can finish now // increase the timestamp ++frameCount; #if (ENGINE_VERBOSITY > 2) std::cout << "**** update finished" << std::endl; #endif }