CMS 3D CMS Logo

ServicesManager.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     ServiceRegistry
00004 // Class  :     ServicesManager
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Mon Sep  5 13:33:19 EDT 2005
00011 // $Id: ServicesManager.cc,v 1.10 2007/02/14 20:45:12 wdd Exp $
00012 //
00013 
00014 // system include files
00015 #include <set>
00016 
00017 // user include files
00018 #include "FWCore/ServiceRegistry/interface/ServicesManager.h"
00019 #include "FWCore/ServiceRegistry/interface/ServicePluginFactory.h"
00020 #include "FWCore/ServiceRegistry/interface/ServiceToken.h"
00021 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
00022 
00023 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00024 
00025 using namespace edm::serviceregistry;
00026 //
00027 // constants, enums and typedefs
00028 //
00029 
00030 ServicesManager::MakerHolder::MakerHolder(boost::shared_ptr<ServiceMakerBase> iMaker,
00031                                           const edm::ParameterSet& iPSet,
00032                                           edm::ActivityRegistry& iRegistry) :
00033 maker_(iMaker),
00034 pset_(&iPSet),
00035 registry_(&iRegistry),
00036 wasAdded_(false)
00037 {}
00038 
00039 bool 
00040 ServicesManager::MakerHolder::add(ServicesManager& oManager) const
00041 {
00042    if(!wasAdded_) {
00043       return wasAdded_ = maker_->make(*pset_, *registry_, oManager);
00044    }
00045    return wasAdded_;
00046 }
00047 
00048 //
00049 // static data member definitions
00050 //
00051 
00052 //
00053 // constructors and destructor
00054 //
00055 ServicesManager::ServicesManager(const std::vector<edm::ParameterSet>& iConfiguration) :
00056 type2Maker_(new Type2Maker)
00057 {
00058    //First create the list of makers
00059    fillListOfMakers(iConfiguration);
00060    
00061    createServices();
00062 }
00063 ServicesManager::ServicesManager(ServiceToken iToken,
00064                                  ServiceLegacy iLegacy,
00065                                  const std::vector<edm::ParameterSet>& iConfiguration):
00066   associatedManager_(iToken.manager_),
00067   type2Maker_(new Type2Maker)
00068 {
00069    fillListOfMakers(iConfiguration);
00070 
00071    //find overlaps between services in iToken and iConfiguration
00072    typedef std::set< TypeIDBase> TypeSet;
00073    TypeSet configTypes;
00074    for(Type2Maker::iterator itType = type2Maker_->begin(), itTypeEnd = type2Maker_->end();
00075        itType != itTypeEnd;
00076        ++itType) {
00077       configTypes.insert(itType->first);
00078    }
00079 
00080    TypeSet tokenTypes;
00081    if(0 != associatedManager_.get()) {
00082       for(Type2Service::iterator itType = associatedManager_->type2Service_.begin(),
00083           itTypeEnd = associatedManager_->type2Service_.end();
00084           itType != itTypeEnd;
00085           ++itType) {
00086          tokenTypes.insert(itType->first);
00087       }
00088    
00089       typedef std::set<TypeIDBase> IntersectionType;
00090       IntersectionType intersection;
00091       std::set_intersection(configTypes.begin(), configTypes.end(),
00092                             tokenTypes.begin(), tokenTypes.end(),
00093                             inserter(intersection, intersection.end()));
00094       
00095       switch(iLegacy) {
00096          case kOverlapIsError :
00097             if(!intersection.empty()) {
00098                throw edm::Exception(errors::Configuration, "Service")
00099                <<"the Service "<<(*type2Maker_).find(*(intersection.begin()))->second.pset_->getParameter<std::string>("@service_type")
00100                <<" already has an instance of that type of Service";
00101             } else {
00102                //get all the services from Token
00103                type2Service_ = associatedManager_->type2Service_;
00104             }
00105             break;
00106          case kTokenOverrides :
00107             //get all the services from Token
00108             type2Service_ = associatedManager_->type2Service_;
00109             
00110             //remove from type2Maker the overlapping services so we never try to make them
00111             for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
00112                 itType != itTypeEnd;
00113                 ++itType) {
00114                type2Maker_->erase(type2Maker_->find(*itType)); 
00115             }
00116             break;
00117          case kConfigurationOverrides:
00118             //get all the services from Token
00119             type2Service_ = associatedManager_->type2Service_;
00120             
00121             //now remove the ones we do not want
00122             for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
00123                 itType != itTypeEnd;
00124                 ++itType) {
00125                type2Service_.erase(type2Service_.find(*itType)); 
00126             }
00127             break;
00128       }
00129       //make sure our signals are propagated to our 'inherited' Services
00130       registry_.copySlotsFrom(associatedManager_->registry_); 
00131    }
00132    createServices();
00133 }
00134 
00135 // ServicesManager::ServicesManager(const ServicesManager& rhs)
00136 // {
00137 //    // do actual copying here;
00138 // }
00139 
00140 ServicesManager::~ServicesManager()
00141 {
00142    // Force the Service destructors to execute in the reverse order of construction.
00143    // Note that services passed in by a token are not included in this loop and
00144    // do not get destroyed until the ServicesManager object that created them is destroyed
00145    // which occurs after the body of this destructor is executed (the correct order).
00146    // Services directly passed in by a put and not created in the constructor
00147    // may or not be detroyed in the desired order because this class does not control
00148    // their creation (as I'm writing this comment everything in a standard cmsRun
00149    // executable is destroyed in the desired order).
00150    for (std::vector<TypeIDBase>::const_reverse_iterator idIter = actualCreationOrder_.rbegin(),
00151                                                          idEnd = actualCreationOrder_.rend();
00152         idIter != idEnd;
00153         ++idIter) {
00154 
00155       Type2Service::iterator itService = type2Service_.find(*idIter);
00156 
00157       if (itService != type2Service_.end()) {
00158 
00159          // This will cause the Service's destruction if
00160          // there are no other shared pointers around
00161          itService->second.reset();
00162       }
00163    }
00164 }
00165 
00166 //
00167 // assignment operators
00168 //
00169 // const ServicesManager& ServicesManager::operator=(const ServicesManager& rhs)
00170 // {
00171 //   //An exception safe implementation is
00172 //   ServicesManager temp(rhs);
00173 //   swap(rhs);
00174 //
00175 //   return *this;
00176 // }
00177 
00178 //
00179 // member functions
00180 //
00181 void 
00182 ServicesManager::connect(ActivityRegistry& iOther)
00183 {
00184    registry_.connect(iOther);
00185 }   
00186 
00187 void 
00188 ServicesManager::connectTo(ActivityRegistry& iOther)
00189 {
00190    iOther.connect(registry_);
00191 }
00192 
00193 void 
00194 ServicesManager::copySlotsFrom(ActivityRegistry& iOther)
00195 {
00196   registry_.copySlotsFrom(iOther);
00197 }   
00198 
00199 void 
00200 ServicesManager::copySlotsTo(ActivityRegistry& iOther)
00201 {
00202   iOther.copySlotsFrom(registry_);
00203 }
00204 
00205 
00206 void
00207 ServicesManager::fillListOfMakers(const std::vector<edm::ParameterSet>& iConfiguration)
00208 {
00209    for(std::vector<edm::ParameterSet>::const_iterator itParam = iConfiguration.begin(),
00210         itParamEnd = iConfiguration.end();
00211         itParam != itParamEnd;
00212         ++itParam) {
00213       boost::shared_ptr<ServiceMakerBase> base(
00214                                                ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
00215 
00216       if(0 == base.get()) {
00217          throw edm::Exception(edm::errors::Configuration, "Service")
00218          <<"could not find a service named "
00219          << itParam->getParameter<std::string>("@service_type")
00220          <<". Please check spelling.";
00221       }
00222       Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
00223       if(itFound != type2Maker_->end()) {
00224          throw edm::Exception(edm::errors::Configuration,"Service") 
00225          <<" the service "<< itParam->getParameter<std::string>("@service_type") 
00226          <<" provides the same service as "
00227          << itFound->second.pset_->getParameter<std::string>("@service_type")
00228          <<"\n Please reconfigure job to only use one of these services.";
00229       }
00230       type2Maker_->insert(Type2Maker::value_type(TypeIDBase(base->serviceType()),
00231                                                   MakerHolder(base,
00232                                                               *itParam,
00233                                                               registry_)));
00234       requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
00235    }
00236    
00237 }
00238 
00239 namespace {
00240    struct NoOp {
00241       void operator()(ServicesManager*) {}
00242    };
00243 }
00244 
00245 void
00246 ServicesManager::createServices()
00247 {
00248    
00249 
00250    //create a shared_ptr of 'this' that will not delete us
00251    boost::shared_ptr<ServicesManager> shareThis(this, NoOp());
00252    
00253    ServiceToken token(shareThis);
00254    
00255    //Now make our services to ones obtained via ServiceRegistry
00256    // when this goes out of scope, it will revert back to the previous Service set
00257    ServiceRegistry::Operate operate(token);
00258    
00259    //Now, make each Service.  If a service depends on a service that has yet to be
00260    // created, that other service will automatically be made
00261    
00262    for (std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
00263                                                  idEnd = requestedCreationOrder_.end();
00264         idIter != idEnd;
00265         ++idIter) {
00266      Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
00267 
00268      // Check to make sure this maker is still there.  They are deleted
00269      // sometimes and that is OK.
00270      if (itMaker != type2Maker_->end()) {
00271        try {
00272          // This creates the service
00273          itMaker->second.add(*this);
00274        }
00275        catch(cms::Exception& iException) {
00276          edm::Exception toThrow(edm::errors::Configuration,"Error occured while creating ");
00277          toThrow<<itMaker->second.pset_->getParameter<std::string>("@service_type")<<"\n";
00278          toThrow.append(iException);
00279          throw toThrow;
00280        }
00281      }
00282    }
00283    
00284    //No longer need the makers
00285    type2Maker_.reset();
00286    
00287 }   
00288 //
00289 // const member functions
00290 //
00291 
00292 //
00293 // static member functions
00294 //

Generated on Tue Jun 9 17:36:39 2009 for CMSSW by  doxygen 1.5.4