HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_SmallArray.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_SmallArray.h (UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #pragma once
12 
13 #ifndef __UT_SMALLARRAY_H_INCLUDED__
14 #define __UT_SMALLARRAY_H_INCLUDED__
15 
16 #include "UT_API.h"
17 #include "UT_Array.h"
18 #include "UT_Assert.h"
19 #include <SYS/SYS_Compiler.h>
20 #include <SYS/SYS_StaticAssert.h>
21 #include <utility>
22 #include <stddef.h>
23 
24 /// An array class with the small buffer optimization, making it ideal for
25 /// cases when you know it will only contain a few elements at the expense of
26 /// increasing the object size by MAX_BYTES (subject to alignment).
27 template <typename T, size_t MAX_BYTES = 64>
29 {
30  // As many elements that fit into MAX_BYTES with 1 item minimum
31  enum { MAX_ELEMS = MAX_BYTES/sizeof(T) < 1 ? 1 : MAX_BYTES/sizeof(T) };
32 
33 public:
34 
35 // gcc falsely warns about our use of offsetof() on non-POD types. We can't
36 // easily suppress this because it has to be done in the caller at
37 // instantiation time. Instead, punt to a runtime check instead.
38 #if defined(__clang__)
39  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
40  using ThisT = UT_SmallArray<T,MAX_BYTES>; \
41  SYS_STATIC_ASSERT( \
42  __builtin_offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>))
43 #elif !SYS_IS_GCC_GE(4, 8) || defined(_MSC_VER)
44  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
45  using ThisT = UT_SmallArray<T,MAX_BYTES>; \
46  SYS_STATIC_ASSERT(offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>))
47 #else
48  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
49  UT_ASSERT_P(!UT_Array<T>::isHeapBuffer());
50 #endif
51 
52  /// Default construction
54  : UT_Array<T>(/*capacity*/0)
55  {
56  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
58  }
59 
60  /// Copy constructor
61  /// @{
62  explicit UT_SmallArray(const UT_Array<T> &copy)
63  : UT_Array<T>(/*capacity*/0)
64  {
65  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
68  }
70  : UT_Array<T>(/*capacity*/0)
71  {
72  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
75  }
76  /// @}
77 
78  /// Move constructor
79  /// @{
80  UT_SmallArray(UT_Array<T> &&movable) noexcept
81  {
82  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
84  UT_Array<T>::operator=(std::move(movable));
85  }
87  {
88  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
90  UT_Array<T>::operator=(std::move(movable));
91  }
92  /// @}
93 
94  /// Initializer list constructor
95  /// If you are wondering why we mark this as explicit...
96  /// Imagine you have the following:
97  /// void foo(int i); // 1
98  /// void foo(UT_SmallArray<int>); // 2
99  /// Without explicit you can do this
100  /// foo({1})
101  /// and function 1 will be called when you probably meant
102  /// for function 2 to be called.
103  explicit UT_SmallArray(std::initializer_list<T> init)
104  {
105  UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
108  }
109 
110 #undef UT_SMALL_ARRAY_SIZE_ASSERT
111 
112  /// Assignment operator
113  /// @{
116  {
117  UT_Array<T>::operator=(copy); // NOLINT
118  return *this;
119  }
122  {
124  return *this;
125  }
126  /// @}
127 
128  /// Move operator
129  /// @{
132  {
133  UT_Array<T>::operator=(std::move(movable));
134  return *this;
135  }
138  {
139  UT_Array<T>::operator=(std::move(movable));
140  return *this;
141  }
142  /// @}
143 
145  operator=(std::initializer_list<T> src)
146  {
148  return *this;
149  }
150 private:
151  alignas(T) char myBuffer[MAX_ELEMS*sizeof(T)];
152 };
153 
154 // For UT::ArraySet.
155 namespace UT
156 {
157 template <typename T>
158 struct DefaultClearer;
159 
160 template <typename T, size_t BYTES>
162 {
164  {
165  // Just in case, destruct and reconstruct,
166  // instead of using setCapacity(0).
168  p->~UT_SmallArray<T, BYTES>();
169  new ((void *)p) UT_SmallArray<T, BYTES>();
170  }
171  static bool isClear(const UT_SmallArray<T, BYTES> &v)
172  {
173  return v.isEmpty();
174  }
176  {
177  new ((void *)p) UT_SmallArray<T, BYTES>();
178  }
179  static const bool clearNeedsDestruction = false;
180 };
181 } // namespace UT
182 
183 #endif // __UT_SMALLARRAY_H_INCLUDED__
UT_SmallArray(UT_SmallArray< T, MAX_BYTES > &&movable) noexcept
Definition: UT_SmallArray.h:86
UT_SmallArray< T, MAX_BYTES > & operator=(UT_Array< T > &&movable)
UT_SmallArray< T, MAX_BYTES > & operator=(const UT_Array< T > &copy)
#define UT_SMALL_ARRAY_SIZE_ASSERT()
Definition: UT_SmallArray.h:44
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
UT_Array< T > & operator=(const UT_Array< T > &a)
Definition: UT_ArrayImpl.h:832
UT_SmallArray< T, MAX_BYTES > & operator=(UT_SmallArray< T, MAX_BYTES > &&movable)
GLenum src
Definition: glcorearb.h:1793
const GLdouble * v
Definition: glcorearb.h:837
UT_SmallArray(const UT_Array< T > &copy)
Definition: UT_SmallArray.h:62
static void clearConstruct(UT_SmallArray< T, BYTES > *p)
GLfloat GLfloat p
Definition: glew.h:16656
static void clear(UT_SmallArray< T, BYTES > &v)
void unsafeShareData(UT_Array< T > &src)
Definition: UT_Array.h:1014
UT_SmallArray< T, MAX_BYTES > & operator=(const UT_SmallArray< T, MAX_BYTES > &copy)
UT_SmallArray(UT_Array< T > &&movable) noexcept
Definition: UT_SmallArray.h:80
UT_SmallArray(std::initializer_list< T > init)
UT_SmallArray()
Default construction.
Definition: UT_SmallArray.h:53
#define UT_API_TMPL
Definition: UT_API.h:15
static bool isClear(const UT_SmallArray< T, BYTES > &v)
UT_SmallArray(const UT_SmallArray< T, MAX_BYTES > &copy)
Definition: UT_SmallArray.h:69
UT_SmallArray< T, MAX_BYTES > & operator=(std::initializer_list< T > src)
bool isEmpty() const
Returns true iff there are no occupied elements in the array.
Definition: UT_Array.h:613