Line data Source code
1 : #pragma once 2 : 3 : #include <functional> 4 : #include <memory> 5 : #include <string> 6 : 7 : #include "envoy/common/pure.h" 8 : #include "envoy/config/typed_config.h" 9 : #include "envoy/registry/registry.h" 10 : #include "envoy/singleton/instance.h" 11 : 12 : namespace Envoy { 13 : namespace Singleton { 14 : 15 : /** 16 : * An abstract registration for a singleton entry. 17 : */ 18 : class Registration : public Config::UntypedFactory { 19 : public: 20 0 : std::string category() const override { return "envoy.singleton"; } 21 : }; 22 : 23 : /** 24 : * A concrete implementation of a singleton registration. All singletons are referenced by name 25 : * and must be statically registered ahead of time. This can be done like so: 26 : * 27 : * static constexpr char foo_singleton_name[] = "foo_singleton"; 28 : * static Registry::RegisterFactory<Singleton::RegistrationImpl<foo_singleton_name>, 29 : * Singleton::Registration> 30 : * date_provider_singleton_registered_; 31 : * 32 : * Once this is done, the singleton can be get/set via the manager. See the Manager interface 33 : * for more information. 34 : */ 35 : template <const char* name_param> class RegistrationImpl : public Registration { 36 : public: 37 517 : std::string name() const override { return name_param; } 38 : }; 39 : 40 : /** 41 : * Macro used to statically register singletons managed by the singleton manager 42 : * defined in envoy/singleton/manager.h. After the NAME has been registered use the 43 : * SINGLETON_MANAGER_REGISTERED_NAME macro to access the name registered with the 44 : * singleton manager. 45 : */ 46 : #define SINGLETON_MANAGER_REGISTRATION(NAME) \ 47 : static constexpr char NAME##_singleton_name[] = #NAME "_singleton"; \ 48 : static Envoy::Registry::RegisterInternalFactory< \ 49 : Envoy::Singleton::RegistrationImpl<NAME##_singleton_name>, Envoy::Singleton::Registration> \ 50 : NAME##_singleton_registered_; 51 : 52 1319 : #define SINGLETON_MANAGER_REGISTERED_NAME(NAME) NAME##_singleton_name 53 : 54 : /** 55 : * Callback function used to create a singleton. 56 : */ 57 : using SingletonFactoryCb = std::function<InstanceSharedPtr()>; 58 : 59 : /** 60 : * A manager for all server-side singletons. 61 : */ 62 : class Manager { 63 : public: 64 850 : virtual ~Manager() = default; 65 : 66 : /** 67 : * This is a helper on top of get() that casts the object stored to the specified type. Since the 68 : * manager only stores pointers to the base interface, dynamic_cast provides some level of 69 : * protection via RTTI. 70 : * @param name the unique name of the singleton instance. This should be provided by the macro 71 : * SINGLETON_MANAGER_REGISTERED_NAME. 72 : * @param cb supplies the singleton creation callback. This will only be called if the singleton 73 : * does not already exist. 74 : * @param pin supplies whether the singleton should be pinned. By default, the manager only stores 75 : * a weak pointer. This allows a singleton to be cleaned up if it is not needed any more. All code 76 : * that uses singletons must store the shared_ptr for as long as the singleton is needed. But if 77 : * the pin is set to true, the singleton will be stored as a shared_ptr. This is useful if the 78 : * users want to keep the singleton around for the lifetime of the server even if it is not used 79 : * for a while. 80 : * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not 81 : * exist. 82 : */ 83 : template <class T> 84 1381 : std::shared_ptr<T> getTyped(const std::string& name, SingletonFactoryCb cb, bool pin = false) { 85 1381 : return std::dynamic_pointer_cast<T>(get(name, cb, pin)); 86 1381 : } 87 : 88 : /** 89 : * This is a non-constructing getter. Use when the caller can deal with instances where 90 : * the singleton being accessed may not have been constructed previously. 91 : * @param name the unique name of singleton instance. This should be provided by the macro 92 : * SINGLETON_MANAGER_REGISTERED_NAME. 93 : * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not 94 : * exist. 95 : */ 96 0 : template <class T> std::shared_ptr<T> getTyped(const std::string& name) { 97 0 : return std::dynamic_pointer_cast<T>(get( 98 0 : name, [] { return nullptr; }, false)); 99 0 : } 100 : 101 : /** 102 : * Get a singleton and create it if it does not exist. 103 : * @param name the unique name of the singleton instance. This should be provided by the macro 104 : * SINGLETON_MANAGER_REGISTERED_NAME. 105 : * @param cb supplies the singleton creation callback. This will only be called if the singleton 106 : * does not already exist. 107 : * @param pin supplies whether the singleton should be pinned. By default, the manager only stores 108 : * a weak pointer. This allows a singleton to be cleaned up if it is not needed any more. All code 109 : * that uses singletons must store the shared_ptr for as long as the singleton is needed. But if 110 : * the pin is set to true, the singleton will be stored as a shared_ptr. This is useful if the 111 : * users want to keep the singleton around for the lifetime of the server even if it is not used 112 : * for a while. 113 : * @return InstancePtr the singleton cast to the specified type. nullptr if the singleton does not 114 : * exist. 115 : */ 116 : virtual InstanceSharedPtr get(const std::string& name, SingletonFactoryCb cb, bool pin) PURE; 117 : }; 118 : 119 : using ManagerPtr = std::unique_ptr<Manager>; 120 : 121 : } // namespace Singleton 122 : } // namespace Envoy