5 #ifndef GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
6 #define GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
10 #include <type_traits>
12 #include <ginkgo/core/base/executor.hpp>
13 #include <ginkgo/core/base/utils.hpp>
14 #include <ginkgo/core/log/logger.hpp>
18 namespace experimental {
19 namespace distributed {
56 this->
template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
74 std::shared_ptr<const Executor> exec)
const
76 this->
template log<log::Logger::polymorphic_object_create_started>(
78 auto created = this->create_default_impl(std::move(exec));
79 this->
template log<log::Logger::polymorphic_object_create_completed>(
80 exec_.get(),
this, created.get());
107 std::unique_ptr<PolymorphicObject>
clone(
108 std::shared_ptr<const Executor> exec)
const
111 new_op->copy_from(
this);
123 std::unique_ptr<PolymorphicObject>
clone()
const
125 return this->
clone(exec_);
141 this->
template log<log::Logger::polymorphic_object_copy_started>(
142 exec_.get(), other,
this);
143 auto copied = this->copy_from_impl(other);
144 this->
template log<log::Logger::polymorphic_object_copy_completed>(
145 exec_.get(), other,
this);
164 template <
typename Derived,
typename Deleter>
166 "This function will be removed in a future release, the replacement "
167 "will copy instead of move. If a move is intended, use move_from "
173 this->
template log<log::Logger::polymorphic_object_move_started>(
174 exec_.get(), other.get(),
this);
175 auto copied = this->copy_from_impl(std::move(other));
176 this->
template log<log::Logger::polymorphic_object_move_completed>(
177 exec_.get(), other.get(),
this);
188 template <
typename Derived,
typename Deleter>
190 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
192 copy_from(
const std::unique_ptr<Derived, Deleter>& other)
201 const std::shared_ptr<const PolymorphicObject>& other)
219 this->
template log<log::Logger::polymorphic_object_move_started>(
220 exec_.get(), other.
get(),
this);
221 auto moved = this->move_from_impl(other.
get());
222 this->
template log<log::Logger::polymorphic_object_move_completed>(
223 exec_.get(), other.
get(),
this);
259 : exec_{std::move(exec)}
263 explicit PolymorphicObject(
const PolymorphicObject& other)
276 virtual std::unique_ptr<PolymorphicObject> create_default_impl(
277 std::shared_ptr<const Executor> exec)
const = 0;
287 virtual PolymorphicObject* copy_from_impl(
288 const PolymorphicObject* other) = 0;
298 virtual PolymorphicObject* copy_from_impl(
299 std::unique_ptr<PolymorphicObject> other) = 0;
309 virtual PolymorphicObject* move_from_impl(PolymorphicObject* other) = 0;
319 virtual PolymorphicObject* move_from_impl(
320 std::unique_ptr<PolymorphicObject> other) = 0;
328 virtual PolymorphicObject* clear_impl() = 0;
331 std::shared_ptr<const Executor> exec_;
353 template <
typename AbstractObject,
typename PolymorphicBase = PolymorphicObject>
356 using PolymorphicBase::PolymorphicBase;
358 std::unique_ptr<AbstractObject> create_default(
359 std::shared_ptr<const Executor> exec)
const
361 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
362 this->PolymorphicBase::create_default(std::move(exec)).release())};
365 std::unique_ptr<AbstractObject> create_default()
const
367 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
368 this->PolymorphicBase::create_default().release())};
371 std::unique_ptr<AbstractObject>
clone(
372 std::shared_ptr<const Executor> exec)
const
374 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
375 this->PolymorphicBase::clone(std::move(exec)).release())};
378 std::unique_ptr<AbstractObject>
clone()
const
380 return std::unique_ptr<AbstractObject>{static_cast<AbstractObject*>(
381 this->PolymorphicBase::clone().release())};
386 return static_cast<AbstractObject*>(
387 this->PolymorphicBase::copy_from(other));
390 template <
typename Derived>
392 "This function will be removed in a future release, the replacement "
393 "will copy instead of move. If a move in intended, use move_to "
396 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
397 AbstractObject>* copy_from(std::unique_ptr<Derived>&& other)
399 return static_cast<AbstractObject*>(
400 this->PolymorphicBase::copy_from(std::move(other)));
403 template <
typename Derived>
405 std::is_base_of<PolymorphicObject, std::decay_t<Derived>>::value,
407 copy_from(
const std::unique_ptr<Derived>& other)
409 return copy_from(other.get());
412 AbstractObject* copy_from(
413 const std::shared_ptr<const PolymorphicObject>& other)
415 return copy_from(other.get());
420 return static_cast<AbstractObject*>(
421 this->PolymorphicBase::move_from(other.
get()));
424 AbstractObject* clear()
426 return static_cast<AbstractObject*>(this->PolymorphicBase::clear());
439 #define GKO_ENABLE_SELF(_type) \
440 _type* self() noexcept { return static_cast<_type*>(this); } \
442 const _type* self() const noexcept \
444 return static_cast<const _type*>(this); \
478 template <
typename ResultType>
481 using result_type = ResultType;
490 virtual void convert_to(result_type* result)
const = 0;
511 virtual void move_to(result_type* result) = 0;
520 template <
typename R,
typename T>
521 std::unique_ptr<R, std::function<void(R*)>> copy_and_convert_to_impl(
522 std::shared_ptr<const Executor> exec, T* obj)
524 auto obj_as_r = dynamic_cast<R*>(obj);
525 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
527 return {obj_as_r, [](R*) {}};
529 auto copy = R::create(exec);
530 as<ConvertibleTo<std::decay_t<R>>>(obj)->convert_to(copy);
531 return {copy.release(), std::default_delete<R>{}};
536 template <
typename R,
typename T>
537 std::shared_ptr<R> copy_and_convert_to_impl(
538 std::shared_ptr<const Executor> exec, std::shared_ptr<T> obj)
540 auto obj_as_r = std::dynamic_pointer_cast<R>(obj);
541 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
544 auto copy = R::create(exec);
545 as<ConvertibleTo<std::decay_t<R>>>(obj.get())->convert_to(copy);
546 return {std::move(copy)};
570 template <
typename R,
typename T>
572 std::shared_ptr<const Executor> exec, T* obj)
574 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
584 template <
typename R,
typename T>
586 std::shared_ptr<const Executor> exec,
const T* obj)
588 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
609 template <
typename R,
typename T>
611 std::shared_ptr<T> obj)
613 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
624 template <
typename R,
typename T>
626 std::shared_ptr<const Executor> exec, std::shared_ptr<const T> obj)
628 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
666 template <
typename ConcreteObject,
typename PolymorphicBase = PolymorphicObject>
673 std::unique_ptr<PolymorphicObject> create_default_impl(
674 std::shared_ptr<const Executor> exec)
const override
676 if constexpr (std::is_base_of_v<
679 return std::unique_ptr<ConcreteObject>{
680 new ConcreteObject(exec,
self()->get_communicator())};
682 return std::unique_ptr<ConcreteObject>{
new ConcreteObject(exec)};
688 as<ConvertibleTo<ConcreteObject>>(other)->convert_to(
self());
693 std::unique_ptr<PolymorphicObject> other)
override
695 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
701 as<ConvertibleTo<ConcreteObject>>(other)->move_to(
self());
706 std::unique_ptr<PolymorphicObject> other)
override
708 as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(
self());
714 if constexpr (std::is_base_of_v<
717 *
self() = ConcreteObject{this->get_executor(),
718 self()->get_communicator()};
720 *
self() = ConcreteObject{this->get_executor()};
726 GKO_ENABLE_SELF(ConcreteObject);
742 template <
typename ConcreteType,
typename ResultType = ConcreteType>
745 using result_type = ResultType;
754 GKO_ENABLE_SELF(ConcreteType);
766 template <
typename ConcreteType>
769 template <
typename... Args>
770 static std::unique_ptr<ConcreteType> create(Args&&... args)
772 return std::unique_ptr<ConcreteType>(
773 new ConcreteType(std::forward<Args>(args)...));
781 #endif // GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_