HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vectorImpl_Shared.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_VDF_VECTOR_IMPL_SHARED_H
8 #define PXR_EXEC_VDF_VECTOR_IMPL_SHARED_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/exec/vdf/api.h"
14 
16 #include "pxr/base/vt/array.h"
17 
18 #include <atomic>
19 
21 
22 /// \class Vdf_VectorImplShared
23 ///
24 /// \brief Implements a Vdf_VectorData storage the supports reference counted
25 /// sharing of other vector implementations.
26 ///
28  : public Vdf_VectorData
29 {
30 public:
31  // This class only stores a TfDelegatedCountPtr to _SharedSource, so most
32  // of the constructor, destructor, and operator heavy lifting is
33  // implemented in the equivalent methods on TfDelegatedCountPtr.
34  //
35  VDF_API
36  explicit Vdf_VectorImplShared(DataHolder* srcData);
37  VDF_API
38  Vdf_VectorImplShared(const Vdf_VectorImplShared &o);
39  VDF_API
40  Vdf_VectorImplShared(Vdf_VectorImplShared &&o) noexcept;
41  VDF_API
42  ~Vdf_VectorImplShared() override;
43 
44  // Returns the type_info for the held data.
45  //
46  VDF_API
47  const std::type_info& GetTypeInfo() const override;
48 
49  // Sets \p destData to an empty data of this data's held type.
50  //
51  VDF_API
52  void NewEmpty(size_t size, DataHolder* destData) const override;
53 
54  // Sets \p destData to a single element of this data's held type.
55  //
56  VDF_API
57  void NewSingle(DataHolder* destData) const override;
58 
59  // Sets \p destData to a sparse vector of this data's held type.
60  //
61  VDF_API
62  void NewSparse(size_t size, size_t first, size_t last,
63  DataHolder* destData) const override;
64 
65  // Sets \p destData to a dense vector of this data's held type.
66  //
67  VDF_API
68  void NewDense(size_t size, DataHolder* destData) const override;
69 
70  // Moves this vector's held data into the \p destData.
71  //
72  VDF_API
73  void MoveInto(Vdf_VectorData::DataHolder* destData) override;
74 
75  // Clones this vector's data object into \p destData. Causes the _refCount
76  // to increase.
77  //
78  VDF_API
79  void Clone(Vdf_VectorData::DataHolder* destData) const override;
80 
81  // This is like the clone method, only it uses a mask to potentially
82  // copy a smaller set of this vector into \p destData. This does not
83  // cause the _refCount to increase.
84  //
85  VDF_API
86  void CloneSubset(const VdfMask& mask,
87  Vdf_VectorData::DataHolder* destData) const override;
88 
89  // Boxes the stored data. As a result of this, \p destData will store a
90  // single element, which is a Vdf_BoxedContainer containing all the
91  // elements stored in this vector data instance.
92  //
93  // Only the data elements specified in \p bits will be pushed into the
94  // boxed container.
95  //
96  VDF_API
97  void Box(const VdfMask::Bits& bits,
98  Vdf_VectorData::DataHolder* destData) const override;
99 
100  // Merges the held data into \p destData.
101  //
102  VDF_API
103  void Merge(const VdfMask::Bits& bits,
104  Vdf_VectorData::DataHolder* destData) const override;
105 
106  // Expand the storage capabilities of the underlying vector
107  // implementation, if necessary.
108  //
109  // Note, this should never get called on VectorImpl_Shared as it mutates
110  // the held data.
111  //
112  VDF_API
113  void Expand(size_t first, size_t last) override;
114 
115  // Returns the size of the vector. Note that there may not be storage
116  // allocated for all the elements in the vector size.
117  //
118  VDF_API
119  size_t GetSize() const override;
120 
121  // Returns the number of elements stored in the vector implementation.
122  //
123  VDF_API
124  size_t GetNumStoredElements() const override;
125 
126  // Returns a pointer to the SharedSource data structure for copyless
127  // value extraction.
128  //
129  VDF_API
130  Vt_ArrayForeignDataSource* GetSharedSource() const override;
131 
132  // Returns the vector implementation details.
133  //
134  VDF_API
135  Info GetInfo() override;
136 
137  // Returns the estimated size of the allocated memory for a single
138  // element stored in this vector.
139  //
140  VDF_API
141  size_t EstimateElementMemory() const override;
142 
143  // Detaches \p data from its shared source data.
144  //
145  // It is the caller's responsibility to ensure that \p *data is holding a
146  // Vdf_VectorImplShared.
147  //
148  // If the ref count of the shared data is one then it is not safe to
149  // make copies of the shared source and detach at the same time. This
150  // is not an issue in practice because the executor data manager will
151  // always hold onto the last instance of the shared source. Meaning that
152  // if the ref count is one then either no clients are holding onto a copy
153  // or there is no more data manager (meaning that the vector cannot be
154  // written to). Also it is generally not thread-safe to try to make
155  // copies of something being written to concurrently so you would already
156  // have to be in a bad place for this to occur.
157  //
158  // An alternate approach would be to not optimize the refcount equals one
159  // case inside this method. Instead copies would always occur during
160  // detachment and the data manager could "unshare" previously shared
161  // vectors when they are reused. The performance benefits would be similar.
162  //
163  VDF_API
164  static void Detach(Vdf_VectorData::DataHolder* data);
165 
166 private:
167  // Implement a foreign data source for VtArray, it shares in the
168  // lifetime of the held DataHolder.
169  class _SharedSource: public Vt_ArrayForeignDataSource
170  {
171  public:
172  explicit _SharedSource(DataHolder* srcData);
173 
174  ~_SharedSource();
175 
176  // Return the held DataHolder for use in detachment.
177  Vdf_VectorData::DataHolder* GetHolder() {
178  return &_data;
179  }
180 
181  // Returns true if there is only one last outstanding reference to the
182  // shared data.
183  bool IsUnique() const {
184  return _refCount.load(std::memory_order_acquire) == 1;
185  }
186 
187  // Specialized TfDelegatedCountPtr operations for _SharedSource.
188  friend inline void
189  TfDelegatedCountIncrement(_SharedSource* s) noexcept {
190  s->_refCount.fetch_add(1, std::memory_order_relaxed);
191  }
192 
193  friend inline void
194  TfDelegatedCountDecrement(_SharedSource* s) noexcept {
195  if (s->_refCount.fetch_sub(1, std::memory_order_release) == 1) {
196  std::atomic_thread_fence(std::memory_order_acquire);
197  delete s;
198  }
199  }
200 
201  private:
202  // Callback for VtArray foreign data source.
203  static void _Detached(Vt_ArrayForeignDataSource* selfBase);
204 
206  };
207 
209 };
210 
212 
213 #endif
GLint first
Definition: glcorearb.h:405
virtual void MoveInto(DataHolder *destData)=0
void TfDelegatedCountIncrement(VdfMask::_BitsImpl *p) noexcept
Definition: mask.h:686
virtual size_t GetNumStoredElements() const =0
virtual VDF_API void Expand(size_t first, size_t last)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLdouble s
Definition: glad.h:3009
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
#define VDF_API
Definition: api.h:25
Abstract base class for storing data in a VdfVector.
Definition: vectorData.h:26
virtual Info GetInfo()=0
Fast, compressed bit array which is capable of performing logical operations without first decompress...
Implements a Vdf_VectorData storage the supports reference counted sharing of other vector implementa...
virtual void NewSparse(size_t size, size_t first, size_t last, DataHolder *destData) const =0
virtual void NewEmpty(size_t size, DataHolder *destData) const =0
virtual void NewSingle(DataHolder *destData) const =0
virtual size_t EstimateElementMemory() const =0
virtual void Clone(DataHolder *destData) const =0
GLint GLuint mask
Definition: glcorearb.h:124
virtual VDF_API Vt_ArrayForeignDataSource * GetSharedSource() const
virtual const std::type_info & GetTypeInfo() const =0
virtual void CloneSubset(const VdfMask &mask, DataHolder *destData) const =0
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
GLsizeiptr size
Definition: glcorearb.h:664
virtual size_t GetSize() const =0
#define VDF_API_TYPE
Definition: api.h:26
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
virtual void Box(const VdfMask::Bits &bits, DataHolder *destData) const =0
virtual void NewDense(size_t size, DataHolder *destData) const =0
Definition: format.h:1821
virtual void Merge(const VdfMask::Bits &bits, DataHolder *destData) const =0
void TfDelegatedCountDecrement(VdfMask::_BitsImpl *p) noexcept
Definition: mask.h:703