5 #ifndef GKO_PUBLIC_CORE_BASE_ABSTRACT_FACTORY_HPP_
6 #define GKO_PUBLIC_CORE_BASE_ABSTRACT_FACTORY_HPP_
10 #include <unordered_map>
12 #include <ginkgo/core/base/polymorphic_object.hpp>
44 template <
typename AbstractProductType,
typename ComponentsType>
47 using abstract_product_type = AbstractProductType;
48 using components_type = ComponentsType;
64 template <
typename... Args>
65 std::unique_ptr<abstract_product_type>
generate(Args&&... args)
const
68 this->generate_impl(components_type{std::forward<Args>(args)...});
69 for (
auto logger : this->loggers_) {
70 product->add_logger(logger);
92 virtual std::unique_ptr<abstract_product_type> generate_impl(
93 ComponentsType args)
const = 0;
120 template <
typename ConcreteFactory,
typename ProductType,
121 typename ParametersType,
typename PolymorphicBase>
124 using product_type = ProductType;
125 using parameters_type = ParametersType;
126 using polymorphic_base = PolymorphicBase;
127 using abstract_product_type =
128 typename PolymorphicBase::abstract_product_type;
129 using components_type =
typename PolymorphicBase::components_type;
131 template <
typename... Args>
132 std::unique_ptr<product_type> generate(Args&&... args)
const
134 auto product = std::unique_ptr<product_type>(static_cast<product_type*>(
135 this->polymorphic_base::generate(std::forward<Args>(args)...)
162 static parameters_type
create() {
return {}; }
172 const parameters_type& parameters = {})
173 : PolymorphicBase(std::move(exec)), parameters_{parameters}
176 std::unique_ptr<abstract_product_type> generate_impl(
177 components_type args)
const override
179 return std::unique_ptr<abstract_product_type>(
180 new product_type(
self(), args));
184 GKO_ENABLE_SELF(ConcreteFactory);
186 ParametersType parameters_;
202 template <
typename ConcreteParametersType,
typename Factory>
205 using factory = Factory;
211 template <
typename... Args>
214 this->loggers = {std::forward<Args>(_value)...};
225 std::unique_ptr<Factory>
on(std::shared_ptr<const Executor> exec)
const
227 ConcreteParametersType copy = *
self();
228 for (
const auto& item : deferred_factories) {
229 item.second(exec, copy);
231 auto factory = std::unique_ptr<Factory>(
new Factory(exec, copy));
232 for (
auto& logger : loggers) {
233 factory->add_logger(logger);
239 GKO_ENABLE_SELF(ConcreteParametersType);
244 std::vector<std::shared_ptr<const log::Logger>> loggers{};
252 std::unordered_map<std::string,
253 std::function<void(std::shared_ptr<const Executor> exec,
254 ConcreteParametersType&)>>
272 #define GKO_CREATE_FACTORY_PARAMETERS(_parameters_name, _factory_name) \
274 class _factory_name; \
275 struct _parameters_name##_type \
276 : public ::gko::enable_parameters_type<_parameters_name##_type, \
285 template <
typename From,
typename To>
286 struct is_pointer_convertible : std::is_convertible<From*, To*> {};
300 template <
typename FactoryType>
309 generator_ = [](std::shared_ptr<const Executor>) {
return nullptr; };
316 template <
typename ConcreteFactoryType,
317 std::enable_if_t<detail::is_pointer_convertible<
318 ConcreteFactoryType, FactoryType>::value>* =
nullptr>
321 generator_ = [factory =
322 std::shared_ptr<FactoryType>(std::move(factory))](
323 std::shared_ptr<const Executor>) {
return factory; };
330 template <
typename ConcreteFactoryType,
typename Deleter,
331 std::enable_if_t<detail::is_pointer_convertible<
332 ConcreteFactoryType, FactoryType>::value>* =
nullptr>
334 std::unique_ptr<ConcreteFactoryType, Deleter> factory)
336 generator_ = [factory =
337 std::shared_ptr<FactoryType>(std::move(factory))](
338 std::shared_ptr<const Executor>) {
return factory; };
346 template <
typename ParametersType,
347 typename U = decltype(std::declval<ParametersType>().
on(
348 std::shared_ptr<const Executor>{})),
349 std::enable_if_t<detail::is_pointer_convertible<
350 typename U::element_type, FactoryType>::value>* =
nullptr>
353 generator_ = [parameters](std::shared_ptr<const Executor> exec)
354 -> std::shared_ptr<FactoryType> {
return parameters.on(exec); };
361 std::shared_ptr<FactoryType>
on(std::shared_ptr<const Executor> exec)
const
364 GKO_NOT_SUPPORTED(*
this);
366 return generator_(exec);
370 bool is_empty()
const {
return !bool(generator_); }
373 std::function<std::shared_ptr<FactoryType>(std::shared_ptr<const Executor>)>
386 #define GKO_ENABLE_BUILD_METHOD(_factory_name) \
387 static auto build()->decltype(_factory_name::create()) \
389 return _factory_name::create(); \
391 static_assert(true, \
392 "This assert is used to counter the false positive extra " \
393 "semi-colon warnings")
396 #if !(defined(__CUDACC__) || defined(__HIPCC__))
409 #define GKO_FACTORY_PARAMETER(_name, ...) \
410 _name{__VA_ARGS__}; \
412 template <typename... Args> \
413 auto with_##_name(Args&&... _value) \
414 ->std::decay_t<decltype(*(this->self()))>& \
416 using type = decltype(this->_name); \
417 this->_name = type{std::forward<Args>(_value)...}; \
418 return *(this->self()); \
420 static_assert(true, \
421 "This assert is used to counter the false positive extra " \
422 "semi-colon warnings")
437 #define GKO_FACTORY_PARAMETER_SCALAR(_name, _default) \
438 GKO_FACTORY_PARAMETER(_name, _default)
453 #define GKO_FACTORY_PARAMETER_VECTOR(_name, ...) \
454 GKO_FACTORY_PARAMETER(_name, __VA_ARGS__)
455 #else // defined(__CUDACC__) || defined(__HIPCC__)
460 #define GKO_FACTORY_PARAMETER(_name, ...) \
461 _name{__VA_ARGS__}; \
463 template <typename... Args> \
464 auto with_##_name(Args&&... _value) \
465 ->std::decay_t<decltype(*(this->self()))>& \
467 GKO_NOT_IMPLEMENTED; \
468 return *(this->self()); \
470 static_assert(true, \
471 "This assert is used to counter the false positive extra " \
472 "semi-colon warnings")
474 #define GKO_FACTORY_PARAMETER_SCALAR(_name, _default) \
477 template <typename Arg> \
478 auto with_##_name(Arg&& _value)->std::decay_t<decltype(*(this->self()))>& \
480 using type = decltype(this->_name); \
481 this->_name = type{std::forward<Arg>(_value)}; \
482 return *(this->self()); \
484 static_assert(true, \
485 "This assert is used to counter the false positive extra " \
486 "semi-colon warnings")
488 #define GKO_FACTORY_PARAMETER_VECTOR(_name, ...) \
489 _name{__VA_ARGS__}; \
491 template <typename... Args> \
492 auto with_##_name(Args&&... _value) \
493 ->std::decay_t<decltype(*(this->self()))>& \
495 using type = decltype(this->_name); \
496 this->_name = type{std::forward<Args>(_value)...}; \
497 return *(this->self()); \
499 static_assert(true, \
500 "This assert is used to counter the false positive extra " \
501 "semi-colon warnings")
502 #endif // defined(__CUDACC__) || defined(__HIPCC__)
513 #define GKO_DEFERRED_FACTORY_PARAMETER(_name) \
517 using _name##_type = typename decltype(_name)::element_type; \
520 auto with_##_name(::gko::deferred_factory_parameter<_name##_type> factory) \
521 ->std::decay_t<decltype(*(this->self()))>& \
523 this->_name##_generator_ = std::move(factory); \
524 this->deferred_factories[#_name] = [](const auto& exec, \
526 if (!params._name##_generator_.is_empty()) { \
527 params._name = params._name##_generator_.on(exec); \
530 return *(this->self()); \
534 ::gko::deferred_factory_parameter<_name##_type> _name##_generator_; \
537 static_assert(true, \
538 "This assert is used to counter the false positive extra " \
539 "semi-colon warnings")
551 #define GKO_DEFERRED_FACTORY_VECTOR_PARAMETER(_name) \
555 using _name##_type = typename decltype(_name)::value_type::element_type; \
558 template <typename... Args, \
559 typename = std::enable_if_t<::std::conjunction< \
560 std::is_convertible<Args, ::gko::deferred_factory_parameter< \
561 _name##_type>>...>::value>> \
562 auto with_##_name(Args&&... factories) \
563 ->std::decay_t<decltype(*(this->self()))>& \
565 this->_name##_generator_ = { \
566 ::gko::deferred_factory_parameter<_name##_type>{ \
567 std::forward<Args>(factories)}...}; \
568 this->deferred_factories[#_name] = [](const auto& exec, \
570 if (!params._name##_generator_.empty()) { \
571 params._name.clear(); \
572 for (auto& generator : params._name##_generator_) { \
573 params._name.push_back(generator.on(exec)); \
577 return *(this->self()); \
579 template <typename FactoryType, \
580 typename = std::enable_if_t<std::is_convertible< \
582 ::gko::deferred_factory_parameter<_name##_type>>::value>> \
583 auto with_##_name(const std::vector<FactoryType>& factories) \
584 ->std::decay_t<decltype(*(this->self()))>& \
586 this->_name##_generator_.clear(); \
587 for (const auto& factory : factories) { \
588 this->_name##_generator_.push_back(factory); \
590 this->deferred_factories[#_name] = [](const auto& exec, \
592 if (!params._name##_generator_.empty()) { \
593 params._name.clear(); \
594 for (auto& generator : params._name##_generator_) { \
595 params._name.push_back(generator.on(exec)); \
599 return *(this->self()); \
603 std::vector<::gko::deferred_factory_parameter<_name##_type>> \
604 _name##_generator_; \
607 static_assert(true, \
608 "This assert is used to counter the false positive extra " \
609 "semi-colon warnings")
615 #endif // GKO_PUBLIC_CORE_BASE_ABSTRACT_FACTORY_HPP_