Ginkgo  Generated from pipelines/1330831941 branch based on master. Ginkgo version 1.8.0
A numerical linear algebra library targeting many-core architectures
utils_helper.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
6 #define GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
7 
8 
9 #include <functional>
10 #include <memory>
11 #include <type_traits>
12 
13 
14 #include <ginkgo/core/base/exception.hpp>
15 #include <ginkgo/core/base/name_demangling.hpp>
16 #include <ginkgo/core/base/std_extensions.hpp>
17 #include <ginkgo/core/base/types.hpp>
18 
19 
20 #ifndef NDEBUG
21 #include <cstdio>
22 #endif // NDEBUG
23 
24 
25 namespace gko {
26 
27 
28 class Executor;
29 
30 
42 template <typename T>
43 class ptr_param {
44 public:
46  ptr_param(T* ptr) : ptr_{ptr} {}
47 
49  template <typename U,
50  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
51  ptr_param(const std::shared_ptr<U>& ptr) : ptr_param{ptr.get()}
52  {}
53 
55  template <typename U, typename Deleter,
56  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
57  ptr_param(const std::unique_ptr<U, Deleter>& ptr) : ptr_param{ptr.get()}
58  {}
59 
61  template <typename U,
62  std::enable_if_t<std::is_base_of<T, U>::value>* = nullptr>
63  ptr_param(const ptr_param<U>& ptr) : ptr_param{ptr.get()}
64  {}
65 
66  ptr_param(const ptr_param&) = default;
67 
68  ptr_param(ptr_param&&) = default;
69 
71  T& operator*() const { return *ptr_; }
72 
74  T* operator->() const { return ptr_; }
75 
77  T* get() const { return ptr_; }
78 
80  explicit operator bool() const { return ptr_; }
81 
82  ptr_param& operator=(const ptr_param&) = delete;
83 
84  ptr_param& operator=(ptr_param&&) = delete;
85 
86 private:
87  T* ptr_;
88 };
89 
90 
91 namespace detail {
92 
93 
94 template <typename T>
95 using pointee =
96  std::remove_reference_t<decltype(*std::declval<std::decay_t<T>>())>;
97 
98 
99 template <typename T, typename = void>
100 struct is_clonable_impl : std::false_type {};
101 
102 template <typename T>
103 struct is_clonable_impl<T, xstd::void_t<decltype(std::declval<T>().clone())>>
104  : std::true_type {};
105 
106 template <typename T>
107 constexpr bool is_clonable()
108 {
109  return is_clonable_impl<std::decay_t<T>>::value;
110 }
111 
112 
113 template <typename T, typename = void>
114 struct is_clonable_to_impl : std::false_type {};
115 
116 template <typename T>
117 struct is_clonable_to_impl<
118  T, xstd::void_t<decltype(std::declval<T>().clone(
119  std::declval<std::shared_ptr<const Executor>>()))>>
120  : std::true_type {};
121 
122 template <typename T>
123 constexpr bool is_clonable_to()
124 {
125  return is_clonable_to_impl<std::decay_t<T>>::value;
126 }
127 
128 
129 template <typename T>
130 struct have_ownership_impl : std::false_type {};
131 
132 template <typename T, typename Deleter>
133 struct have_ownership_impl<std::unique_ptr<T, Deleter>> : std::true_type {};
134 
135 template <typename T>
136 struct have_ownership_impl<std::shared_ptr<T>> : std::true_type {};
137 
138 template <typename T>
139 using have_ownership_s = have_ownership_impl<std::decay_t<T>>;
140 
141 template <typename T>
142 constexpr bool have_ownership()
143 {
144  return have_ownership_s<T>::value;
145 }
146 
147 
148 template <typename Pointer>
149 using cloned_type =
150  std::unique_ptr<typename std::remove_cv<pointee<Pointer>>::type>;
151 
152 
153 template <typename Pointer>
154 using shared_type = std::shared_ptr<pointee<Pointer>>;
155 
156 
157 } // namespace detail
158 
159 
174 template <typename Pointer>
175 inline detail::cloned_type<Pointer> clone(const Pointer& p)
176 {
177  static_assert(detail::is_clonable<detail::pointee<Pointer>>(),
178  "Object is not clonable");
179  return detail::cloned_type<Pointer>(
180  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
181  p->clone().release()));
182 }
183 
184 
200 template <typename Pointer>
201 inline detail::cloned_type<Pointer> clone(std::shared_ptr<const Executor> exec,
202  const Pointer& p)
203 {
204  static_assert(detail::is_clonable_to<detail::pointee<Pointer>>(),
205  "Object is not clonable");
206  return detail::cloned_type<Pointer>(
207  static_cast<typename std::remove_cv<detail::pointee<Pointer>>::type*>(
208  p->clone(std::move(exec)).release()));
209 }
210 
211 
225 template <typename OwningPointer>
226 inline detail::shared_type<OwningPointer> share(OwningPointer&& p)
227 {
228  static_assert(detail::have_ownership<OwningPointer>(),
229  "OwningPointer does not have ownership of the object");
230  static_assert(std::is_rvalue_reference<decltype(p)>::value,
231  "p must be an rvalue for this function to work");
232  return detail::shared_type<OwningPointer>(std::move(p));
233 }
234 
235 
248 template <typename OwningPointer>
249 inline typename std::remove_reference<OwningPointer>::type&& give(
250  OwningPointer&& p)
251 {
252  static_assert(detail::have_ownership<OwningPointer>(),
253  "OwningPointer does not have ownership of the object");
254  return std::move(p);
255 }
256 
257 
268 template <typename Pointer>
269 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
270 inline typename std::enable_if<detail::have_ownership_s<Pointer>::value,
271  detail::pointee<Pointer>*>::type
272  lend(const Pointer& p)
273 {
274  return p.get();
275 }
276 
287 template <typename Pointer>
288 GKO_DEPRECATED("no longer necessary, just pass the object without lend")
289 inline typename std::enable_if<!detail::have_ownership_s<Pointer>::value,
290  detail::pointee<Pointer>*>::type
291  lend(const Pointer& p)
292 {
293  return p;
294 }
295 
296 
308 template <typename T, typename U>
309 inline std::decay_t<T>* as(U* obj)
310 {
311  if (auto p = dynamic_cast<std::decay_t<T>*>(obj)) {
312  return p;
313  } else {
314  throw NotSupported(__FILE__, __LINE__,
315  std::string{"gko::as<"} +
316  name_demangling::get_type_name(typeid(T)) + ">",
317  name_demangling::get_type_name(typeid(*obj)));
318  }
319 }
320 
334 template <typename T, typename U>
335 inline const std::decay_t<T>* as(const U* obj)
336 {
337  if (auto p = dynamic_cast<const std::decay_t<T>*>(obj)) {
338  return p;
339  } else {
340  throw NotSupported(__FILE__, __LINE__,
341  std::string{"gko::as<"} +
342  name_demangling::get_type_name(typeid(T)) + ">",
343  name_demangling::get_type_name(typeid(*obj)));
344  }
345 }
346 
347 
359 template <typename T, typename U>
360 inline std::decay_t<T>* as(ptr_param<U> obj)
361 {
362  return as<T>(obj.get());
363 }
364 
378 template <typename T, typename U>
379 inline const std::decay_t<T>* as(ptr_param<const U> obj)
380 {
381  return as<T>(obj.get());
382 }
383 
384 
397 template <typename T, typename U>
398 inline std::unique_ptr<std::decay_t<T>> as(std::unique_ptr<U>&& obj)
399 {
400  if (auto p = dynamic_cast<std::decay_t<T>*>(obj.get())) {
401  obj.release();
402  return std::unique_ptr<std::decay_t<T>>{p};
403  } else {
404  throw NotSupported(__FILE__, __LINE__, __func__,
405  name_demangling::get_type_name(typeid(*obj)));
406  }
407 }
408 
409 
421 template <typename T, typename U>
422 inline std::shared_ptr<std::decay_t<T>> as(std::shared_ptr<U> obj)
423 {
424  auto ptr = std::dynamic_pointer_cast<std::decay_t<T>>(obj);
425  if (ptr) {
426  return ptr;
427  } else {
428  throw NotSupported(__FILE__, __LINE__, __func__,
429  name_demangling::get_type_name(typeid(*obj)));
430  }
431 }
432 
433 
447 template <typename T, typename U>
448 inline std::shared_ptr<const std::decay_t<T>> as(std::shared_ptr<const U> obj)
449 {
450  auto ptr = std::dynamic_pointer_cast<const std::decay_t<T>>(obj);
451  if (ptr) {
452  return ptr;
453  } else {
454  throw NotSupported(__FILE__, __LINE__, __func__,
455  name_demangling::get_type_name(typeid(*obj)));
456  }
457 }
458 
459 
466 template <typename T>
468 public:
469  using pointer = T*;
470 
476  void operator()(pointer) const noexcept {}
477 };
478 
479 // a specialization for arrays
480 template <typename T>
481 class null_deleter<T[]> {
482 public:
483  using pointer = T[];
484 
485  void operator()(pointer) const noexcept {}
486 };
487 
488 
489 } // namespace gko
490 
491 
492 #endif // GKO_PUBLIC_CORE_BASE_UTILS_HELPER_HPP_
gko::ptr_param::ptr_param
ptr_param(const std::unique_ptr< U, Deleter > &ptr)
Initializes the ptr_param from a unique_ptr.
Definition: utils_helper.hpp:57
gko::give
std::remove_reference< OwningPointer >::type && give(OwningPointer &&p)
Marks that the object pointed to by p can be given to the callee.
Definition: utils_helper.hpp:249
gko::ptr_param::ptr_param
ptr_param(const ptr_param< U > &ptr)
Initializes the ptr_param from a ptr_param of a derived type.
Definition: utils_helper.hpp:63
gko::ptr_param::operator->
T * operator->() const
Definition: utils_helper.hpp:74
gko::null_deleter
This is a deleter that does not delete the object.
Definition: utils_helper.hpp:467
gko::ptr_param::operator*
T & operator*() const
Definition: utils_helper.hpp:71
gko::null_deleter::operator()
void operator()(pointer) const noexcept
Deletes the object.
Definition: utils_helper.hpp:476
gko::ptr_param::get
T * get() const
Definition: utils_helper.hpp:77
gko::ptr_param::ptr_param
ptr_param(const std::shared_ptr< U > &ptr)
Initializes the ptr_param from a shared_ptr.
Definition: utils_helper.hpp:51
gko::NotSupported
NotSupported is thrown in case it is not possible to perform the requested operation on the given obj...
Definition: exception.hpp:128
gko::clone
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition: utils_helper.hpp:175
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20
gko::as
std::decay_t< T > * as(U *obj)
Performs polymorphic type conversion.
Definition: utils_helper.hpp:309
gko::ptr_param
This class is used for function parameters in the place of raw pointers.
Definition: utils_helper.hpp:43
gko::share
detail::shared_type< OwningPointer > share(OwningPointer &&p)
Marks the object pointed to by p as shared.
Definition: utils_helper.hpp:226
gko::lend
std::enable_if< detail::have_ownership_s< Pointer >::value, detail::pointee< Pointer > * >::type lend(const Pointer &p)
Returns a non-owning (plain) pointer to the object pointed to by p.
Definition: utils_helper.hpp:272
gko::ptr_param::ptr_param
ptr_param(T *ptr)
Initializes the ptr_param from a raw pointer.
Definition: utils_helper.hpp:46