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 {
50 this->
template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
85 : exec_{std::move(exec)}
89 explicit PolymorphicObject(
const PolymorphicObject& other)
95 std::shared_ptr<const Executor> exec_;
107 #define GKO_ENABLE_SELF(_type) \
108 _type* self() noexcept { return static_cast<_type*>(this); } \
110 const _type* self() const noexcept \
112 return static_cast<const _type*>(this); \
146 template <
typename ResultType>
149 using result_type = ResultType;
158 virtual void convert_to(result_type* result)
const = 0;
162 convert_to(result.
get());
179 virtual void move_to(result_type* result) = 0;
188 template <
typename R,
typename T>
189 std::unique_ptr<R, std::function<void(R*)>> copy_and_convert_to_impl(
190 std::shared_ptr<const Executor> exec, T* obj)
192 auto obj_as_r = dynamic_cast<R*>(obj);
193 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
195 return {obj_as_r, [](R*) {}};
197 auto copy = R::create(exec);
198 as<ConvertibleTo<std::decay_t<R>>>(obj)->convert_to(copy);
199 return {copy.release(), std::default_delete<R>{}};
204 template <
typename R,
typename T>
205 std::shared_ptr<R> copy_and_convert_to_impl(
206 std::shared_ptr<const Executor> exec, std::shared_ptr<T> obj)
208 auto obj_as_r = std::dynamic_pointer_cast<R>(obj);
209 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
212 auto copy = R::create(exec);
213 as<ConvertibleTo<std::decay_t<R>>>(obj.get())->convert_to(copy);
214 return {std::move(copy)};
238 template <
typename R,
typename T>
240 std::shared_ptr<const Executor> exec, T* obj)
242 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
252 template <
typename R,
typename T>
254 std::shared_ptr<const Executor> exec,
const T* obj)
256 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
277 template <
typename R,
typename T>
279 std::shared_ptr<T> obj)
281 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
292 template <
typename R,
typename T>
294 std::shared_ptr<const Executor> exec, std::shared_ptr<const T> obj)
296 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
309 [[nodiscard]] std::unique_ptr<Cloneable> clone(
310 std::shared_ptr<const Executor> exec)
const
312 return this->clone_impl(std::move(exec));
315 [[nodiscard]] std::unique_ptr<Cloneable> clone()
const
317 return this->clone_impl();
322 auto copied = this->copy_from_impl(other.
get());
328 auto moved = this->move_from_impl(other.
get());
332 [[nodiscard]] std::unique_ptr<Cloneable> create_default(
333 std::shared_ptr<const Executor> exec)
const
335 return this->create_default_impl(std::move(exec));
338 [[nodiscard]] std::unique_ptr<Cloneable> create_default()
const
340 return this->create_default_impl();
346 virtual Cloneable* copy_from_impl(std::unique_ptr<Cloneable> other) = 0;
350 virtual Cloneable* move_from_impl(std::unique_ptr<Cloneable> other) = 0;
352 [[nodiscard]]
virtual std::unique_ptr<Cloneable> clone_impl(
353 std::shared_ptr<const Executor> exec)
const = 0;
355 [[nodiscard]]
virtual std::unique_ptr<Cloneable> clone_impl()
const = 0;
357 [[nodiscard]]
virtual std::unique_ptr<Cloneable> create_default_impl()
360 [[nodiscard]]
virtual std::unique_ptr<Cloneable> create_default_impl(
361 std::shared_ptr<const Executor> exec)
const = 0;
375 template <
typename ConcreteType>
378 using result_type = ConcreteType;
392 [[nodiscard]] std::unique_ptr<ConcreteType>
clone(
393 std::shared_ptr<const Executor> exec)
const
395 return as<ConcreteType>(this->clone_impl(std::move(exec)));
406 [[nodiscard]] std::unique_ptr<ConcreteType>
clone()
const
408 return as<ConcreteType>(this->clone_impl());
411 void convert_to(result_type* result)
const override { *result = *
self(); }
413 void move_to(result_type* result)
override { *result = std::move(*
self()); }
415 [[nodiscard]] std::unique_ptr<ConcreteType> create_default()
const
417 return as<ConcreteType>(this->create_default_impl());
420 [[nodiscard]] std::unique_ptr<ConcreteType> create_default(
421 std::shared_ptr<const Executor> exec)
const
423 return as<ConcreteType>(this->create_default_impl(std::move(exec)));
427 Cloneable* copy_from_impl(
const Cloneable* other)
override
429 self()->
template log<log::Logger::polymorphic_object_copy_started>(
430 self()->get_executor().get(),
431 dynamic_cast<const PolymorphicObject*>(other),
432 dynamic_cast<const PolymorphicObject*>(
this));
433 as<ConvertibleTo<ConcreteType>>(other)->
convert_to(
self());
434 self()->
template log<log::Logger::polymorphic_object_copy_completed>(
435 self()->get_executor().get(),
436 dynamic_cast<const PolymorphicObject*>(other),
437 dynamic_cast<const PolymorphicObject*>(
this));
441 Cloneable* copy_from_impl(std::unique_ptr<Cloneable> other)
override
443 self()->
template log<log::Logger::polymorphic_object_copy_started>(
444 self()->get_executor().get(),
445 dynamic_cast<const PolymorphicObject*>(other.get()),
446 dynamic_cast<const PolymorphicObject*>(
this));
447 as<ConvertibleTo<ConcreteType>>(other.get())->
convert_to(
self());
448 self()->
template log<log::Logger::polymorphic_object_copy_completed>(
449 self()->get_executor().get(),
450 dynamic_cast<const PolymorphicObject*>(other.get()),
451 dynamic_cast<const PolymorphicObject*>(
this));
455 Cloneable* move_from_impl(Cloneable* other)
override
457 self()->
template log<log::Logger::polymorphic_object_move_started>(
458 self()->get_executor().get(),
459 dynamic_cast<const PolymorphicObject*>(other),
460 dynamic_cast<const PolymorphicObject*>(
this));
461 as<ConvertibleTo<ConcreteType>>(other)->
move_to(
self());
462 self()->
template log<log::Logger::polymorphic_object_move_completed>(
463 self()->get_executor().get(),
464 dynamic_cast<const PolymorphicObject*>(other),
465 dynamic_cast<const PolymorphicObject*>(
this));
469 Cloneable* move_from_impl(std::unique_ptr<Cloneable> other)
override
471 self()->
template log<log::Logger::polymorphic_object_move_started>(
472 self()->get_executor().get(),
473 dynamic_cast<const PolymorphicObject*>(other.get()),
474 dynamic_cast<const PolymorphicObject*>(
this));
475 as<ConvertibleTo<ConcreteType>>(other.get())->
move_to(
self());
476 self()->
template log<log::Logger::polymorphic_object_move_completed>(
477 self()->get_executor().get(),
478 dynamic_cast<const PolymorphicObject*>(other.get()),
479 dynamic_cast<const PolymorphicObject*>(
this));
483 [[nodiscard]] std::unique_ptr<Cloneable> clone_impl(
484 std::shared_ptr<const Executor> exec)
const override
486 auto new_op =
self()->create_default(exec);
487 new_op->copy_from(
this);
491 [[nodiscard]] std::unique_ptr<Cloneable> clone_impl()
const override
493 return this->clone_impl(
self()->get_executor());
496 [[nodiscard]] std::unique_ptr<Cloneable> create_default_impl()
499 return this->create_default_impl(
self()->get_executor());
502 [[nodiscard]] std::unique_ptr<Cloneable> create_default_impl(
503 std::shared_ptr<const Executor> exec)
const override
505 if constexpr (std::is_base_of_v<
506 experimental::distributed::DistributedBase,
508 return std::unique_ptr<ConcreteType>(
509 new ConcreteType(std::move(exec),
self()->get_communicator()));
511 return std::unique_ptr<ConcreteType>(
512 new ConcreteType(std::move(exec)));
516 GKO_ENABLE_SELF(ConcreteType);
528 template <
typename ConcreteType>
531 template <
typename... Args>
532 static std::unique_ptr<ConcreteType> create(Args&&... args)
534 return std::unique_ptr<ConcreteType>(
535 new ConcreteType(std::forward<Args>(args)...));
543 #endif // GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_