Ginkgo Generated from branch based on master. Ginkgo version 1.7.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
temporary_clone.hpp
1/*******************************<GINKGO LICENSE>******************************
2Copyright (c) 2017-2023, the Ginkgo authors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither the name of the copyright holder nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31******************************<GINKGO LICENSE>*******************************/
32
33#ifndef GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
34#define GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
35
36
37#include <functional>
38#include <memory>
39#include <type_traits>
40
41
42#include <ginkgo/core/base/exception_helpers.hpp>
43#include <ginkgo/core/base/executor.hpp>
44#include <ginkgo/core/base/utils_helper.hpp>
45
46
47namespace gko {
48namespace detail {
49
50
65template <typename T>
66class copy_back_deleter {
67public:
68 using pointer = T*;
69
76 copy_back_deleter(pointer original) : original_{original} {}
77
83 void operator()(pointer ptr) const
84 {
85 original_->copy_from(ptr);
86 delete ptr;
87 }
88
89private:
90 pointer original_;
91};
92
93// specialization for constant objects, no need to copy back something that
94// cannot change
95template <typename T>
96class copy_back_deleter<const T> {
97public:
98 using pointer = const T*;
99 copy_back_deleter(pointer original) : original_{original} {}
100
101 void operator()(pointer ptr) const { delete ptr; }
102
103private:
104 pointer original_;
105};
106
107
108template <typename T>
109struct temporary_clone_helper {
110 static std::unique_ptr<T> create(std::shared_ptr<const Executor> exec,
111 T* ptr, bool)
112 {
113 return gko::clone(std::move(exec), ptr);
114 }
115};
116
117
129template <typename T>
130class temporary_clone {
131public:
132 using value_type = T;
133 using pointer = T*;
134
143 explicit temporary_clone(std::shared_ptr<const Executor> exec,
144 ptr_param<T> ptr, bool copy_data = true)
145 {
146 if (ptr->get_executor()->memory_accessible(exec)) {
147 // just use the object we already have
148 handle_ = handle_type(ptr.get(), null_deleter<T>());
149 } else {
150 // clone the object to the new executor and make sure it's copied
151 // back before we delete it
152 handle_ = handle_type(temporary_clone_helper<T>::create(
153 std::move(exec), ptr.get(), copy_data)
154 .release(),
155 copy_back_deleter<T>(ptr.get()));
156 }
157 }
158
164 T* get() const { return handle_.get(); }
165
171 T* operator->() const { return handle_.get(); }
172
178 T& operator*() const { return *handle_; }
179
180private:
181 // std::function deleter allows to decide the (type of) deleter at runtime
182 using handle_type = std::unique_ptr<T, std::function<void(T*)>>;
183
184 handle_type handle_;
185};
186
187
188} // namespace detail
189
190
191template <typename T>
192struct err {};
193
206template <typename Ptr>
207detail::temporary_clone<detail::pointee<Ptr>> make_temporary_clone(
208 std::shared_ptr<const Executor> exec, Ptr&& ptr)
209{
210 using T = detail::pointee<Ptr>;
211 return detail::temporary_clone<T>(std::move(exec), std::forward<Ptr>(ptr));
212}
213
214
229template <typename Ptr>
230detail::temporary_clone<detail::pointee<Ptr>> make_temporary_output_clone(
231 std::shared_ptr<const Executor> exec, Ptr&& ptr)
232{
233 using T = detail::pointee<Ptr>;
234 static_assert(
235 !std::is_const<T>::value,
236 "make_temporary_output_clone should only be used on non-const objects");
237 return detail::temporary_clone<T>(std::move(exec), std::forward<Ptr>(ptr),
238 false);
239}
240
241
242} // namespace gko
243
244
245#endif // GKO_PUBLIC_CORE_BASE_TEMPORARY_CLONE_HPP_
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
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:230
detail::cloned_type< Pointer > clone(const Pointer &p)
Creates a unique clone of the object pointed to by p.
Definition utils_helper.hpp:203
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:207
Definition temporary_clone.hpp:192