Path: blob/master/thirdparty/embree/common/sys/vector.h
9912 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "alloc.h"6#include <algorithm>78namespace embree9{10class Device;1112template<typename T, typename allocator>13class vector_t14{15public:16typedef T value_type;17typedef T* iterator;18typedef const T* const_iterator;1920__forceinline vector_t ()21: size_active(0), size_alloced(0), items(nullptr) {}2223__forceinline explicit vector_t (size_t sz)24: size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }2526template<typename M>27__forceinline explicit vector_t (M alloc, size_t sz)28: alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }2930__forceinline vector_t (Device* alloc)31: vector_t(alloc,0) {}3233__forceinline vector_t(void* data, size_t bytes)34: size_active(0), size_alloced(bytes/sizeof(T)), items((T*)data) {}3536__forceinline ~vector_t() {37clear();38}3940__forceinline vector_t (const vector_t& other)41{42size_active = other.size_active;43size_alloced = other.size_alloced;44items = alloc.allocate(size_alloced);45for (size_t i=0; i<size_active; i++)46::new (&items[i]) value_type(other.items[i]);47}4849__forceinline vector_t (vector_t&& other)50: alloc(std::move(other.alloc))51{52size_active = other.size_active; other.size_active = 0;53size_alloced = other.size_alloced; other.size_alloced = 0;54items = other.items; other.items = nullptr;55}5657__forceinline vector_t& operator=(const vector_t& other)58{59resize(other.size_active);60for (size_t i=0; i<size_active; i++)61items[i] = value_type(other.items[i]);62return *this;63}6465__forceinline vector_t& operator=(vector_t&& other)66{67clear();68alloc = std::move(other.alloc);69size_active = other.size_active; other.size_active = 0;70size_alloced = other.size_alloced; other.size_alloced = 0;71items = other.items; other.items = nullptr;72return *this;73}7475__forceinline allocator& getAlloc() {76return alloc;77}7879/********************** Iterators ****************************/8081__forceinline iterator begin() { return items; };82__forceinline const_iterator begin() const { return items; };8384__forceinline iterator end () { return items+size_active; };85__forceinline const_iterator end () const { return items+size_active; };868788/********************** Capacity ****************************/8990__forceinline bool empty () const { return size_active == 0; }91__forceinline size_t size () const { return size_active; }92__forceinline size_t capacity () const { return size_alloced; }939495__forceinline void resize(size_t new_size) {96internal_resize(new_size,internal_grow_size(new_size));97}9899__forceinline void reserve(size_t new_alloced)100{101/* do nothing if container already large enough */102if (new_alloced <= size_alloced)103return;104105/* resize exact otherwise */106internal_resize(size_active,new_alloced);107}108109__forceinline void shrink_to_fit() {110internal_resize(size_active,size_active);111}112113/******************** Element access **************************/114115__forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }116__forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }117118__forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }119__forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }120121__forceinline T& front() const { assert(size_active > 0); return items[0]; };122__forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };123124__forceinline T* data() { return items; };125__forceinline const T* data() const { return items; };126127/* dangerous only use if you know what you're doing */128__forceinline void setDataPtr(T* data) { items = data; }129130/******************** Modifiers **************************/131132__forceinline void push_back(const T& nt)133{134const T v = nt; // need local copy as input reference could point to this vector135internal_resize(size_active,internal_grow_size(size_active+1));136::new (&items[size_active++]) T(v);137}138139__forceinline void pop_back()140{141assert(!empty());142size_active--;143items[size_active].~T();144}145146__forceinline void clear()147{148/* destroy elements */149for (size_t i=0; i<size_active; i++){150items[i].~T();151}152153/* free memory */154alloc.deallocate(items,size_alloced);155items = nullptr;156size_active = size_alloced = 0;157}158159/******************** Comparisons **************************/160161friend bool operator== (const vector_t& a, const vector_t& b)162{163if (a.size() != b.size()) return false;164for (size_t i=0; i<a.size(); i++)165if (a[i] != b[i])166return false;167return true;168}169170friend bool operator!= (const vector_t& a, const vector_t& b) {171return !(a==b);172}173174private:175176__forceinline void internal_resize_init(size_t new_active)177{178assert(size_active == 0);179assert(size_alloced == 0);180assert(items == nullptr);181if (new_active == 0) return;182items = alloc.allocate(new_active);183for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();184size_active = new_active;185size_alloced = new_active;186}187188__forceinline void internal_resize(size_t new_active, size_t new_alloced)189{190assert(new_active <= new_alloced);191192/* destroy elements */193if (new_active < size_active)194{195for (size_t i=new_active; i<size_active; i++){196items[i].~T();197}198size_active = new_active;199}200201/* only reallocate if necessary */202if (new_alloced == size_alloced) {203for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;204size_active = new_active;205return;206}207208/* reallocate and copy items */209T* old_items = items;210items = alloc.allocate(new_alloced);211for (size_t i=0; i<size_active; i++) {212::new (&items[i]) T(std::move(old_items[i]));213old_items[i].~T();214}215216for (size_t i=size_active; i<new_active; i++) {217::new (&items[i]) T;218}219220alloc.deallocate(old_items,size_alloced);221size_active = new_active;222size_alloced = new_alloced;223}224225__forceinline size_t internal_grow_size(size_t new_alloced)226{227/* do nothing if container already large enough */228if (new_alloced <= size_alloced)229return size_alloced;230231/* if current size is 0 allocate exact requested size */232if (size_alloced == 0)233return new_alloced;234235/* resize to next power of 2 otherwise */236size_t new_size_alloced = size_alloced;237while (new_size_alloced < new_alloced) {238new_size_alloced = std::max(size_t(1),2*new_size_alloced);239}240return new_size_alloced;241}242243private:244allocator alloc;245size_t size_active; // number of valid items246size_t size_alloced; // number of items allocated247T* items; // data array248};249250/*! vector class that performs standard allocations */251template<typename T>252using vector = vector_t<T,std::allocator<T>>;253254/*! vector class that performs aligned allocations */255template<typename T>256using avector = vector_t<T,aligned_allocator<T,std::alignment_of<T>::value> >;257258/*! vector class that performs OS allocations */259template<typename T>260using ovector = vector_t<T,os_allocator<T> >;261262/*! vector class with externally managed data buffer */263template<typename T>264using evector = vector_t<T,no_allocator<T>>;265}266267268