vector_t.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. namespace embree
  17. {
  18. template<typename T, typename allocator = allocator_t>
  19. class vector_t
  20. {
  21. public:
  22. typedef T value_type;
  23. typedef T* iterator;
  24. typedef const T* const_iterator;
  25. #if defined(VECTOR_INIT_ALLOCATOR)
  26. template<typename M>
  27. __forceinline vector_t (M alloc)
  28. : alloc(alloc), size_active(0), size_alloced(0), items(nullptr) {}
  29. template<typename M>
  30. __forceinline vector_t (M alloc, size_t sz)
  31. : alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
  32. #else
  33. __forceinline vector_t ()
  34. : size_active(0), size_alloced(0), items(nullptr) {}
  35. __forceinline explicit vector_t (size_t sz)
  36. : size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }
  37. #endif
  38. __forceinline ~vector_t() {
  39. clear();
  40. }
  41. __forceinline vector_t (const vector_t& other)
  42. {
  43. size_active = other.size_active;
  44. size_alloced = other.size_alloced;
  45. items = alloc.allocate(size_alloced);
  46. for (size_t i=0; i<size_active; i++)
  47. ::new (&items[i]) value_type(other.items[i]);
  48. }
  49. __forceinline vector_t (vector_t&& other)
  50. : alloc(std::move(other.alloc))
  51. {
  52. size_active = other.size_active; other.size_active = 0;
  53. size_alloced = other.size_alloced; other.size_alloced = 0;
  54. items = other.items; other.items = nullptr;
  55. }
  56. __forceinline vector_t& operator=(const vector_t& other)
  57. {
  58. resize(other.size_active);
  59. for (size_t i=0; i<size_active; i++)
  60. ::new (&items[i]) value_type(other.items[i]);
  61. return *this;
  62. }
  63. __forceinline vector_t& operator=(vector_t&& other)
  64. {
  65. alloc = std::move(other.alloc);
  66. size_active = other.size_active; other.size_active = 0;
  67. size_alloced = other.size_alloced; other.size_alloced = 0;
  68. items = other.items; other.items = nullptr;
  69. return *this;
  70. }
  71. /********************** Iterators ****************************/
  72. __forceinline iterator begin() { return items; };
  73. __forceinline const_iterator begin() const { return items; };
  74. __forceinline iterator end () { return items+size_active; };
  75. __forceinline const_iterator end () const { return items+size_active; };
  76. /********************** Capacity ****************************/
  77. __forceinline bool empty () const { return size_active == 0; }
  78. __forceinline size_t size () const { return size_active; }
  79. __forceinline size_t capacity () const { return size_alloced; }
  80. __forceinline void resize(size_t new_size) {
  81. internal_resize(new_size,size_alloced < new_size ? new_size : size_alloced);
  82. }
  83. __forceinline void reserve(size_t new_alloced)
  84. {
  85. /* do nothing if container already large enough */
  86. if (new_alloced <= size_alloced)
  87. return;
  88. /* resize exact otherwise */
  89. internal_resize(size_active,new_alloced);
  90. }
  91. __forceinline void shrink_to_fit() {
  92. internal_resize(size_active,size_active);
  93. }
  94. /******************** Element access **************************/
  95. __forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }
  96. __forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }
  97. __forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }
  98. __forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }
  99. __forceinline T& front() const { assert(size_active > 0); return items[0]; };
  100. __forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };
  101. __forceinline T* data() { return items; };
  102. __forceinline const T* data() const { return items; };
  103. /******************** Modifiers **************************/
  104. __forceinline void push_back(const T& nt)
  105. {
  106. const T v = nt; // need local copy as input reference could point to this vector
  107. internal_grow(size_active+1);
  108. ::new (&items[size_active++]) T(v);
  109. }
  110. __forceinline void pop_back()
  111. {
  112. assert(!empty());
  113. size_active--;
  114. alloc.destroy(&items[size_active]);
  115. }
  116. __forceinline void clear()
  117. {
  118. /* destroy elements */
  119. for (size_t i=0; i<size_active; i++)
  120. alloc.destroy(&items[i]);
  121. /* free memory */
  122. alloc.deallocate(items,size_alloced);
  123. items = nullptr;
  124. size_active = size_alloced = 0;
  125. }
  126. /******************** Comparisons **************************/
  127. friend bool operator== (const vector_t& a, const vector_t& b)
  128. {
  129. if (a.size() != b.size()) return false;
  130. for (size_t i=0; i<a.size(); i++)
  131. if (a[i] != b[i])
  132. return false;
  133. return true;
  134. }
  135. friend bool operator!= (const vector_t& a, const vector_t& b) {
  136. return !(a==b);
  137. }
  138. private:
  139. __forceinline void internal_resize_init(size_t new_active)
  140. {
  141. assert(size_active == 0);
  142. assert(size_alloced == 0);
  143. assert(items == nullptr);
  144. if (new_active == 0) return;
  145. items = alloc.allocate(new_active);
  146. for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();
  147. size_active = new_active;
  148. size_alloced = new_active;
  149. }
  150. __forceinline void internal_resize(size_t new_active, size_t new_alloced)
  151. {
  152. assert(new_active <= new_alloced);
  153. /* destroy elements */
  154. if (new_active < size_active)
  155. {
  156. for (size_t i=new_active; i<size_active; i++)
  157. alloc.destroy(&items[i]);
  158. size_active = new_active;
  159. }
  160. /* only reallocate if necessary */
  161. if (new_alloced == size_alloced) {
  162. for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;
  163. size_active = new_active;
  164. return;
  165. }
  166. /* reallocate and copy items */
  167. T* old_items = items;
  168. items = alloc.allocate(new_alloced);
  169. for (size_t i=0; i<size_active; i++) {
  170. ::new (&items[i]) T(std::move(old_items[i]));
  171. alloc.destroy(&old_items[i]);
  172. }
  173. for (size_t i=size_active; i<new_active; i++) {
  174. ::new (&items[i]) T;
  175. }
  176. alloc.deallocate(old_items,size_alloced);
  177. size_active = new_active;
  178. size_alloced = new_alloced;
  179. }
  180. __forceinline void internal_grow(size_t new_alloced)
  181. {
  182. /* do nothing if container already large enough */
  183. if (new_alloced <= size_alloced)
  184. return;
  185. /* resize to next power of 2 otherwise */
  186. size_t new_size_alloced = size_alloced;
  187. while (new_size_alloced < new_alloced) {
  188. new_size_alloced = 2*new_size_alloced;
  189. if (new_size_alloced == 0) new_size_alloced = 1;
  190. }
  191. internal_resize(size_active,new_size_alloced);
  192. }
  193. private:
  194. allocator alloc;
  195. size_t size_active; // number of valid items
  196. size_t size_alloced; // number of items allocated
  197. T* items; // data array
  198. };
  199. }