DPC++ Runtime
Runtime libraries for oneAPI DPC++
weak_object.hpp
Go to the documentation of this file.
1 //==-------------- weak_object.hpp --- SYCL weak objects -------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <sycl/access/access.hpp> // for target, mode
12 #include <sycl/accessor.hpp> // for accessor
13 #include <sycl/buffer.hpp> // for buffer
14 #include <sycl/detail/impl_utils.hpp> // for createSyc...
15 #include <sycl/detail/memcpy.hpp> // for detail
16 #include <sycl/exception.hpp> // for make_erro...
18 #include <sycl/ext/oneapi/weak_object_base.hpp> // for weak_obje...
19 #include <sycl/range.hpp> // for range
20 #include <sycl/stream.hpp> // for stream
21 
22 #include <memory> // for shared_ptr
23 #include <optional> // for optional
24 #include <stddef.h> // for size_t
25 
26 namespace sycl {
27 inline namespace _V1 {
28 namespace ext::oneapi {
29 namespace detail {
30 // Import from detail:: into ext::oneapi::detail:: to improve readability later
31 using namespace ::sycl::detail;
32 
33 // Helper for creating ranges for empty weak_objects.
34 template <int Dims> static range<Dims> createDummyRange() {
35  static_assert(Dims >= 0 && Dims < 4, "Invalid dimensionality in range.");
36  if constexpr (Dims == 0)
37  return {};
38  if constexpr (Dims == 1)
39  return {1};
40  else if constexpr (Dims == 2)
41  return {1, 1};
42  else
43  return {1, 1, 1};
44 }
45 } // namespace detail
46 
47 // The weak_object class.
48 // Since we use std::shared_ptr to implementations as a way to handle common
49 // reference semantics in SYCL classes, the implementation of the weak_object
50 // class holds a weak_ptr to the implementations. The weak_ptr is in the
51 // weak_object_base class.
52 template <typename SYCLObjT>
53 class weak_object : public detail::weak_object_base<SYCLObjT> {
54 public:
56 
57  constexpr weak_object() noexcept = default;
58  weak_object(const SYCLObjT &SYCLObj) noexcept
59  : detail::weak_object_base<SYCLObjT>(SYCLObj) {}
60  weak_object(const weak_object &Other) noexcept = default;
61  weak_object(weak_object &&Other) noexcept = default;
62 
63  weak_object &operator=(const SYCLObjT &SYCLObj) noexcept {
64  // Create weak_ptr from the shared_ptr to SYCLObj's implementation object.
65  this->MObjWeakPtr =
67  return *this;
68  }
69  weak_object &operator=(const weak_object &Other) noexcept = default;
71 
72 #ifndef __SYCL_DEVICE_ONLY__
73  std::optional<SYCLObjT> try_lock() const noexcept {
74  auto MObjImplPtr = this->MObjWeakPtr.lock();
75  if (!MObjImplPtr)
76  return std::nullopt;
77  return sycl::detail::createSyclObjFromImpl<SYCLObjT>(MObjImplPtr);
78  }
79  SYCLObjT lock() const {
80  std::optional<SYCLObjT> OptionalObj = try_lock();
81  if (!OptionalObj)
82  throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
83  "Referenced object has expired.");
84  return *OptionalObj;
85  }
86 #else
87  // On device calls to these functions are disallowed, so declare them but
88  // don't define them to avoid compilation failures.
89  std::optional<SYCLObjT> try_lock() const noexcept;
90  SYCLObjT lock() const;
91 #endif // __SYCL_DEVICE_ONLY__
92 };
93 
94 // Specialization of weak_object for buffer as it needs additional members
95 // to reconstruct the original buffer.
96 template <typename T, int Dimensions, typename AllocatorT>
97 class weak_object<buffer<T, Dimensions, AllocatorT>>
98  : public detail::weak_object_base<buffer<T, Dimensions, AllocatorT>> {
99 private:
101 
102 public:
103  using object_type =
105 
106  constexpr weak_object() noexcept
107  : detail::weak_object_base<buffer_type>(),
108  MRange{detail::createDummyRange<Dimensions>()}, MOffsetInBytes{0},
109  MIsSubBuffer{false} {}
111  : detail::weak_object_base<buffer_type>(SYCLObj), MRange{SYCLObj.Range},
112  MOffsetInBytes{SYCLObj.OffsetInBytes},
113  MIsSubBuffer{SYCLObj.IsSubBuffer} {}
114  weak_object(const weak_object &Other) noexcept = default;
115  weak_object(weak_object &&Other) noexcept = default;
116 
118  // Create weak_ptr from the shared_ptr to SYCLObj's implementation object.
121  this->MRange = SYCLObj.Range;
122  this->MOffsetInBytes = SYCLObj.OffsetInBytes;
123  this->MIsSubBuffer = SYCLObj.IsSubBuffer;
124  return *this;
125  }
126  weak_object &operator=(const weak_object &Other) noexcept = default;
128 
129  void swap(weak_object &Other) noexcept {
130  this->MObjWeakPtr.swap(Other.MObjWeakPtr);
131  std::swap(MRange, Other.MRange);
132  std::swap(MOffsetInBytes, Other.MOffsetInBytes);
133  std::swap(MIsSubBuffer, Other.MIsSubBuffer);
134  }
135 
136 #ifndef __SYCL_DEVICE_ONLY__
137  std::optional<buffer_type> try_lock() const noexcept {
138  auto MObjImplPtr = this->MObjWeakPtr.lock();
139  if (!MObjImplPtr)
140  return std::nullopt;
141  // To reconstruct the buffer we use the reinterpret constructor.
142  return buffer_type{MObjImplPtr, MRange, MOffsetInBytes, MIsSubBuffer};
143  }
144  buffer_type lock() const {
145  std::optional<buffer_type> OptionalObj = try_lock();
146  if (!OptionalObj)
147  throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
148  "Referenced object has expired.");
149  return *OptionalObj;
150  }
151 #else
152  // On device calls to these functions are disallowed, so declare them but
153  // don't define them to avoid compilation failures.
154  std::optional<buffer_type> try_lock() const noexcept;
155  buffer_type lock() const;
156 #endif // __SYCL_DEVICE_ONLY__
157 
158 private:
159  // Additional members required for recreating buffers.
160  range<Dimensions> MRange;
161  size_t MOffsetInBytes;
162  bool MIsSubBuffer;
163 };
164 
165 // Specialization of weak_object for stream as it needs additional members
166 // to reconstruct the original stream.
167 template <>
168 class weak_object<stream> : public detail::weak_object_base<stream> {
169 public:
171 
172  constexpr weak_object() noexcept : detail::weak_object_base<stream>() {}
173  weak_object(const stream &SYCLObj) noexcept
175  MWeakGlobalBuf{SYCLObj.GlobalBuf},
176  MWeakGlobalOffset{SYCLObj.GlobalOffset},
177  MWeakGlobalFlushBuf{SYCLObj.GlobalFlushBuf} {}
178  weak_object(const weak_object &Other) noexcept = default;
179  weak_object(weak_object &&Other) noexcept = default;
180 
181  weak_object &operator=(const stream &SYCLObj) noexcept {
182  // Create weak_ptr from the shared_ptr to SYCLObj's implementation object.
184  MWeakGlobalBuf = SYCLObj.GlobalBuf;
185  MWeakGlobalOffset = SYCLObj.GlobalOffset;
186  MWeakGlobalFlushBuf = SYCLObj.GlobalFlushBuf;
187  return *this;
188  }
189  weak_object &operator=(const weak_object &Other) noexcept = default;
191 
192  void swap(weak_object &Other) noexcept {
193  this->MObjWeakPtr.swap(Other.MObjWeakPtr);
194  MWeakGlobalBuf.swap(Other.MWeakGlobalBuf);
195  MWeakGlobalOffset.swap(Other.MWeakGlobalOffset);
196  MWeakGlobalFlushBuf.swap(Other.MWeakGlobalFlushBuf);
197  }
198 
199  void reset() noexcept {
200  this->MObjWeakPtr.reset();
201  MWeakGlobalBuf.reset();
202  MWeakGlobalOffset.reset();
203  MWeakGlobalFlushBuf.reset();
204  }
205 
206 #ifndef __SYCL_DEVICE_ONLY__
207  std::optional<stream> try_lock() const noexcept {
208  auto ObjImplPtr = this->MObjWeakPtr.lock();
209  auto GlobalBuf = MWeakGlobalBuf.try_lock();
210  auto GlobalOffset = MWeakGlobalOffset.try_lock();
211  auto GlobalFlushBuf = MWeakGlobalFlushBuf.try_lock();
212  if (!ObjImplPtr || !GlobalBuf || !GlobalOffset || !GlobalFlushBuf)
213  return std::nullopt;
214  return stream{ObjImplPtr, *GlobalBuf, *GlobalOffset, *GlobalFlushBuf};
215  }
216  stream lock() const {
217  std::optional<stream> OptionalObj = try_lock();
218  if (!OptionalObj)
219  throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
220  "Referenced object has expired.");
221  return *OptionalObj;
222  }
223 #else
224  // On device calls to these functions are disallowed, so declare them but
225  // don't define them to avoid compilation failures.
226  std::optional<stream> try_lock() const noexcept;
227  stream lock() const;
228 #endif // __SYCL_DEVICE_ONLY__
229 
230 private:
231  // Additional members required for recreating stream.
234  weak_object<detail::GlobalBufAccessorT> MWeakGlobalFlushBuf;
235 };
236 
237 } // namespace ext::oneapi
238 } // namespace _V1
239 } // namespace sycl
The file contains implementations of accessor class.
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:168
decltype(sycl::detail::getSyclObjImpl(std::declval< SYCLObjT >())) ::weak_type MObjWeakPtr
static decltype(MObjWeakPtr) GetWeakImpl(const SYCLObjT &SYCLObj)
weak_object & operator=(const buffer_type &SYCLObj) noexcept
weak_object & operator=(weak_object &&Other) noexcept=default
weak_object & operator=(const weak_object &Other) noexcept=default
typename detail::weak_object_base< buffer_type >::object_type object_type
weak_object(const weak_object &Other) noexcept=default
weak_object & operator=(const stream &SYCLObj) noexcept
weak_object(const stream &SYCLObj) noexcept
weak_object & operator=(const weak_object &Other) noexcept=default
weak_object & operator=(weak_object &&Other) noexcept=default
void swap(weak_object &Other) noexcept
std::optional< stream > try_lock() const noexcept
weak_object(weak_object &&Other) noexcept=default
typename detail::weak_object_base< stream >::object_type object_type
typename detail::weak_object_base< SYCLObjT >::object_type object_type
Definition: weak_object.hpp:55
weak_object(weak_object &&Other) noexcept=default
weak_object(const weak_object &Other) noexcept=default
weak_object & operator=(const weak_object &Other) noexcept=default
weak_object & operator=(const SYCLObjT &SYCLObj) noexcept
Definition: weak_object.hpp:63
weak_object & operator=(weak_object &&Other) noexcept=default
std::optional< SYCLObjT > try_lock() const noexcept
Definition: weak_object.hpp:73
constexpr weak_object() noexcept=default
static range< Dims > createDummyRange()
Definition: weak_object.hpp:34
class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:87
Definition: access.hpp:18
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324