Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:47:02

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWCore/Framework
0004 // Class  :     SharedResourcesRegistry
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Sun, 06 Oct 2013 15:48:50 GMT
0011 //
0012 
0013 // system include files
0014 #include <algorithm>
0015 #include <cassert>
0016 
0017 // user include files
0018 #include "FWCore/Framework/interface/SharedResourcesRegistry.h"
0019 #include "FWCore/Framework/interface/SharedResourcesAcquirer.h"
0020 
0021 namespace edm {
0022 
0023   const std::string SharedResourcesRegistry::kLegacyModuleResourceName{"__legacy__"};
0024 
0025   SharedResourcesRegistry* SharedResourcesRegistry::instance() {
0026     static SharedResourcesRegistry s_instance;
0027     return &s_instance;
0028   }
0029 
0030   SharedResourcesRegistry::SharedResourcesRegistry() : nLegacy_(0) {}
0031 
0032   void SharedResourcesRegistry::registerSharedResource(const std::string& resourceName) {
0033     auto& queueAndCounter = resourceMap_[resourceName];
0034 
0035     if (resourceName == kLegacyModuleResourceName) {
0036       ++nLegacy_;
0037       for (auto& resource : resourceMap_) {
0038         if (!resource.second.first) {
0039           resource.second.first = std::make_shared<SerialTaskQueue>();
0040         }
0041         ++resource.second.second;
0042       }
0043     } else {
0044       // count the number of times the resource was registered
0045       ++queueAndCounter.second;
0046 
0047       // When first registering a nonlegacy resource, we have to
0048       // account for any legacy resource registrations already made.
0049       if (queueAndCounter.second == 1) {
0050         if (nLegacy_ > 0U) {
0051           queueAndCounter.first = std::make_shared<SerialTaskQueue>();
0052           queueAndCounter.second += nLegacy_;
0053         }
0054         // If registering a nonlegacy resource the second time and
0055         // the legacy resource has not been registered yet,
0056         // we know we will need the queue so go ahead and create it.
0057       } else if (queueAndCounter.second == 2) {
0058         queueAndCounter.first = std::make_shared<SerialTaskQueue>();
0059       }
0060     }
0061   }
0062 
0063   std::pair<SharedResourcesAcquirer, std::shared_ptr<std::recursive_mutex>>
0064   SharedResourcesRegistry::createAcquirerForSourceDelayedReader() {
0065     if (not resourceForDelayedReader_) {
0066       resourceForDelayedReader_ =
0067           std::make_shared<std::recursive_mutex>();  // propagate_const<T> has no reset() function
0068       queueForDelayedReader_ = std::make_shared<SerialTaskQueue>();
0069     }
0070 
0071     std::vector<std::shared_ptr<SerialTaskQueue>> queues = {get_underlying(queueForDelayedReader_)};
0072     return std::make_pair(SharedResourcesAcquirer(std::move(queues)), get_underlying(resourceForDelayedReader_));
0073   }
0074 
0075   SharedResourcesAcquirer SharedResourcesRegistry::createAcquirer(std::vector<std::string> const& resourceNames) const {
0076     // The acquirer will acquire the shared resources declared by a module
0077     // so that only it can use those resources while it runs. The other
0078     // modules using the same resource will not be run until the module
0079     // that acquired the resources completes its task.
0080 
0081     // The legacy shared resource is special.
0082     // Legacy modules cannot run concurrently with each other or
0083     // any other module that has declared any shared resource. Treat
0084     // one modules that call usesResource with no argument in the
0085     // same way.
0086 
0087     // Sort by how often used and then by name
0088     // Consistent sorting avoids deadlocks and this particular order optimizes performance
0089     std::map<std::pair<unsigned int, std::string>, std::shared_ptr<SerialTaskQueue>> sortedResources;
0090 
0091     // Is this acquirer for a module that depends on the legacy shared resource?
0092     if (std::find(resourceNames.begin(), resourceNames.end(), kLegacyModuleResourceName) != resourceNames.end()) {
0093       for (auto const& resource : resourceMap_) {
0094         // It's redundant to declare legacy if the legacy modules
0095         // all declare all the other resources, so just skip it.
0096         // But if the only shared resource is the legacy resource don't skip it.
0097         if (resource.first == kLegacyModuleResourceName && resourceMap_.size() > 1)
0098           continue;
0099         //legacy modules are not allowed to depend on ES shared resources
0100         if (resource.first.substr(0, 3) == "es_")
0101           continue;
0102         //If only one module wants it, it really isn't shared
0103         if (resource.second.second > 1) {
0104           sortedResources.insert(
0105               std::make_pair(std::make_pair(resource.second.second, resource.first), resource.second.first));
0106         }
0107       }
0108       // Handle cases where the module does not declare the legacy resource
0109     } else {
0110       for (auto const& name : resourceNames) {
0111         auto resource = resourceMap_.find(name);
0112         assert(resource != resourceMap_.end());
0113         //If only one module wants it, it really isn't shared
0114         if (resource->second.second > 1) {
0115           sortedResources.insert(
0116               std::make_pair(std::make_pair(resource->second.second, resource->first), resource->second.first));
0117         }
0118       }
0119     }
0120 
0121     std::vector<std::shared_ptr<SerialTaskQueue>> queues;
0122     queues.reserve(sortedResources.size());
0123     for (auto const& resource : sortedResources) {
0124       queues.push_back(resource.second);
0125     }
0126     if (queues.empty()) {
0127       //Calling code is depending on there being at least one shared queue
0128       queues.reserve(1);
0129       queues.push_back(std::make_shared<SerialTaskQueue>());
0130     }
0131 
0132     return SharedResourcesAcquirer(std::move(queues));
0133   }
0134 }  // namespace edm