Ginkgo  Generated from tags/v1.0.0^0 branch based on master. Ginkgo version 1.0.0
A numerical linear algebra library targeting many-core architectures
polymorphic_object.hpp
1 /*******************************<GINKGO LICENSE>******************************
2 Copyright (c) 2017-2019, the Ginkgo authors
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 
16 3. Neither the name of the copyright holder nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************<GINKGO LICENSE>*******************************/
32 
33 #ifndef GKO_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
34 #define GKO_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
35 
36 
37 #include <ginkgo/core/base/executor.hpp>
38 #include <ginkgo/core/base/utils.hpp>
39 #include <ginkgo/core/log/logger.hpp>
40 
41 
42 namespace gko {
43 
44 
67 class PolymorphicObject : public log::EnableLogging<PolymorphicObject> {
68 public:
69  virtual ~PolymorphicObject()
70  {
71  this->template log<log::Logger::polymorphic_object_deleted>(exec_.get(),
72  this);
73  }
74 
75  // preserve the executor of the object
76  PolymorphicObject &operator=(const PolymorphicObject &) { return *this; }
77 
88  std::unique_ptr<PolymorphicObject> create_default(
89  std::shared_ptr<const Executor> exec) const
90  {
91  this->template log<log::Logger::polymorphic_object_create_started>(
92  exec_.get(), this);
93  auto created = this->create_default_impl(std::move(exec));
94  this->template log<log::Logger::polymorphic_object_create_completed>(
95  exec_.get(), this, created.get());
96  return created;
97  }
98 
107  std::unique_ptr<PolymorphicObject> create_default() const
108  {
109  return this->create_default(exec_);
110  }
111 
122  std::unique_ptr<PolymorphicObject> clone(
123  std::shared_ptr<const Executor> exec) const
124  {
125  auto new_op = this->create_default(exec);
126  new_op->copy_from(this);
127  return new_op;
128  }
129 
138  std::unique_ptr<PolymorphicObject> clone() const
139  {
140  return this->clone(exec_);
141  }
142 
155  {
156  this->template log<log::Logger::polymorphic_object_copy_started>(
157  exec_.get(), other, this);
158  auto copied = this->copy_from_impl(other);
159  this->template log<log::Logger::polymorphic_object_copy_completed>(
160  exec_.get(), other, this);
161  return copied;
162  }
163 
175  PolymorphicObject *copy_from(std::unique_ptr<PolymorphicObject> other)
176  {
177  this->template log<log::Logger::polymorphic_object_copy_started>(
178  exec_.get(), other.get(), this);
179  auto copied = this->copy_from_impl(std::move(other));
180  this->template log<log::Logger::polymorphic_object_copy_completed>(
181  exec_.get(), other.get(), this);
182  return copied;
183  }
184 
194  PolymorphicObject *clear() { return this->clear_impl(); }
195 
201  std::shared_ptr<const Executor> get_executor() const noexcept
202  {
203  return exec_;
204  }
205 
206 protected:
207  // This method is defined as protected since a polymorphic object should not
208  // be created using their constructor directly, but by creating an
209  // std::unique_ptr to it. Defining the constructor as protected keeps these
210  // access rights when inheriting the constructor.
216  explicit PolymorphicObject(std::shared_ptr<const Executor> exec)
217  : exec_{std::move(exec)}
218  {}
219 
228  virtual std::unique_ptr<PolymorphicObject> create_default_impl(
229  std::shared_ptr<const Executor> exec) const = 0;
230 
239  virtual PolymorphicObject *copy_from_impl(
240  const PolymorphicObject *other) = 0;
241 
250  virtual PolymorphicObject *copy_from_impl(
251  std::unique_ptr<PolymorphicObject> other) = 0;
252 
259  virtual PolymorphicObject *clear_impl() = 0;
260 
261 private:
262  std::shared_ptr<const Executor> exec_;
263 };
264 
265 
284 template <typename AbstactObject, typename PolymorphicBase = PolymorphicObject>
285 class EnableAbstractPolymorphicObject : public PolymorphicBase {
286 public:
287  using PolymorphicBase::PolymorphicBase;
288 
289  std::unique_ptr<AbstactObject> create_default(
290  std::shared_ptr<const Executor> exec) const
291  {
292  return std::unique_ptr<AbstactObject>{static_cast<AbstactObject *>(
293  this->create_default_impl(std::move(exec)).release())};
294  }
295 
296  std::unique_ptr<AbstactObject> create_default() const
297  {
298  return this->create_default(this->get_executor());
299  }
300 
301  std::unique_ptr<AbstactObject> clone(
302  std::shared_ptr<const Executor> exec) const
303  {
304  auto new_op = this->create_default(exec);
305  new_op->copy_from(this);
306  return new_op;
307  }
308 
309  std::unique_ptr<AbstactObject> clone() const
310  {
311  return this->clone(this->get_executor());
312  }
313 
314  AbstactObject *copy_from(const PolymorphicObject *other)
315  {
316  return static_cast<AbstactObject *>(this->copy_from_impl(other));
317  }
318 
319  AbstactObject *copy_from(std::unique_ptr<PolymorphicObject> other)
320  {
321  return static_cast<AbstactObject *>(
322  this->copy_from_impl(std::move(other)));
323  }
324 
325  AbstactObject *clear()
326  {
327  return static_cast<AbstactObject *>(this->clear_impl());
328  }
329 };
330 
331 
340 #define GKO_ENABLE_SELF(_type) \
341  _type *self() noexcept { return static_cast<_type *>(this); } \
342  \
343  const _type *self() const noexcept \
344  { \
345  return static_cast<const _type *>(this); \
346  }
347 
348 
379 template <typename ResultType>
381 public:
382  using result_type = ResultType;
383 
384  virtual ~ConvertibleTo() = default;
385 
391  virtual void convert_to(result_type *result) const = 0;
392 
407  virtual void move_to(result_type *result) = 0;
408 };
409 
410 
411 namespace detail {
412 
413 
414 template <typename R, typename T>
415 std::unique_ptr<R, std::function<void(R *)>> copy_and_convert_to_impl(
416  std::shared_ptr<const Executor> exec, T *obj)
417 {
418  auto obj_as_r = dynamic_cast<R *>(obj);
419  if (obj_as_r != nullptr && obj->get_executor() == exec) {
420  return {obj_as_r, [](R *) {}};
421  } else {
422  auto copy = R::create(exec);
423  as<ConvertibleTo<xstd::decay_t<R>>>(obj)->convert_to(lend(copy));
424  return {copy.release(), std::default_delete<R>{}};
425  }
426 }
427 
428 
429 } // namespace detail
430 
431 
448 template <typename R, typename T>
449 std::unique_ptr<R, std::function<void(R *)>> copy_and_convert_to(
450  std::shared_ptr<const Executor> exec, T *obj)
451 {
452  return detail::copy_and_convert_to_impl<R>(std::move(exec), obj);
453 }
454 
455 
462 template <typename R, typename T>
463 std::unique_ptr<const R, std::function<void(const R *)>> copy_and_convert_to(
464  std::shared_ptr<const Executor> exec, const T *obj)
465 {
466  return detail::copy_and_convert_to_impl<const R>(std::move(exec), obj);
467 }
468 
469 
504 template <typename ConcreteObject, typename PolymorphicBase = PolymorphicObject>
506  : public EnableAbstractPolymorphicObject<ConcreteObject, PolymorphicBase> {
507 protected:
509  ConcreteObject, PolymorphicBase>::EnableAbstractPolymorphicObject;
510 
511  std::unique_ptr<PolymorphicObject> create_default_impl(
512  std::shared_ptr<const Executor> exec) const override
513  {
514  return std::unique_ptr<ConcreteObject>{new ConcreteObject(exec)};
515  }
516 
517  PolymorphicObject *copy_from_impl(const PolymorphicObject *other) override
518  {
519  as<ConvertibleTo<ConcreteObject>>(other)->convert_to(self());
520  return this;
521  }
522 
523  PolymorphicObject *copy_from_impl(
524  std::unique_ptr<PolymorphicObject> other) override
525  {
526  as<ConvertibleTo<ConcreteObject>>(other.get())->move_to(self());
527  return this;
528  }
529 
530  PolymorphicObject *clear_impl() override
531  {
532  *self() = ConcreteObject{this->get_executor()};
533  return this;
534  }
535 
536 private:
537  GKO_ENABLE_SELF(ConcreteObject);
538 };
539 
540 
553 template <typename ConcreteType, typename ResultType = ConcreteType>
554 class EnablePolymorphicAssignment : public ConvertibleTo<ResultType> {
555 public:
556  using result_type = ResultType;
557 
558  void convert_to(result_type *result) const override { *result = *self(); }
559 
560  void move_to(result_type *result) override { *result = std::move(*self()); }
561 
562 private:
563  GKO_ENABLE_SELF(ConcreteType);
564 };
565 
566 
575 template <typename ConcreteType>
577 public:
578  template <typename... Args>
579  static std::unique_ptr<ConcreteType> create(Args &&... args)
580  {
581  return std::unique_ptr<ConcreteType>(
582  new ConcreteType(std::forward<Args>(args)...));
583  }
584 };
585 
586 
587 } // namespace gko
588 
589 
590 #endif // GKO_CORE_BASE_POLYMORPHIC_OBJECT_HPP_
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:285
std::unique_ptr< PolymorphicObject > clone(std::shared_ptr< const Executor > exec) const
Creates a clone of the object.
Definition: polymorphic_object.hpp:122
This mixin implements a static create() method on ConcreteType that dynamically allocates the memory...
Definition: polymorphic_object.hpp:576
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition: polymorphic_object.hpp:380
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:505
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:88
PolymorphicObject * copy_from(std::unique_ptr< PolymorphicObject > other)
Moves another object into this object.
Definition: polymorphic_object.hpp:175
PolymorphicObject * clear()
Transforms the object into its default state.
Definition: polymorphic_object.hpp:194
std::unique_ptr< PolymorphicObject > create_default() const
Creates a new "default" object of the same dynamic type as this object.
Definition: polymorphic_object.hpp:107
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:449
The Ginkgo namespace.
Definition: abstract_factory.hpp:45
PolymorphicObject * copy_from(const PolymorphicObject *other)
Copies another object into this object.
Definition: polymorphic_object.hpp:154
A PolymorphicObject is the abstract base for all "heavy" objects in Ginkgo that behave polymorphicall...
Definition: polymorphic_object.hpp:67
std::unique_ptr< PolymorphicObject > clone() const
Creates a clone of the object.
Definition: polymorphic_object.hpp:138
EnableLogging is a mixin which should be inherited by any class which wants to enable logging...
Definition: logger.hpp:521
void convert_to(result_type *result) const override
Converts the implementer to an object of type result_type.
Definition: polymorphic_object.hpp:558
void move_to(result_type *result) override
Converts the implementer to an object of type result_type by moving data from this object...
Definition: polymorphic_object.hpp:560
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:201
std::enable_if< detail::have_ownership< Pointer >), detail::pointee< Pointer > * >::type lend(const Pointer &p)
Returns a non-owning (plain) pointer to the object pointed to by p.
Definition: utils.hpp:249
This mixin is used to enable a default PolymorphicObject::copy_from() implementation for objects that...
Definition: polymorphic_object.hpp:554