LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ServicesManager.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // ServicesManager
4 //
5 // ======================================================================
6 
10 #include "cetlib/LibraryManager.h"
11 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <cassert>
15 #include <memory>
16 #include <utility>
17 
19  cet::LibraryManager const& lm,
20  ActivityRegistry& reg)
21  : registry_{reg}
22 {
23  fillCache_(psets, lm);
24 }
25 
27 {
28  // Force the Service destructors to execute in the reverse order of
29  // construction. Note that services passed in by a token are not
30  // included in this loop and do not get destroyed until the
31  // ServicesManager object that created them is destroyed which
32  // occurs after the body of this destructor is executed (the correct
33  // order). Services directly passed in by a put and not created in
34  // the constructor may or may not be detroyed in the desired order
35  // because this class does not control their creation (as I'm
36  // writing this comment everything in a standard fw executable is
37  // destroyed in the desired order).
38  index_.clear();
39  factory_.clear();
40  while (!actualCreationOrder_.empty()) {
42  }
43 }
44 
45 void
47 {
48  for (auto const& val : requestedCreationOrder_) {
49  auto c = factory_.find(val);
50  if (c != factory_.end()) {
51  c->second.forceCreation(registry_);
52  }
53  // JBK - should an exception be thrown if name not found in map?
54  }
55 }
56 
57 void
59  ProductDescriptions& productsToProduce,
60  ProducingServiceSignals& signals,
61  ProcessConfiguration const& pc)
62 {
63  for (auto& pr : factory_) {
64  auto& serviceEntry = pr.second;
65 
66  // Per-schedule services cannot register products
67  if (serviceEntry.serviceScope() == ServiceScope::PER_SCHEDULE)
68  continue;
69 
70  // Service interfaces cannot be used for product insertion.
71  if (serviceEntry.is_interface())
72  continue;
73 
74  // The value of service_type becomes the "module name/label" for
75  // the ModuleDescription object.
76  auto const& pset = serviceEntry.getParameterSet();
77  std::string moduleLabel{};
78  if (!pset.get_if_present("service_type", moduleLabel)) {
79  // System services do not insert products.
80  continue;
81  }
82 
83  ModuleDescription const md{pset.id(), moduleLabel, moduleLabel, pc};
84  serviceEntry.registerProducts(mpr, productsToProduce, signals, md);
85  }
86 }
87 
88 void
90 {
92  for (auto const& cur : factory_) {
93  tmp.push_back(cur.second.getParameterSet());
94  }
95  tmp.swap(out);
96 }
97 
98 void
100  cet::LibraryManager const& lm)
101 {
102  // Receive from EventProcessor when we go multi-schedule.
104  // Loop over each configured service parameter set.
105  for (auto const& ps : psets) {
106  std::string const service_name{ps.get<std::string>("service_type")};
107  std::string const service_provider{
108  ps.get<std::string>("service_provider", service_name)};
109  // Get the helper from the library.
110  std::unique_ptr<detail::ServiceHelperBase> service_helper{
111  lm.getSymbolByLibspec<SHBCREATOR_t>(service_provider,
112  "create_service_helper")()};
113  if (service_helper->is_interface()) {
115  << "Service " << service_name << " (of type "
116  << service_helper->get_typeid().className()
117  << ")\nhas been registered as an interface in its header using\n"
118  << "DECLARE_ART_SERVICE_INTERFACE.\n"
119  << "Use DECLARE_ART_SERVICE OR DECLARE_ART_SERVICE_INTERFACE_IMPL\n"
120  << "as appropriate. A true service interface should *not* be\n"
121  << "compiled into a _service.so plugin library.\n";
122  }
123  std::unique_ptr<detail::ServiceInterfaceHelper> iface_helper;
124  if (service_helper->is_interface_impl()) { // Expect an interface helper
125  iface_helper.reset(dynamic_cast<detail::ServiceInterfaceHelper*>(
126  lm.getSymbolByLibspec<SHBCREATOR_t>(service_provider,
127  "create_iface_helper")()
128  .release()));
129  if (dynamic_cast<detail::ServiceInterfaceImplHelper*>(
130  service_helper.get())
131  ->get_interface_typeid() != iface_helper->get_typeid()) {
133  << "Service registration for " << service_provider
134  << " is internally inconsistent: " << iface_helper->get_typeid()
135  << " (" << iface_helper->get_typeid().className() << ") != "
136  << dynamic_cast<detail::ServiceInterfaceImplHelper*>(
137  service_helper.get())
138  ->get_interface_typeid()
139  << " ("
140  << dynamic_cast<detail::ServiceInterfaceImplHelper*>(
141  service_helper.get())
142  ->get_interface_typeid()
143  .className()
144  << ").\n"
145  << "Contact the art developers <artists@fnal.gov>.\n";
146  }
147  if (service_provider == service_name) {
148  std::string iface_name{
149  cet::demangle_symbol(iface_helper->get_typeid().name())};
150  // Remove any namespace qualification if necessary
151  auto const colon_pos = iface_name.find_last_of(":");
152  if (colon_pos != std::string::npos) {
153  iface_name.erase(0, colon_pos + 1);
154  }
156  << "Illegal use of service interface implementation as service name "
157  "in configuration.\n"
158  << "Correct use: services." << iface_name
159  << ": { service_provider: \"" << service_provider << "\" }\n";
160  }
161  }
162  // Insert the cache entry for the main service implementation. Note
163  // we save the typeid of the implementation because we're about to
164  // give away the helper.
165  TypeID service_typeid{service_helper->get_typeid()};
166  auto svc = insertImpl_(ps, std::move(service_helper));
167  if (iface_helper) {
168  insertInterface_(ps, std::move(iface_helper), svc.first);
169  }
170  index_[service_name] = svc.first;
171  requestedCreationOrder_.emplace_back(std::move(service_typeid));
172  }
173 } // fillCache()
174 
175 std::pair<art::detail::ServiceCache::iterator, bool>
177  fhicl::ParameterSet const& pset,
178  std::unique_ptr<detail::ServiceHelperBase>&& helper)
179 {
180  // Need temporary because we can't guarantee the order of evaluation
181  // of the arguments to emplace below.
182  TypeID const sType{helper->get_typeid()};
183  return factory_.emplace(sType,
184  detail::ServiceCacheEntry(pset, std::move(helper)));
185 }
186 
187 void
189  fhicl::ParameterSet const& pset,
190  std::unique_ptr<detail::ServiceHelperBase>&& helper,
191  detail::ServiceCache::iterator const implEntry)
192 {
193  // Need temporary because we can't guarantee the order of evaluation
194  // of the arguments to emplace below.
195  TypeID const iType{helper->get_typeid()};
196  factory_.emplace(
197  iType,
198  detail::ServiceCacheEntry(pset, std::move(helper), implEntry->second));
199 }
200 // ======================================================================
std::vector< fhicl::ParameterSet > ParameterSets
intermediate_table::iterator iterator
void registerProducts(MasterProductRegistry &mpr, ProductDescriptions &productsToProduce, ProducingServiceSignals &signals, ProcessConfiguration const &pc)
Float_t tmp
Definition: plot.C:37
std::vector< BranchDescription > ProductDescriptions
detail::ServiceStack actualCreationOrder_
void getParameterSets(ParameterSets &out) const
ModuleDescriptionID id() const
std::unique_ptr< detail::ServiceHelperBase >(*)( SHBCREATOR_t)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::pair< detail::ServiceCache::iterator, bool > insertImpl_(fhicl::ParameterSet const &pset, std::unique_ptr< detail::ServiceHelperBase > &&helper)
detail::ServiceCache factory_
void insertInterface_(fhicl::ParameterSet const &pset, std::unique_ptr< detail::ServiceHelperBase > &&helper, detail::ServiceCache::iterator implEntry)
ServicesManager(ServicesManager const &)=delete
void fillCache_(ParameterSets const &psets, cet::LibraryManager const &lm)
art::ActivityRegistry & registry_
static void setNSchedules(size_t nSched)