ExecutableModel* LLVMModelGenerator::createModel(const std::string& sbml, uint options) { bool computeAndAssignConsevationLaws = options & ModelGenerator::ComputeAndAssignConsevationLaws; bool forceReCompile = options & ModelGenerator::ForceReCompile; string md5; if (!forceReCompile) { // check for a chached copy md5 = rr::getMD5(sbml); ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); if ((i = cachedModels.find(md5)) != cachedModels.end()) { sp = i->second.lock(); } cachedModelsMutex.unlock(); // we could have recieved a bad ptr, a model could have been deleted, // in which case, we should have a bad ptr. if (sp) { Log(Logger::PRIO_DEBUG) << "found a cached model for " << md5; return new LLVMExecutableModel(sp); } else { Log(Logger::PRIO_TRACE) << "no cached model found for " << md5 << ", creating new one"; } } SharedModelPtr rc(new ModelResources()); ModelGeneratorContext context(sbml, computeAndAssignConsevationLaws); rc->evalInitialConditionsPtr = EvalInitialConditionsCodeGen(context).createFunction(); rc->evalReactionRatesPtr = EvalReactionRatesCodeGen(context).createFunction(); rc->getBoundarySpeciesAmountPtr = GetBoundarySpeciesAmountCodeGen(context).createFunction(); rc->getFloatingSpeciesAmountPtr = GetFloatingSpeciesAmountCodeGen(context).createFunction(); rc->getBoundarySpeciesConcentrationPtr = GetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->getFloatingSpeciesConcentrationPtr = GetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->getCompartmentVolumePtr = GetCompartmentVolumeCodeGen(context).createFunction(); rc->getGlobalParameterPtr = GetGlobalParameterCodeGen(context).createFunction(); rc->evalRateRuleRatesPtr = EvalRateRuleRatesCodeGen(context).createFunction(); rc->getEventTriggerPtr = GetEventTriggerCodeGen(context).createFunction(); rc->getEventPriorityPtr = GetEventPriorityCodeGen(context).createFunction(); rc->getEventDelayPtr = GetEventDelayCodeGen(context).createFunction(); rc->eventTriggerPtr = EventTriggerCodeGen(context).createFunction(); rc->eventAssignPtr = EventAssignCodeGen(context).createFunction(); rc->evalVolatileStoichPtr = EvalVolatileStoichCodeGen(context).createFunction(); rc->evalConversionFactorPtr = EvalConversionFactorCodeGen(context).createFunction(); if (options & ModelGenerator::ReadOnlyModel) { rc->setBoundarySpeciesAmountPtr = 0; rc->setBoundarySpeciesConcentrationPtr = 0; rc->setFloatingSpeciesConcentrationPtr = 0; rc->setCompartmentVolumePtr = 0; rc->setFloatingSpeciesAmountPtr = 0; rc->setGlobalParameterPtr = 0; } else { rc->setBoundarySpeciesAmountPtr = SetBoundarySpeciesAmountCodeGen( context).createFunction(); rc->setBoundarySpeciesConcentrationPtr = SetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->setFloatingSpeciesConcentrationPtr = SetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->setCompartmentVolumePtr = SetCompartmentVolumeCodeGen(context).createFunction(); rc->setFloatingSpeciesAmountPtr = SetFloatingSpeciesAmountCodeGen( context).createFunction(); rc->setGlobalParameterPtr = SetGlobalParameterCodeGen(context).createFunction(); } // if anything up to this point throws an exception, thats OK, because // we have not allocated any memory yet that is not taken care of by // something else. // Now that everything that could have thrown would have thrown, we // can now create the model and set its fields. // * MOVE * the bits over from the context to the exe model. context.stealThePeach(&rc->symbols, &rc->context, &rc->executionEngine, &rc->errStr); if (!forceReCompile) { // check for a chached copy, another thread could have // created one while we were making ours... ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); // whilst we have it locked, clear any expired ptrs for (ModelPtrMap::const_iterator j = cachedModels.begin(); j != cachedModels.end();) { if (j->second.expired()) { Log(Logger::PRIO_INFORMATION) << "removing expired model resource for hash " << md5; j = cachedModels.erase(j); } else { ++j; } } if ((i = cachedModels.find(md5)) == cachedModels.end()) { Log(Logger::PRIO_INFORMATION) << "could not find existing cached resource " "resources, for hash " << md5 << ", inserting new resources into cache"; cachedModels[md5] = rc; } cachedModelsMutex.unlock(); } return new LLVMExecutableModel(rc); }
ExecutableModel* LLVMModelGenerator::createModel(const std::string& sbml, uint options) { bool forceReCompile = options & LoadSBMLOptions::RECOMPILE; string md5; if (!forceReCompile) { // check for a chached copy md5 = rr::getMD5(sbml); if (options & LoadSBMLOptions::CONSERVED_MOIETIES) { md5 += "_conserved"; } ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); if ((i = cachedModels.find(md5)) != cachedModels.end()) { sp = i->second.lock(); } cachedModelsMutex.unlock(); // we could have recieved a bad ptr, a model could have been deleted, // in which case, we should have a bad ptr. if (sp) { Log(Logger::LOG_DEBUG) << "found a cached model for " << md5; return new LLVMExecutableModel(sp, createModelData(*sp->symbols, sp->random)); } else { Log(Logger::LOG_TRACE) << "no cached model found for " << md5 << ", creating new one"; } } SharedModelPtr rc(new ModelResources()); ModelGeneratorContext context(sbml, options); rc->evalInitialConditionsPtr = EvalInitialConditionsCodeGen(context).createFunction(); rc->evalReactionRatesPtr = EvalReactionRatesCodeGen(context).createFunction(); rc->getBoundarySpeciesAmountPtr = GetBoundarySpeciesAmountCodeGen(context).createFunction(); rc->getFloatingSpeciesAmountPtr = GetFloatingSpeciesAmountCodeGen(context).createFunction(); rc->getBoundarySpeciesConcentrationPtr = GetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->getFloatingSpeciesConcentrationPtr = GetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->getCompartmentVolumePtr = GetCompartmentVolumeCodeGen(context).createFunction(); rc->getGlobalParameterPtr = GetGlobalParameterCodeGen(context).createFunction(); rc->evalRateRuleRatesPtr = EvalRateRuleRatesCodeGen(context).createFunction(); rc->getEventTriggerPtr = GetEventTriggerCodeGen(context).createFunction(); rc->getEventPriorityPtr = GetEventPriorityCodeGen(context).createFunction(); rc->getEventDelayPtr = GetEventDelayCodeGen(context).createFunction(); rc->eventTriggerPtr = EventTriggerCodeGen(context).createFunction(); rc->eventAssignPtr = EventAssignCodeGen(context).createFunction(); rc->evalVolatileStoichPtr = EvalVolatileStoichCodeGen(context).createFunction(); rc->evalConversionFactorPtr = EvalConversionFactorCodeGen(context).createFunction(); if (options & LoadSBMLOptions::READ_ONLY) { rc->setBoundarySpeciesAmountPtr = 0; rc->setBoundarySpeciesConcentrationPtr = 0; rc->setFloatingSpeciesConcentrationPtr = 0; rc->setCompartmentVolumePtr = 0; rc->setFloatingSpeciesAmountPtr = 0; rc->setGlobalParameterPtr = 0; } else { rc->setBoundarySpeciesAmountPtr = SetBoundarySpeciesAmountCodeGen( context).createFunction(); rc->setBoundarySpeciesConcentrationPtr = SetBoundarySpeciesConcentrationCodeGen(context).createFunction(); rc->setFloatingSpeciesConcentrationPtr = SetFloatingSpeciesConcentrationCodeGen(context).createFunction(); rc->setCompartmentVolumePtr = SetCompartmentVolumeCodeGen(context).createFunction(); rc->setFloatingSpeciesAmountPtr = SetFloatingSpeciesAmountCodeGen( context).createFunction(); rc->setGlobalParameterPtr = SetGlobalParameterCodeGen(context).createFunction(); } if (options & LoadSBMLOptions::MUTABLE_INITIAL_CONDITIONS) { rc->getFloatingSpeciesInitConcentrationsPtr = GetFloatingSpeciesInitConcentrationCodeGen(context).createFunction(); rc->setFloatingSpeciesInitConcentrationsPtr = SetFloatingSpeciesInitConcentrationCodeGen(context).createFunction(); rc->getFloatingSpeciesInitAmountsPtr = GetFloatingSpeciesInitAmountCodeGen(context).createFunction(); rc->setFloatingSpeciesInitAmountsPtr = SetFloatingSpeciesInitAmountCodeGen(context).createFunction(); rc->getCompartmentInitVolumesPtr = GetCompartmentInitVolumeCodeGen(context).createFunction(); rc->setCompartmentInitVolumesPtr = SetCompartmentInitVolumeCodeGen(context).createFunction(); rc->getGlobalParameterInitValuePtr = GetGlobalParameterInitValueCodeGen(context).createFunction(); rc->setGlobalParameterInitValuePtr = SetGlobalParameterInitValueCodeGen(context).createFunction(); } else { rc->getFloatingSpeciesInitConcentrationsPtr = 0; rc->setFloatingSpeciesInitConcentrationsPtr = 0; rc->getFloatingSpeciesInitAmountsPtr = 0; rc->setFloatingSpeciesInitAmountsPtr = 0; rc->getCompartmentInitVolumesPtr = 0; rc->setCompartmentInitVolumesPtr = 0; rc->getGlobalParameterInitValuePtr = 0; rc->setGlobalParameterInitValuePtr = 0; } // if anything up to this point throws an exception, thats OK, because // we have not allocated any memory yet that is not taken care of by // something else. // Now that everything that could have thrown would have thrown, we // can now create the model and set its fields. LLVMModelData *modelData = createModelData(context.getModelDataSymbols(), context.getRandom()); uint llvmsize = ModelDataIRBuilder::getModelDataSize(context.getModule(), &context.getExecutionEngine()); if (llvmsize != modelData->size) { std::stringstream s; s << "LLVM Model Data size " << llvmsize << " is different from " << "C++ size of LLVM ModelData, " << modelData->size; LLVMModelData_free(modelData); Log(Logger::LOG_FATAL) << s.str(); throw_llvm_exception(s.str()); } // * MOVE * the bits over from the context to the exe model. context.stealThePeach(&rc->symbols, &rc->context, &rc->executionEngine, &rc->random, &rc->errStr); if (!forceReCompile) { // check for a chached copy, another thread could have // created one while we were making ours... ModelPtrMap::const_iterator i; SharedModelPtr sp; cachedModelsMutex.lock(); // whilst we have it locked, clear any expired ptrs for (ModelPtrMap::const_iterator j = cachedModels.begin(); j != cachedModels.end();) { if (j->second.expired()) { Log(Logger::LOG_DEBUG) << "removing expired model resource for hash " << md5; j = cachedModels.erase(j); } else { ++j; } } if ((i = cachedModels.find(md5)) == cachedModels.end()) { Log(Logger::LOG_DEBUG) << "could not find existing cached resource " "resources, for hash " << md5 << ", inserting new resources into cache"; cachedModels[md5] = rc; } cachedModelsMutex.unlock(); } return new LLVMExecutableModel(rc, modelData); }