Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/JANA/Services/JServiceLocator.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #ifndef _JSERVICELOCATOR_H_
0007 #define _JSERVICELOCATOR_H_
0008 
0009 
0010 #include <map>
0011 #include <typeinfo>
0012 #include <typeindex>
0013 #include <assert.h>
0014 #include <memory>
0015 #include <mutex>
0016 
0017 #include <JANA/JException.h>
0018 #include "JANA/Utils/JTypeInfo.h"
0019 #include <JANA/JServiceFwd.h>
0020 
0021 
0022 
0023 /// JService is a trait indicating that an object can be shared among JANA components
0024 /// via a simple ServiceLocator. It provides a callback interface for configuring itself
0025 /// when it depends on other JServices.
0026 
0027 /// JServiceLocator is a nexus for collecting, initializing, and retrieving JServices.
0028 /// This may be exposed via the JApplication facade, or used on its own. JServiceLocator
0029 /// uses shared-pointer semantics to ensure that JServices always get freed,
0030 /// but also don't get freed prematurely if a JApplication or JServiceLocator go out of scope.
0031 class JServiceLocator {
0032 
0033     std::map<std::type_index, std::shared_ptr<JService>> underlying;
0034     std::mutex mutex;
0035 
0036 public:
0037 
0038 
0039     template<typename T>
0040     void provide(std::shared_ptr<T> t) {
0041 
0042         /// Publish a Service to the ServiceLocator. This Service should have
0043         /// already been constructed, but not finalized.
0044         /// Users are intended to call this from InitPlugin() most of the time
0045 
0046         std::lock_guard<std::mutex> lock(mutex);
0047         auto svc = std::dynamic_pointer_cast<JService>(t);
0048         assert(svc != nullptr);
0049         underlying[std::type_index(typeid(T))] = svc;
0050     }
0051 
0052     template<typename T>
0053     std::shared_ptr<T> get() {
0054         /// Retrieve a JService. If acquire_services() has not yet been called, it will be.
0055         /// Usually called from Service::finalize(). It may be called from anywhere,
0056         /// but it is generally safer to retrieve the services we need during acquire_dependencies()
0057         /// and keep pointers to those, instead of keeping a pointer to the ServiceLocator itself.
0058         /// (This also makes it easier to migrate to dependency injection if we so desire)
0059 
0060         auto iter = underlying.find(std::type_index(typeid(T)));
0061         if (iter == underlying.end()) {
0062             std::ostringstream oss;
0063             oss << "Service not found: '" << JTypeInfo::demangle<T>() << "'. Did you forget to include a plugin?" << std::endl;
0064             throw JException(oss.str());
0065         }
0066         auto svc = iter->second;
0067         svc->DoInit(this); 
0068         // Will short-circuit if already initialized
0069         // Note: Requires JApplication to already be set.
0070 
0071         auto svc_typed = std::static_pointer_cast<T>(svc);
0072         return svc_typed;
0073     }
0074 
0075     void wire_everything() {
0076         /// Make sure that all Services have been finalized. This is not strictly necessary,
0077         /// but it makes user errors easier to understand, and it prevents Services from being
0078         /// unpredictably finalized later on, particularly during computation.
0079 
0080         for (auto& entry : underlying) {
0081             entry.second->DoInit(this); 
0082         }
0083     }
0084 };
0085 
0086 #endif // _JSERVICELOCATOR_H_