|
||||
File indexing completed on 2025-01-18 10:17:35
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 svc->SetTypeName(JTypeInfo::demangle<T>()); 0050 underlying[std::type_index(typeid(T))] = svc; 0051 } 0052 0053 template<typename T> 0054 std::shared_ptr<T> get() { 0055 /// Retrieve a JService. If acquire_services() has not yet been called, it will be. 0056 /// Usually called from Service::finalize(). It may be called from anywhere, 0057 /// but it is generally safer to retrieve the services we need during acquire_dependencies() 0058 /// and keep pointers to those, instead of keeping a pointer to the ServiceLocator itself. 0059 /// (This also makes it easier to migrate to dependency injection if we so desire) 0060 0061 auto iter = underlying.find(std::type_index(typeid(T))); 0062 if (iter == underlying.end()) { 0063 std::ostringstream oss; 0064 oss << "Service not found: '" << JTypeInfo::demangle<T>() << "'. Did you forget to include a plugin?" << std::endl; 0065 throw JException(oss.str()); 0066 } 0067 auto svc = iter->second; 0068 svc->DoInit(this); 0069 // Will short-circuit if already initialized 0070 // Note: Requires JApplication to already be set. 0071 0072 auto svc_typed = std::static_pointer_cast<T>(svc); 0073 return svc_typed; 0074 } 0075 0076 void wire_everything() { 0077 /// Make sure that all Services have been finalized. This is not strictly necessary, 0078 /// but it makes user errors easier to understand, and it prevents Services from being 0079 /// unpredictably finalized later on, particularly during computation. 0080 0081 for (auto& entry : underlying) { 0082 entry.second->DoInit(this); 0083 } 0084 } 0085 }; 0086 0087 #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 |