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(),
78 : exec_{std::move(exec)}
82 explicit PolymorphicObject(
const PolymorphicObject& other)
88 std::shared_ptr<const Executor> exec_;
100 #define GKO_ENABLE_SELF(_type) \
101 _type* self() noexcept { return static_cast<_type*>(this); } \
103 const _type* self() const noexcept \
105 return static_cast<const _type*>(this); \
139 template <
typename ResultType>
142 using result_type = ResultType;
151 virtual void convert_to(result_type* result)
const = 0;
155 convert_to(result.
get());
172 virtual void move_to(result_type* result) = 0;
181 template <
typename R,
typename T>
182 std::unique_ptr<R, std::function<void(R*)>> copy_and_convert_to_impl(
183 std::shared_ptr<const Executor> exec, T* obj)
185 auto obj_as_r = dynamic_cast<R*>(obj);
186 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
188 return {obj_as_r, [](R*) {}};
190 auto copy = R::create(exec);
191 as<ConvertibleTo<std::decay_t<R>>>(obj)->convert_to(copy);
192 return {copy.release(), std::default_delete<R>{}};
197 template <
typename R,
typename T>
198 std::shared_ptr<R> copy_and_convert_to_impl(
199 std::shared_ptr<const Executor> exec, std::shared_ptr<T> obj)
201 auto obj_as_r = std::dynamic_pointer_cast<R>(obj);
202 if (obj_as_r !=
nullptr && obj->get_executor() == exec) {
205 auto copy = R::create(exec);
206 as<ConvertibleTo<std::decay_t<R>>>(obj.get())->convert_to(copy);
207 return {std::move(copy)};
231 template <
typename R,
typename T>
233 std::shared_ptr<const Executor> exec, T* obj)
235 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
245 template <
typename R,
typename T>
247 std::shared_ptr<const Executor> exec,
const T* obj)
249 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
270 template <
typename R,
typename T>
272 std::shared_ptr<T> obj)
274 return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
285 template <
typename R,
typename T>
287 std::shared_ptr<const Executor> exec, std::shared_ptr<const T> obj)
289 return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
302 [[nodiscard]] std::unique_ptr<Cloneable> clone(
303 std::shared_ptr<const Executor> exec)
const
305 return this->clone_impl(std::move(exec));
308 [[nodiscard]] std::unique_ptr<Cloneable> clone()
const
310 return this->clone_impl();
315 auto copied = this->copy_from_impl(other.
get());
321 auto moved = this->move_from_impl(other.
get());
325 [[nodiscard]] std::unique_ptr<Cloneable> create_default(
326 std::shared_ptr<const Executor> exec)
const
328 return this->create_default_impl(std::move(exec));
331 [[nodiscard]] std::unique_ptr<Cloneable> create_default()
const
333 return this->create_default_impl();
339 virtual Cloneable* copy_from_impl(std::unique_ptr<Cloneable> other) = 0;
343 virtual Cloneable* move_from_impl(std::unique_ptr<Cloneable> other) = 0;
345 [[nodiscard]]
virtual std::unique_ptr<Cloneable> clone_impl(
346 std::shared_ptr<const Executor> exec)
const = 0;
348 [[nodiscard]]
virtual std::unique_ptr<Cloneable> clone_impl()
const = 0;
350 [[nodiscard]]
virtual std::unique_ptr<Cloneable> create_default_impl()
353 [[nodiscard]]
virtual std::unique_ptr<Cloneable> create_default_impl(
354 std::shared_ptr<const Executor> exec)
const = 0;
368 template <
typename ConcreteType>
371 using result_type = ConcreteType;
385 [[nodiscard]] std::unique_ptr<ConcreteType>
clone(
386 std::shared_ptr<const Executor> exec)
const
388 return as<ConcreteType>(this->clone_impl(std::move(exec)));
399 [[nodiscard]] std::unique_ptr<ConcreteType>
clone()
const
401 return as<ConcreteType>(this->clone_impl());
404 void convert_to(result_type* result)
const override { *result = *
self(); }
406 void move_to(result_type* result)
override { *result = std::move(*
self()); }
408 [[nodiscard]] std::unique_ptr<ConcreteType> create_default()
const
410 return as<ConcreteType>(this->create_default_impl());
413 [[nodiscard]] std::unique_ptr<ConcreteType> create_default(
414 std::shared_ptr<const Executor> exec)
const
416 return as<ConcreteType>(this->create_default_impl(std::move(exec)));
420 Cloneable* copy_from_impl(
const Cloneable* other)
override
422 self()->
template log<log::Logger::polymorphic_object_copy_started>(
423 self()->get_executor().get(),
424 dynamic_cast<const PolymorphicObject*>(other),
425 dynamic_cast<const PolymorphicObject*>(
this));
426 as<ConvertibleTo<ConcreteType>>(other)->
convert_to(
self());
427 self()->
template log<log::Logger::polymorphic_object_copy_completed>(
428 self()->get_executor().get(),
429 dynamic_cast<const PolymorphicObject*>(other),
430 dynamic_cast<const PolymorphicObject*>(
this));
434 Cloneable* copy_from_impl(std::unique_ptr<Cloneable> other)
override
436 self()->
template log<log::Logger::polymorphic_object_copy_started>(
437 self()->get_executor().get(),
438 dynamic_cast<const PolymorphicObject*>(other.get()),
439 dynamic_cast<const PolymorphicObject*>(
this));
440 as<ConvertibleTo<ConcreteType>>(other.get())->
convert_to(
self());
441 self()->
template log<log::Logger::polymorphic_object_copy_completed>(
442 self()->get_executor().get(),
443 dynamic_cast<const PolymorphicObject*>(other.get()),
444 dynamic_cast<const PolymorphicObject*>(
this));
448 Cloneable* move_from_impl(Cloneable* other)
override
450 self()->
template log<log::Logger::polymorphic_object_move_started>(
451 self()->get_executor().get(),
452 dynamic_cast<const PolymorphicObject*>(other),
453 dynamic_cast<const PolymorphicObject*>(
this));
454 as<ConvertibleTo<ConcreteType>>(other)->
move_to(
self());
455 self()->
template log<log::Logger::polymorphic_object_move_completed>(
456 self()->get_executor().get(),
457 dynamic_cast<const PolymorphicObject*>(other),
458 dynamic_cast<const PolymorphicObject*>(
this));
462 Cloneable* move_from_impl(std::unique_ptr<Cloneable> other)
override
464 self()->
template log<log::Logger::polymorphic_object_move_started>(
465 self()->get_executor().get(),
466 dynamic_cast<const PolymorphicObject*>(other.get()),
467 dynamic_cast<const PolymorphicObject*>(
this));
468 as<ConvertibleTo<ConcreteType>>(other.get())->
move_to(
self());
469 self()->
template log<log::Logger::polymorphic_object_move_completed>(
470 self()->get_executor().get(),
471 dynamic_cast<const PolymorphicObject*>(other.get()),
472 dynamic_cast<const PolymorphicObject*>(
this));
476 [[nodiscard]] std::unique_ptr<Cloneable> clone_impl(
477 std::shared_ptr<const Executor> exec)
const override
479 auto new_op =
self()->create_default(exec);
480 new_op->copy_from(
this);
484 [[nodiscard]] std::unique_ptr<Cloneable> clone_impl()
const override
486 return this->clone_impl(
self()->get_executor());
489 [[nodiscard]] std::unique_ptr<Cloneable> create_default_impl()
492 return this->create_default_impl(
self()->get_executor());
495 [[nodiscard]] std::unique_ptr<Cloneable> create_default_impl(
496 std::shared_ptr<const Executor> exec)
const override
498 if constexpr (std::is_base_of_v<
499 experimental::distributed::DistributedBase,
501 return std::unique_ptr<ConcreteType>(
502 new ConcreteType(std::move(exec),
self()->get_communicator()));
504 return std::unique_ptr<ConcreteType>(
505 new ConcreteType(std::move(exec)));
509 GKO_ENABLE_SELF(ConcreteType);
521 template <
typename ConcreteType>
524 template <
typename... Args>
525 static std::unique_ptr<ConcreteType> create(Args&&... args)
527 return std::unique_ptr<ConcreteType>(
528 new ConcreteType(std::forward<Args>(args)...));
536 #endif // GKO_PUBLIC_CORE_BASE_POLYMORPHIC_OBJECT_HPP_