object_factory.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #pragma once
  2. #include <util/system/guard.h>
  3. #include <util/system/rwlock.h>
  4. #include <util/generic/map.h>
  5. #include <util/generic/set.h>
  6. #include <util/generic/singleton.h>
  7. #include <util/generic/yexception.h>
  8. namespace NObjectFactory {
  9. template <class TProduct, class... TArgs>
  10. class IFactoryObjectCreator {
  11. public:
  12. virtual TProduct* Create(TArgs... args) const = 0;
  13. virtual ~IFactoryObjectCreator() {
  14. }
  15. };
  16. template <class TProduct>
  17. class IFactoryObjectCreator<TProduct, void> {
  18. public:
  19. virtual TProduct* Create(void) const = 0;
  20. virtual ~IFactoryObjectCreator() {
  21. }
  22. };
  23. #define FACTORY_OBJECT_NAME(Name) \
  24. static TString GetTypeName() { \
  25. return #Name; \
  26. } \
  27. virtual TString GetType() const override { \
  28. return #Name; \
  29. }
  30. template <class TBaseProduct, class TDerivedProduct, class... TArgs>
  31. class TFactoryObjectCreator: public IFactoryObjectCreator<TBaseProduct, TArgs...> {
  32. TDerivedProduct* Create(TArgs... args) const override {
  33. return new TDerivedProduct(std::forward<TArgs>(args)...);
  34. }
  35. };
  36. template <class TBaseProduct, class TDerivedProduct>
  37. class TFactoryObjectCreator<TBaseProduct, TDerivedProduct, void>: public IFactoryObjectCreator<TBaseProduct, void> {
  38. TDerivedProduct* Create() const override {
  39. return new TDerivedProduct();
  40. }
  41. };
  42. template <class P, class K, class... TArgs>
  43. class IObjectFactory {
  44. public:
  45. typedef P TProduct;
  46. typedef K TKey;
  47. public:
  48. template <class TDerivedProduct>
  49. void Register(const TKey& key, IFactoryObjectCreator<TProduct, TArgs...>* creator) {
  50. if (!creator)
  51. ythrow yexception() << "Please specify non-null creator for " << key;
  52. TWriteGuard guard(CreatorsLock);
  53. if (!Creators.insert(typename ICreators::value_type(key, creator)).second)
  54. ythrow yexception() << "Product with key " << key << " already registered";
  55. }
  56. template <class TDerivedProduct>
  57. void Register(const TKey& key) {
  58. Register<TDerivedProduct>(key, new TFactoryObjectCreator<TProduct, TDerivedProduct, TArgs...>);
  59. }
  60. void GetKeys(TSet<TKey>& keys) const {
  61. TReadGuard guard(CreatorsLock);
  62. keys.clear();
  63. for (typename ICreators::const_iterator i = Creators.begin(), e = Creators.end(); i != e; ++i) {
  64. keys.insert(i->first);
  65. }
  66. }
  67. protected:
  68. template <class T>
  69. IFactoryObjectCreator<TProduct, TArgs...>* GetCreator(const T& key) const {
  70. TReadGuard guard(CreatorsLock);
  71. typename ICreators::const_iterator i = Creators.find(key);
  72. return i == Creators.end() ? nullptr : i->second.Get();
  73. }
  74. template <class T>
  75. bool HasImpl(const T& key) const {
  76. TReadGuard guard(CreatorsLock);
  77. return Creators.find(key) != Creators.end();
  78. }
  79. private:
  80. typedef TSimpleSharedPtr<IFactoryObjectCreator<TProduct, TArgs...>> ICreatorPtr;
  81. typedef TMap<TKey, ICreatorPtr> ICreators;
  82. ICreators Creators;
  83. TRWMutex CreatorsLock;
  84. };
  85. template <class TProduct, class TKey, class... TArgs>
  86. class TParametrizedObjectFactory: public IObjectFactory<TProduct, TKey, TArgs...> {
  87. public:
  88. template <class T>
  89. TProduct* Create(const T& key, TArgs... args) const {
  90. IFactoryObjectCreator<TProduct, TArgs...>* creator = IObjectFactory<TProduct, TKey, TArgs...>::GetCreator(key);
  91. return creator == nullptr ? nullptr : creator->Create(std::forward<TArgs>(args)...);
  92. }
  93. template <class T>
  94. static bool Has(const T& key) {
  95. return Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->HasImpl(key);
  96. }
  97. template <class T>
  98. static TProduct* Construct(const T& key, const TKey& defKey, TArgs... args) {
  99. TProduct* result = Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->Create(key, std::forward<TArgs>(args)...);
  100. if (!result && !!defKey) {
  101. result = Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->Create(defKey, std::forward<TArgs>(args)...);
  102. }
  103. return result;
  104. }
  105. template <class T>
  106. static TProduct* Construct(const T& key, TArgs... args) {
  107. return Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->Create(key, std::forward<TArgs>(args)...);
  108. }
  109. template <class... Args>
  110. static THolder<TProduct> VerifiedConstruct(Args&&... args) {
  111. auto result = MakeHolder(std::forward<Args>(args)...);
  112. Y_ABORT_UNLESS(result, "Construct by factory failed");
  113. return result;
  114. }
  115. template<class... Args>
  116. static THolder<TProduct> MakeHolder(Args&&... args) {
  117. return THolder<TProduct>(Construct(std::forward<Args>(args)...));
  118. }
  119. static void GetRegisteredKeys(TSet<TKey>& keys) {
  120. return Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->GetKeys(keys);
  121. }
  122. static TSet<TKey> GetRegisteredKeys() {
  123. TSet<TKey> keys;
  124. Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->GetKeys(keys);
  125. return keys;
  126. }
  127. template <class TDerivedProduct>
  128. static TSet<TKey> GetRegisteredKeys() {
  129. TSet<TKey> registeredKeys(GetRegisteredKeys());
  130. TSet<TKey> fileredKeys;
  131. std::copy_if(registeredKeys.begin(), registeredKeys.end(), std::inserter(fileredKeys, fileredKeys.end()), [](const TKey& key) {
  132. THolder<TProduct> objectHolder(Construct(key));
  133. return !!dynamic_cast<const TDerivedProduct*>(objectHolder.Get());
  134. });
  135. return fileredKeys;
  136. }
  137. template <class Product>
  138. class TRegistrator {
  139. public:
  140. TRegistrator(const TKey& key, IFactoryObjectCreator<TProduct, TArgs...>* creator) {
  141. Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->template Register<Product>(key, creator);
  142. }
  143. TRegistrator(const TKey& key) {
  144. Singleton<TParametrizedObjectFactory<TProduct, TKey, TArgs...>>()->template Register<Product>(key);
  145. }
  146. TRegistrator()
  147. : TRegistrator(Product::GetTypeName())
  148. {
  149. }
  150. TString GetName() const {
  151. return Product::GetTypeName();
  152. }
  153. };
  154. };
  155. template <class TProduct, class TKey, class... TArgs>
  156. using TObjectFactory = TParametrizedObjectFactory<TProduct, TKey, TArgs...>;
  157. }