cuda-api-wrappers
Thin C++-flavored wrappers for the CUDA Runtime API
unique_region.hpp
Go to the documentation of this file.
1 
11 #ifndef CUDA_API_WRAPPERS_UNIQUE_REGION_HPP_
12 #define CUDA_API_WRAPPERS_UNIQUE_REGION_HPP_
13 
14 #include "memory.hpp"
15 #include <cassert>
16 
17 namespace cuda {
18 namespace memory {
19 
40 template<typename Deleter>
41 class unique_region : public region_t {
42 public: // types
43  using parent = region_t;
44  using region_t::pointer;
45  using region_t::const_pointer;
46  using region_t::size_type;
47  using deleter_type = Deleter;
48  // and _no_ element_type!
49 
50 public:
51 
53  constexpr unique_region() noexcept = default;
54 
56  constexpr unique_region(::std::nullptr_t) noexcept : unique_region() { }
57 
59  explicit unique_region(region_t region) noexcept : region_t{region} { }
60 
61  // Note: No constructor which also takes a deleter. We do not hold a deleter
62  // member - unlike unique_ptr's. If we wanted a general-purpose unique region
63  // that's not just GPU allocation-oriented, we might have had one of those.
64 
66  unique_region(unique_region&& other) noexcept : unique_region(other.release()) { }
67  // Disable copy construction
68  unique_region(const unique_region&) = delete;
69 
70  // Note: No conversion from "another type" like with ::std::unique_pointer, since
71  // this class is not variant with the element type; and there's not much sense in
72  // supporting conversion of memory between different deleters (/ allocators).
73 
74  ~unique_region() noexcept
75  {
76  if (data() != nullptr) {
77  get_deleter()(data());
78  }
79  static_cast<region_t&>(*this) = region_t{ nullptr, 0 };
80  }
81 
83  unique_region& operator=(const unique_region&) = delete;
84 
87  {
88  reset(other.release());
89  return *this;
90  }
91 
94  operator=(::std::nullptr_t) noexcept
95  {
96  reset();
97  return *this;
98  }
99 
102 
104 
105  operator const_region_t() const noexcept { return *this; }
106 
108  region_t get() const noexcept { return *this; }
109 
112  deleter_type get_deleter() const noexcept { return deleter_type{}; }
113 
115  explicit operator bool() const noexcept { return data() != nullptr; }
116 
117  // Modifiers.
118 
120  region_t release() noexcept
121  {
122  // TODO: Shouldn't I use move construction for release?
123  region_t released { *this };
124  static_cast<region_t&>(*this) = region_t{ nullptr, 0 };
125  return released;
126  }
127 
135  void reset(region_t region = region_t{})
136  {
137  ::std::swap<region_t>(*this, region);
138  if (region.start() != nullptr) {
139  get_deleter()(region.data());
140  }
141  }
142 
144  void swap(unique_region& other) noexcept
145  {
146  ::std::swap<region_t>(*this, other);
147  }
148 }; // class unique_region
149 
150 namespace device {
151 
154 
155 namespace detail_ {
156 
157 inline unique_region make_unique_region(const context::handle_t context_handle, size_t num_bytes)
158 {
159  CAW_SET_SCOPE_CONTEXT(context_handle);
160  return unique_region{ allocate_in_current_context(num_bytes) };
161 }
162 
163 } // namespace detail_
164 
173 unique_region make_unique_region(const context_t& context, size_t num_bytes);
174 
181 unique_region make_unique_region(const device_t& device, size_t num_bytes);
182 
190 unique_region make_unique_region(size_t num_bytes);
192 
193 } // namespace device
194 
195 
197 inline device::unique_region make_unique_region(const context_t& context, size_t num_elements)
198 {
199  return device::make_unique_region(context, num_elements);
200 }
201 
203 inline device::unique_region make_unique_region(const device_t& device, size_t num_elements)
204 {
205  return device::make_unique_region(device, num_elements);
206 }
207 
208 namespace host {
209 
212 
218 inline unique_region make_unique_region(size_t num_bytes);
219 
220 } // namespace host
221 
222 namespace managed {
223 
226 
227 namespace detail_ {
228 
230  const context::handle_t context_handle,
231  size_t num_bytes,
232  initial_visibility_t initial_visibility = initial_visibility_t::to_all_devices)
233 {
234  CAW_SET_SCOPE_CONTEXT(context_handle);
235  return unique_region { allocate_in_current_context(num_bytes, initial_visibility) };
236 }
237 
238 } // namespace detail_
239 
247  const context_t& context,
248  size_t num_bytes,
249  initial_visibility_t initial_visibility = initial_visibility_t::to_all_devices);
250 
258  const device_t& device,
259  size_t num_bytes,
260  initial_visibility_t initial_visibility = initial_visibility_t::to_all_devices);
261 
269  size_t num_bytes);
270 
271 } // namespace managed
272 
273 } // namespace memory
274 
275 } // namespace cuda
276 
277 #endif // CUDA_API_WRAPPERS_UNIQUE_REGION_HPP_
Wrapper class for a CUDA context.
Definition: context.hpp:244
Definitions and functionality wrapping CUDA APIs.
Definition: array.hpp:22
detail_::region_helper< memory::region_t > region_t
A child class of the generic region_t with some managed-memory-specific functionality.
Definition: memory.hpp:1960
deleter_type get_deleter() const noexcept
Return a deleter of the fixed type (it can&#39;t be a reference - we don&#39;t keep a deleter object) ...
Definition: unique_region.hpp:112
CUcontext handle_t
Raw CUDA driver handle for a context; see {context_t}.
Definition: types.hpp:878
unique_region make_unique_region(const context_t &context, cuda::size_t num_elements)
Allocate a region in device-global memory.
Definition: unique_region.hpp:21
A class for holding a region_t of memory owned "uniquely" by its creator - similar to how ::std::uniq...
Definition: unique_region.hpp:41
constexpr unique_region(::std::nullptr_t) noexcept
Act like the default constructor for nullptr_t&#39;s.
Definition: unique_region.hpp:56
unique_region(region_t region) noexcept
Take ownership of an existing region.
Definition: unique_region.hpp:59
device::unique_region make_unique_region(const context_t &context, size_t num_elements)
See device::make_unique_region(const context_t& context, size_t num_elements)
Definition: unique_region.hpp:197
detail_::region_helper< memory::const_region_t > const_region_t
A child class of the generic const_region_t with some managed-memory-specific functionality.
Definition: memory.hpp:1962
region_t release() noexcept
Release ownership of any stored pointer.
Definition: unique_region.hpp:120
void swap(unique_region &other) noexcept
Exchange the pointer and deleter with another object.
Definition: unique_region.hpp:144
void reset(region_t region=region_t{})
Replace the memory region held by this object.
Definition: unique_region.hpp:135
constexpr unique_region() noexcept=default
Default constructor, creates an empty unique_region which owns nothing.
unique_region & operator=(::std::nullptr_t) noexcept
Reset the unique_region to empty, invoking the deleter if necessary.
Definition: unique_region.hpp:94
unique_region & operator=(const unique_region &)=delete
No copy-assignment - that would break our ownership guarantee.
unique_region(unique_region &&other) noexcept
Move constructor.
Definition: unique_region.hpp:66
unique_region & operator=(unique_region &&other) noexcept
A Move-assignment operator, which takes ownership of the other region.
Definition: unique_region.hpp:86
Wrapper class for a CUDA device.
Definition: device.hpp:135
initial_visibility_t
The choices of which categories CUDA devices must a managed memory region be visible to...
Definition: types.hpp:753
freestanding wrapper functions for working with CUDA&#39;s various kinds of memory spaces, arranged into a relevant namespace hierarchy.