// toiderivproducer.cc // Eric Aubourg CEA/DAPNIA/SPP septembre 1999 #include "toiderivproducer.h" #include "toimanager.h" #include "archexc.h" #include "requesthandler.h" #include "subsets.h" set TOIDerivProducer::reqTOIFor(TOI const&) { set empty; return empty; } void TOIDerivProducer::outManifest(RequestHandler* h) { outVersion(h); h->processOption("#COMMENT", " Producing:"); for (set::iterator i = producedTOIs.begin(); i != producedTOIs.end(); i++) { h->processOption("#COMMENT", " " + (*i).fullName()); set x = reqTOIFor(*i); if (!x.empty()) { h->processOption("#COMMENT", " from:"); for (set::iterator j=x.begin(); j!=x.end(); j++) { h->processOption("#COMMENT", " " + (*j).fullName()); } } } } bool TOIDerivProducer::canProduce(TOI const& toi) { // 1. Already in cache ? map >::const_iterator j = neededTOIs.find(toi); if (j != neededTOIs.end()) return true; // 2. It should be in our list of possibleTOI's TOI myTOI; for (set::const_iterator i = possibleTOIs.begin(); i != possibleTOIs.end(); i++) { if ((toi.name == (*i).name) && (toi.index == (*i).index || (*i).index == TOI::all)) { myTOI = (*i); break; } } if (myTOI.name == "") return false; // not in list // 3. Handle options set extraopts = toi.options; // 3a should contain mandatory options for (set::iterator i = myTOI.reqOptions.begin(); i != myTOI.reqOptions.end(); i++) { if (extraopts.find(*i) == extraopts.end()) return false; } // 3b remove local options for (set::iterator i = myTOI.options.begin(); i != myTOI.options.end(); i++) { extraopts.erase(*i); } set unusedextra = extraopts; // 4. Find producers, distribute remaining options map fullInputTOI; set inputTOIs = reqTOIFor(toi); for (set::iterator i = inputTOIs.begin(); i != inputTOIs.end(); i++) { TOI inTOI = *i; //TOIProducer* prod0 = TOIManager::findTOIProducer(inTOI); // Let's see if we get others with options, we have to do this because // of required options, and we have to iterate over all subsets of the options. // This algorithm is NOT correct, but should work for realistic cases... int nmaxopt=-1; TOIProducer* prod=NULL; set > optsets = getSetOfSubsets(extraopts); for (set >::iterator j = optsets.begin(); j != optsets.end(); j++) { TOI toi2 = inTOI; toi2.options.insert((*j).begin(), (*j).end()); TOIProducer* prod0 = TOIManager::findTOIProducer(toi2); if (prod0 == NULL) continue; if ((long) toi2.options.size() > nmaxopt) { prod = prod0; nmaxopt = toi2.options.size(); } } if (!prod) return false; if (!extraopts.empty()) { set xopts = prod->getAvailOptions(inTOI); for (set::iterator j = xopts.begin(); j != xopts.end(); j++) { if (extraopts.find(*j) != extraopts.end()) { inTOI.options.insert(*j); unusedextra.erase(*j); } } } fullInputTOI[inTOI] = prod; } if (!unusedextra.empty()) return false; neededTOIs[toi] = fullInputTOI; return true; } set TOIDerivProducer::getAvailOptions(TOI const& toi) { // toi.options.clear(); // toi.index = -2; // if (!canProduce(toi)) throw ArchExc("cannot produce " + toi.name); set s = getProperAvailOptions(toi); map & need = neededTOIs[toi]; for (map::iterator i = need.begin(); i != need.end(); i++) { set s1 = (*i).second->getAvailOptions((*i).first); s.insert(s1.begin(), s1.end()); } return s; } void TOIDerivProducer::addTOI(TOI& toi, TOIAbsorber* client) { TOIProducer::addTOI(toi, client); map & m = neededTOIs[toi]; for (map::iterator i = m.begin(); i != m.end(); i++) { TOI toi2 = (*i).first; (*i).second->addTOI(toi2,this); } } long TOIDerivProducer::wontNeedEarlier(TOI const& toi, TOIAbsorber* client, long t) { long xt = TOIProducer::wontNeedEarlier(toi, client, t); if (xt>0) propagateLowBound(toi, xt); return xt; } // if no need for past values... void TOIDerivProducer::propagateLowBound(TOI const& toi, long sampleNum) { CHKPROD map & need = neededTOIs[toi]; for (map::iterator i = need.begin(); i != need.end(); i++) { (*i).second->wontNeedEarlier((*i).first, this, sampleNum); } }