|
||||
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_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |