Ginkgo  Generated from pipelines/1556235455 branch based on develop. Ginkgo version 1.9.0
A numerical linear algebra library targeting many-core architectures
temporary_clone.hpp
1 // SPDX-FileCopyrightText: 2017 - 2024 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
6 #define GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
7 
8 
9 #include <functional>
10 #include <memory>
11 #include <type_traits>
12 
13 #include <ginkgo/core/base/exception_helpers.hpp>
14 #include <ginkgo/core/base/executor.hpp>
15 #include <ginkgo/core/base/utils_helper.hpp>
16 
17 
18 namespace gko {
19 namespace detail {
20 
21 
36 template <typename T>
37 class copy_back_deleter {
38 public:
39  using pointer = T*;
40 
47  copy_back_deleter(pointer original) : original_{original} {}
48 
54  void operator()(pointer ptr) const
55  {
56  original_->copy_from(ptr);
57  delete ptr;
58  }
59 
60 private:
61  pointer original_;
62 };
63 
64 // specialization for constant objects, no need to copy back something that
65 // cannot change
66 template <typename T>
67 class copy_back_deleter<const T> {
68 public:
69  using pointer = const T*;
70  copy_back_deleter(pointer original) : original_{original} {}
71 
72  void operator()(pointer ptr) const { delete ptr; }
73 
74 private:
75  pointer original_;
76 };
77 
78 
79 // specialization for copy back via assignment
80 template <typename T>
81 class copy_back_deleter_from_assignment {
82 public:
83  using pointer = T*;
84 
91  copy_back_deleter_from_assignment(pointer original) : original_{original} {}
92 
98  void operator()(pointer ptr) const
99  {
100  *original_ = *ptr;
101  delete ptr;
102  }
103 
104 private:
105  pointer original_;
106 };
107 
108 
109 template <typename T>
110 struct temporary_clone_helper {
111  static std::unique_ptr<T> create(std::shared_ptr<const Executor> exec,
112  T* ptr, bool)
113  {
114  return gko::clone(std::move(exec), ptr);
115  }
116 };
117 
118 
130 template <typename T>
131 class temporary_clone {
132 public:
133  using value_type = T;
134  using pointer = T*;
135 
144  explicit temporary_clone(std::shared_ptr<const Executor> exec,
145  ptr_param<T> ptr, bool copy_data = true)
146  {
147  if (ptr->get_executor()->memory_accessible(exec)) {
148  // just use the object we already have
149  handle_ = handle_type(ptr.get(), null_deleter<T>());
150  } else {
151  // clone the object to the new executor and make sure it's copied
152  // back before we delete it
153  handle_ = handle_type(temporary_clone_helper<T>::create(
154  std::move(exec), ptr.get(), copy_data)
155  .release(),
156  copy_back_deleter<T>(ptr.get()));
157  }
158  }
159 
165  T* get() const { return handle_.get(); }
166 
172  T* operator->() const { return handle_.get(); }
173 
179  T& operator*() const { return *handle_; }
180 
181 private:
182  // std::function deleter allows to decide the (type of) deleter at runtime
183  using handle_type = std::unique_ptr<T, std::function<void(T*)>>;
184 
185  handle_type handle_;
186 };
187 
188 
189 } // namespace detail
190 
191 
192 template <typename T>
193 struct err {};
194 
207 template <typename Ptr>
208 detail::temporary_clone<detail::pointee<Ptr>> make_temporary_clone(
209  std::shared_ptr<const Executor> exec, Ptr&& ptr)
210 {
211  using T = detail::pointee<Ptr>;
212  return detail::temporary_clone<T>(std::move(exec), std::forward<Ptr>(ptr));
213 }
214 
215 
230 template <typename Ptr>
231 detail::temporary_clone<detail::pointee<Ptr>> make_temporary_output_clone(
232  std::shared_ptr<const Executor> exec, Ptr&& ptr)
233 {
234  using T = detail::pointee<Ptr>;
235  static_assert(
236  !std::is_const<T>::value,
237  "make_temporary_output_clone should only be used on non-const objects");
238  return detail::temporary_clone<T>(std::move(exec), std::forward<Ptr>(ptr),
239  false);
240 }
241 
242 
243 } // namespace gko
244 
245 
246 #endif // GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
gko::make_temporary_output_clone
detail::temporary_clone< detail::pointee< Ptr > > make_temporary_output_clone(std::shared_ptr< const Executor > exec, Ptr &&ptr)
Creates a uninitialized temporary_clone that will be copied back to the input afterwards.
Definition: temporary_clone.hpp:231
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:173
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20
gko::err
Definition: temporary_clone.hpp:193
gko::make_temporary_clone
detail::temporary_clone< detail::pointee< Ptr > > make_temporary_clone(std::shared_ptr< const Executor > exec, Ptr &&ptr)
Creates a temporary_clone.
Definition: temporary_clone.hpp:208