5#ifndef GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
6#define GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
12#include <ginkgo/core/base/executor.hpp>
13#include <ginkgo/core/base/utils.hpp>
14#include <ginkgo/core/log/logger.hpp>
18namespace experimental {
54 virtual ~PolymorphicObject()
56 this->
template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
61 PolymorphicObject& operator=(
const PolymorphicObject&) {
return *
this; }
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_);
139 PolymorphicObject*
copy_from(
const PolymorphicObject* other)
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 "
171 PolymorphicObject>*
copy_from(
std::unique_ptr<Derived, Deleter>&& other)
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);
236 PolymorphicObject*
clear() {
return this->clear_impl(); }
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_;
353template <
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())};
384 AbstractObject* copy_from(
const PolymorphicObject* other)
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); \
478template <
typename ResultType>
481 using result_type = ResultType;
511 virtual void move_to(result_type* result) = 0;
520template <
typename R,
typename T>
521std::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);
531 return {copy.release(), std::default_delete<R>{}};
536template <
typename R,
typename T>
537std::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);
546 return {std::move(copy)};
570template <
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);
584template <
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);
609template <
typename R,
typename T>
611 std::shared_ptr<T> obj)
613 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
624template <
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);
666template <
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)};
693 std::unique_ptr<PolymorphicObject> other)
override
706 std::unique_ptr<PolymorphicObject> other)
override
714 if constexpr (std::is_base_of_v<
718 self()->get_communicator()};
726 GKO_ENABLE_SELF(ConcreteObject);
742template <
typename ConcreteType,
typename ResultType = ConcreteType>
745 using result_type = ResultType;
749 void convert_to(result_type* result)
const override { *result = *self(); }
751 void move_to(result_type* result)
override { *result = std::move(*self()); }
754 GKO_ENABLE_SELF(ConcreteType);
766template <
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)...));
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition polymorphic_object.hpp:479
virtual void convert_to(result_type *result) const =0
Converts the implementer to an object of type result_type.
virtual void move_to(result_type *result)=0
Converts the implementer to an object of type result_type by moving data from this object.
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:354
This mixin implements a static create() method on ConcreteType that dynamically allocates the memory,...
Definition polymorphic_object.hpp:767
This mixin is used to enable a default PolymorphicObject::copy_from() implementation for objects that...
Definition polymorphic_object.hpp:743
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:668
A PolymorphicObject is the abstract base for all "heavy" objects in Ginkgo that behave polymorphicall...
Definition polymorphic_object.hpp:52
PolymorphicObject * copy_from(const PolymorphicObject *other)
Copies another object into this object.
Definition polymorphic_object.hpp:139
PolymorphicObject * copy_from(const std::shared_ptr< const PolymorphicObject > &other)
Copies another object into this object.
Definition polymorphic_object.hpp:200
std::enable_if_t< std::is_base_of< PolymorphicObject, std::decay_t< Derived > >::value, PolymorphicObject > * copy_from(const std::unique_ptr< Derived, Deleter > &other)
Copies another object into this object.
Definition polymorphic_object.hpp:192
PolymorphicObject * move_from(ptr_param< PolymorphicObject > other)
Moves another object into this object.
Definition polymorphic_object.hpp:217
std::unique_ptr< PolymorphicObject > create_default() const
Creates a new "default" object of the same dynamic type as this object.
Definition polymorphic_object.hpp:92
std::unique_ptr< PolymorphicObject > clone() const
Creates a clone of the object.
Definition polymorphic_object.hpp:123
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition polymorphic_object.hpp:243
std::unique_ptr< PolymorphicObject > create_default(std::shared_ptr< const Executor > exec) const
Creates a new "default" object of the same dynamic type as this object.
Definition polymorphic_object.hpp:73
std::unique_ptr< PolymorphicObject > clone(std::shared_ptr< const Executor > exec) const
Creates a clone of the object.
Definition polymorphic_object.hpp:107
PolymorphicObject * clear()
Transforms the object into its default state.
Definition polymorphic_object.hpp:236
A base class for distributed objects.
Definition base.hpp:32
EnableLogging is a mixin which should be inherited by any class which wants to enable logging.
Definition logger.hpp:786
This class is used for function parameters in the place of raw pointers.
Definition utils_helper.hpp:41
T * get() const
Definition utils_helper.hpp:75
The distributed namespace.
Definition polymorphic_object.hpp:19
The Ginkgo namespace.
Definition abstract_factory.hpp:20
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition utils_helper.hpp:173
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition utils_helper.hpp:307
std::unique_ptr< R, std::function< void(R *)> > copy_and_convert_to(std::shared_ptr< const Executor > exec, T *obj)
Converts the object to R and places it on Executor exec.
Definition polymorphic_object.hpp:571