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 <SYS/SYS_TypeDecorate.h>
22 #include <utility>
23 #include <stddef.h>
24 
25 /// An array class with the small buffer optimization, making it ideal for
26 /// cases when you know it will only contain a few elements at the expense of
27 /// increasing the object size by MAX_BYTES (subject to alignment).
28 template <typename T, size_t MAX_BYTES = 64>
30 {
31  // As many elements that fit into MAX_BYTES with 1 item minimum
32  enum { MAX_ELEMS = MAX_BYTES/sizeof(T) < 1 ? 1 : MAX_BYTES/sizeof(T) };
33 
34 public:
35 
36 // gcc falsely warns about our use of offsetof() on non-POD types. We can't
37 // easily suppress this because it has to be done in the caller at
38 // instantiation time. Instead, punt to a runtime check instead.
39 #if defined(__clang__)
40  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
41  using ThisT = UT_SmallArray<T,MAX_BYTES>; \
42  SYS_STATIC_ASSERT( \
43  __builtin_offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>))
44 #elif !SYS_IS_GCC_GE(4, 8) || defined(_MSC_VER)
45  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
46  using ThisT = UT_SmallArray<T,MAX_BYTES>; \
47  SYS_STATIC_ASSERT(offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>))
48 #else
49  #define UT_SMALL_ARRAY_SIZE_ASSERT() \
50  UT_ASSERT_P(!UT_Array<T>::isHeapBuffer());
51 #endif
52 
53  /// Default construction
55  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS }
56  {
58  }
59 
60  /// Copy constructor
61  /// @{
62  explicit UT_SmallArray(const UT_Array<T> &copy)
63  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS }
64  {
67  }
68  explicit UT_SmallArray(const UT_SmallArray &copy)
69  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS }
70  {
73  }
74  /// @}
75 
76  /// Move constructor
77  /// @{
78  UT_SmallArray(UT_Array<T> &&movable) noexcept
79  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_MOVE, (T*)myBuffer, MAX_ELEMS, std::move( movable ) }
80  {
81  }
82  UT_SmallArray(UT_SmallArray &&movable) noexcept
83  : UT_Array<T>{ UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS }
84  {
86  UT_Array<T>::operator=(std::move(movable));
87  }
88  /// @}
89 
90  /// Initializer list constructor
91  /// If you are wondering why we mark this as explicit...
92  /// Imagine you have the following:
93  /// void foo(int i); // 1
94  /// void foo(UT_SmallArray<int>); // 2
95  /// Without explicit you can do this
96  /// foo({1})
97  /// and function 1 will be called when you probably meant
98  /// for function 2 to be called.
99  explicit UT_SmallArray(std::initializer_list<T> init)
100  : UT_Array<T>( UT_ArrayCT::EXTERNAL_CAPACITY, (T*)myBuffer, MAX_ELEMS )
101  {
104  }
105 
106 #undef UT_SMALL_ARRAY_SIZE_ASSERT
107 
108  /// Assignment operator
109  /// @{
112  {
113  UT_Array<T>::operator=(copy); // NOLINT
114  return *this;
115  }
117  operator=(const UT_Array<T> &copy)
118  {
120  return *this;
121  }
122  /// @}
123 
124  /// Move operator
125  /// @{
128  {
129  UT_Array<T>::operator=(std::move(movable));
130  return *this;
131  }
133  operator=(UT_Array<T> &&movable)
134  {
135  UT_Array<T>::operator=(std::move(movable));
136  return *this;
137  }
138  /// @}
139 
141  operator=(std::initializer_list<T> src)
142  {
144  return *this;
145  }
146 private:
147  alignas(T) char myBuffer[MAX_ELEMS*sizeof(T)];
148 };
149 
150 // For UT::ArraySet.
151 namespace UT
152 {
153 template <typename T>
154 struct DefaultClearer;
155 
156 template <typename T, size_t BYTES>
157 struct DefaultClearer<UT_SmallArray<T, BYTES>>
158 {
160  {
161  // Just in case, destruct and reconstruct,
162  // instead of using setCapacity(0).
164  p->~UT_SmallArray<T, BYTES>();
165  new ((void *)p) UT_SmallArray<T, BYTES>();
166  }
167  static bool isClear(const UT_SmallArray<T, BYTES> &v)
168  {
169  return v.isEmpty();
170  }
172  {
173  new ((void *)p) UT_SmallArray<T, BYTES>();
174  }
175  static const bool clearNeedsDestruction = false;
176 };
177 } // namespace UT
178 
179 // UT_SmallArray<T> is unsafe for trivial relocation
180 // because its UT_Array<T> part holds a pointer to
181 // UT_SmallArray<T>'s local buffer 'myBuffer'.
182 template <typename T>
184 
185 #endif // __UT_SMALLARRAY_H_INCLUDED__
#define UT_SMALL_ARRAY_SIZE_ASSERT()
Definition: UT_SmallArray.h:45
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
const GLdouble * v
Definition: glcorearb.h:837
UT_Array< T > & operator=(const UT_Array< T > &a)
UT_SmallArray(const UT_Array< T > &copy)
Definition: UT_SmallArray.h:62
static void clearConstruct(UT_SmallArray< T, BYTES > *p)
static constexpr struct UT_ArrayCT::ExternalCapacity EXTERNAL_CAPACITY
static void clear(UT_SmallArray< T, BYTES > &v)
UT_SmallArray(UT_Array< T > &&movable) noexcept
Definition: UT_SmallArray.h:78
#define SYS_DECLARE_IS_NOT_TR_TEMPLATE(...)
Version for class template.
static constexpr struct UT_ArrayCT::ExternalMove EXTERNAL_MOVE
UT_SmallArray()
Default construction.
Definition: UT_SmallArray.h:54
#define UT_API_TMPL
Definition: UT_API.h:15
static bool isClear(const UT_SmallArray< T, BYTES > &v)
UT_SmallArray(const UT_SmallArray &copy)
Definition: UT_SmallArray.h:68
bool isEmpty() const
Returns true iff there are no occupied elements in the array.
Definition: UT_Array.h:650
GLenum src
Definition: glcorearb.h:1793