LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
SharedResource.cc
Go to the documentation of this file.
3 #include "cetlib/container_algorithms.h"
4 #include "cetlib_except/demangle.h"
5 #include "hep_concurrency/SerialTaskQueue.h"
6 #include "range/v3/view.hpp"
7 
8 #include <algorithm>
9 #include <cassert>
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 using namespace hep::concurrency;
16 using namespace std::string_literals;
17 
18 namespace {
19  std::string
20  error_context(std::string const& name)
21  {
22  return "An error occurred while attempting to register the shared resource '"s +
23  name + "'.\n";
24  }
25 }
26 
27 namespace art::detail {
28  SharedResource_t::SharedResource_t(std::string const& resource_name,
29  bool const demangle)
30  : name{demangle ? cet::demangle_symbol(resource_name) : resource_name}
31  {}
32 
34 
35  SharedResource_t const LegacyResource{"__legacy__", false};
36 
38  {
39  // Propulate queues for known shared resources. Creating these
40  // slots does *not* automatically introduce synchronization.
41  // Synchronization is enabled based on the resource-names argument
42  // presented to the 'createQueues' member function.
43  registerSharedResource(LegacyResource);
44  }
45 
46  void
48  {
49  if (frozen_) {
50  throw Exception{errors::LogicError, error_context(name)}
51  << "The shared-resources registry has been frozen. All 'serialize' "
52  "calls\n"
53  << "must be made in the constructor of a shared module and no later.\n";
54  }
55  }
56 
57  void
58  SharedResources::registerSharedResources(std::set<std::string> const& names)
59  {
60  cet::for_all(names, [this](auto const& name) { register_resource(name); });
61  }
62 
63  void
65  {
66  register_resource(resource.name);
67  }
68 
69  void
71  {
72  ensure_not_frozen(name);
73  ++resourceCounts_[name];
74  if (name == LegacyResource.name) {
75  ++nLegacy_;
76  }
77  }
78 
79  void
80  SharedResources::freeze(tbb::task_group& group)
81  {
82  frozen_ = true;
83 
84  std::vector<std::pair<unsigned, std::string>> resources_sorted_by_count;
85  for (auto const& [name, count] : resourceCounts_) {
86  // Make sure all non-legacy resources have a higher count, which
87  // makes legacy always the first queue.
88  auto const offset = (name == LegacyResource.name) ? 0u : nLegacy_;
89  resources_sorted_by_count.emplace_back(count + offset, name);
90  }
91  cet::sort_all(resources_sorted_by_count, [](auto const& a, auto const& b) {
92  return a.first < b.first;
93  });
94 
95  using namespace ::ranges;
96  sortedResources_ =
97  resources_sorted_by_count | views::values |
98  views::transform([&group](auto const& key) {
99  return std::pair{key, std::make_shared<SerialTaskQueue>(group)};
100  }) |
101  to<std::vector>();
102 
103  // Not needed any more now that we have a sorted list of resources.
104  resourceCounts_.clear();
105  }
106 
107  std::vector<std::shared_ptr<SerialTaskQueue>>
109  std::vector<std::string> const& resourceNames) const
110  {
111  using namespace ::ranges;
112  if (cet::search_all(resourceNames, LegacyResource.name)) {
113  // We do not trust legacy modules as they may be accessing one
114  // of the shared resources without our knowledge. We therefore
115  // isolate them from all other shared modules (and each other).
116  return sortedResources_ | views::values | to<std::vector>();
117  }
118  std::vector<std::shared_ptr<SerialTaskQueue>> result;
119  // Not for a legacy module, get the queues for the named resources.
120  for (auto const& name : resourceNames) {
121  auto it =
122  std::find_if(begin(sortedResources_),
123  end(sortedResources_),
124  [&name](auto const& pr) { return pr.first == name; });
125  assert(it != sortedResources_.end());
126  result.push_back(it->second);
127  }
128 
129  assert(not empty(result));
130  return result;
131  }
132 
133 } // namespace art
std::string demangle(T const *=nullptr)
Outputs a demangled name for type T.
Definition: DebugUtils.h:343
void ensure_not_frozen(std::string const &name)
void register_resource(std::string const &name)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
void freeze(tbb::task_group &group)
SharedResource_t const LegacyResource
decltype(auto) values(Coll &&coll)
Range-for loop helper iterating across the values of the specified collection.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void registerSharedResources(std::set< std::string > const &names)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
std::vector< queue_ptr_t > createQueues(std::vector< std::string > const &resourceNames) const
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
void registerSharedResource(detail::SharedResource_t const &)