MakerHolder

ServicesManager

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#ifndef ServiceRegistry_ServicesManager_h
#define ServiceRegistry_ServicesManager_h
// -*- C++ -*-
//
// Package:     ServiceRegistry
// Class  :     ServicesManager
//
/**\class ServicesManager ServicesManager.h FWCore/ServiceRegistry/interface/ServicesManager.h

 Description: <one line class summary>

 Usage:
    <usage>

*/
//
// Original Author:  Chris Jones
//         Created:  Mon Sep  5 13:33:01 EDT 2005
//

// user include files
#include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
#include "FWCore/ServiceRegistry/interface/ServiceLegacy.h"
#include "FWCore/ServiceRegistry/interface/ServiceMakerBase.h"
#include "FWCore/ServiceRegistry/interface/ServiceWrapper.h"
#include "FWCore/Utilities/interface/EDMException.h"
#include "FWCore/Utilities/interface/TypeDemangler.h"
#include "FWCore/Utilities/interface/TypeIDBase.h"
#include "FWCore/Utilities/interface/propagate_const.h"
#include "FWCore/Utilities/interface/thread_safety_macros.h"

// system include files
#include <memory>

#include <cassert>
#include <vector>

// forward declarations
namespace edm {
  class ParameterSet;
  class ServiceToken;

  namespace serviceregistry {

    class ServicesManager {
    public:
      struct MakerHolder {
        MakerHolder(std::shared_ptr<ServiceMakerBase> iMaker, ParameterSet& iPSet, ActivityRegistry&);
        bool add(ServicesManager&) const;

        edm::propagate_const<std::shared_ptr<ServiceMakerBase>> maker_;
        ParameterSet* pset_;
        ActivityRegistry* registry_;  // We do not use propagate_const because the registry itself is mutable
        //Services construction is not allowed to occur across threads
        CMS_SA_ALLOW mutable bool wasAdded_;
      };
      typedef std::map<TypeIDBase, std::shared_ptr<ServiceWrapperBase>> Type2Service;
      typedef std::map<TypeIDBase, MakerHolder> Type2Maker;

      ServicesManager(std::vector<ParameterSet>& iConfiguration);

      /** Takes the services described by iToken and places them into the manager.
             Conflicts over Services provided by both the iToken and iConfiguration
             are resolved based on the value of iLegacy
         */
      ServicesManager(ServiceToken iToken,
                      ServiceLegacy iLegacy,
                      std::vector<ParameterSet>& iConfiguration,
                      bool associate = true);

      ServicesManager(ServicesManager const&) = delete;                   // stop default
      ServicesManager const& operator=(ServicesManager const&) = delete;  // stop default
      ~ServicesManager();

      // ---------- const member functions ---------------------
      template <typename T>
      T& get() const {
        Type2Service::const_iterator itFound = type2Service_.find(TypeIDBase(typeid(T)));
        Type2Maker::const_iterator itFoundMaker;
        if (itFound == type2Service_.end()) {
          //do on demand building of the service
          if (nullptr == type2Maker_.get() ||
              type2Maker_->end() == (itFoundMaker = type2Maker_->find(TypeIDBase(typeid(T))))) {
            auto demangled = typeDemangle(typeid(T).name());
            Exception::throwThis(errors::NotFound,
                                 "Service Request unable to find requested service with C++ type '",
                                 demangled.c_str(),
                                 "'.\n");
          } else {
            const_cast<ServicesManager&>(*this).createServiceFor(itFoundMaker->second);
            itFound = type2Service_.find(TypeIDBase(typeid(T)));
            //the 'add()' should have put the service into the list
            assert(itFound != type2Service_.end());
          }
        }
        //convert it to its actual type
        std::shared_ptr<ServiceWrapper<T>> ptr(std::dynamic_pointer_cast<ServiceWrapper<T>>(itFound->second));
        assert(nullptr != ptr.get());
        return ptr->get();
      }

      ///returns true of the particular service is accessible
      template <typename T>
      bool isAvailable() const {
        Type2Service::const_iterator itFound = type2Service_.find(TypeIDBase(typeid(T)));
        Type2Maker::const_iterator itFoundMaker;
        if (itFound == type2Service_.end()) {
          //do on demand building of the service
          if (nullptr == type2Maker_.get() ||
              type2Maker_->end() == (itFoundMaker = type2Maker_->find(TypeIDBase(typeid(T))))) {
            return false;
          } else {
            //Actually create the service in order to 'flush out' any
            // configuration errors for the service
            const_cast<ServicesManager&>(*this).createServiceFor(itFoundMaker->second);
            itFound = type2Service_.find(TypeIDBase(typeid(T)));
            //the 'add()' should have put the service into the list
            assert(itFound != type2Service_.end());
          }
        }
        return true;
      }

      // ---------- static member functions --------------------

      // ---------- member functions ---------------------------
      ///returns false if put fails because a service of this type already exists
      template <typename T>
      bool put(std::shared_ptr<ServiceWrapper<T>> iPtr, bool iOverride = false) {
        Type2Service::const_iterator itFound = type2Service_.find(TypeIDBase(typeid(T)));
        if (itFound != type2Service_.end() and not iOverride) {
          return false;
        }
        type2Service_[TypeIDBase(typeid(T))] = iPtr;
        actualCreationOrder_.push_back(TypeIDBase(typeid(T)));
        return true;
      }

      ///causes our ActivityRegistry's signals to be forwarded to iOther
      void connect(ActivityRegistry& iOther);

      ///causes iOther's signals to be forward to us
      void connectTo(ActivityRegistry& iOther);

      ///copy our Service's slots to the argument's signals
      void copySlotsTo(ActivityRegistry&);
      ///the copy the argument's slots to the our signals
      void copySlotsFrom(ActivityRegistry&);

    private:
      void fillListOfMakers(std::vector<ParameterSet>&);
      void createServices();
      void createServiceFor(MakerHolder const&);

      // ---------- member data --------------------------------
      //hold onto the Manager passed in from the ServiceToken so that
      // the ActivityRegistry of that Manager does not go out of scope
      // This must be first to get the Service destructors called in
      // the correct order.
      edm::propagate_const<std::shared_ptr<ServicesManager>> associatedManager_;

      ActivityRegistry registry_;
      Type2Service type2Service_;
      edm::propagate_const<std::unique_ptr<Type2Maker>> type2Maker_;
      std::vector<TypeIDBase> requestedCreationOrder_;
      std::vector<TypeIDBase> actualCreationOrder_;
    };
  }  // namespace serviceregistry
}  // namespace edm

#endif