Path: blob/master/thirdparty/embree/common/sys/vector.h
21337 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "alloc.h"6#include <algorithm>7#include <type_traits>89namespace embree10{11class Device;1213template<typename T, typename allocator>14class vector_t15{16public:17typedef T value_type;18typedef T* iterator;19typedef const T* const_iterator;2021__forceinline vector_t ()22: size_active(0), size_alloced(0), items(nullptr) {}2324__forceinline explicit vector_t (size_t sz)25: size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }2627template<typename M>28__forceinline explicit vector_t (M alloc, size_t sz)29: alloc(alloc), size_active(0), size_alloced(0), items(nullptr) { internal_resize_init(sz); }3031__forceinline vector_t (Device* alloc)32: vector_t(alloc,0) {}3334__forceinline vector_t(void* data, size_t bytes)35: size_active(0), size_alloced(bytes/sizeof(T)), items((T*)data) {}3637__forceinline ~vector_t() {38clear();39}4041__forceinline vector_t (const vector_t& other)42{43size_active = other.size_active;44size_alloced = other.size_alloced;45items = alloc.allocate(size_alloced);46for (size_t i=0; i<size_active; i++)47::new (&items[i]) value_type(other.items[i]);48}4950__forceinline vector_t (vector_t&& other)51: alloc(std::move(other.alloc))52{53size_active = other.size_active; other.size_active = 0;54size_alloced = other.size_alloced; other.size_alloced = 0;55items = other.items; other.items = nullptr;56}5758__forceinline vector_t& operator=(const vector_t& other)59{60resize(other.size_active);61for (size_t i=0; i<size_active; i++)62items[i] = value_type(other.items[i]);63return *this;64}6566__forceinline vector_t& operator=(vector_t&& other)67{68clear();69alloc = std::move(other.alloc);70size_active = other.size_active; other.size_active = 0;71size_alloced = other.size_alloced; other.size_alloced = 0;72items = other.items; other.items = nullptr;73return *this;74}7576__forceinline allocator& getAlloc() {77return alloc;78}7980/********************** Iterators ****************************/8182__forceinline iterator begin() { return items; };83__forceinline const_iterator begin() const { return items; };8485__forceinline iterator end () { return items+size_active; };86__forceinline const_iterator end () const { return items+size_active; };878889/********************** Capacity ****************************/9091__forceinline bool empty () const { return size_active == 0; }92__forceinline size_t size () const { return size_active; }93__forceinline size_t capacity () const { return size_alloced; }949596__forceinline void resize(size_t new_size) {97internal_resize(new_size,internal_grow_size(new_size));98}99100__forceinline void reserve(size_t new_alloced)101{102/* do nothing if container already large enough */103if (new_alloced <= size_alloced)104return;105106/* resize exact otherwise */107internal_resize(size_active,new_alloced);108}109110__forceinline void shrink_to_fit() {111internal_resize(size_active,size_active);112}113114/******************** Element access **************************/115116__forceinline T& operator[](size_t i) { assert(i < size_active); return items[i]; }117__forceinline const T& operator[](size_t i) const { assert(i < size_active); return items[i]; }118119__forceinline T& at(size_t i) { assert(i < size_active); return items[i]; }120__forceinline const T& at(size_t i) const { assert(i < size_active); return items[i]; }121122__forceinline T& front() const { assert(size_active > 0); return items[0]; };123__forceinline T& back () const { assert(size_active > 0); return items[size_active-1]; };124125__forceinline T* data() { return items; };126__forceinline const T* data() const { return items; };127128/* dangerous only use if you know what you're doing */129__forceinline void setDataPtr(T* data) { items = data; }130131/******************** Modifiers **************************/132133__forceinline void push_back(const T& nt)134{135const T v = nt; // need local copy as input reference could point to this vector136internal_resize(size_active,internal_grow_size(size_active+1));137::new (&items[size_active++]) T(v);138}139140__forceinline void pop_back()141{142assert(!empty());143size_active--;144items[size_active].~T();145}146147__forceinline void clear()148{149/* destroy elements */150for (size_t i=0; i<size_active; i++){151items[i].~T();152}153154/* free memory */155alloc.deallocate(items,size_alloced);156items = nullptr;157size_active = size_alloced = 0;158}159160/******************** Comparisons **************************/161162friend bool operator== (const vector_t& a, const vector_t& b)163{164if (a.size() != b.size()) return false;165for (size_t i=0; i<a.size(); i++)166if (a[i] != b[i])167return false;168return true;169}170171friend bool operator!= (const vector_t& a, const vector_t& b) {172return !(a==b);173}174175private:176177__forceinline void internal_resize_init(size_t new_active)178{179assert(size_active == 0);180assert(size_alloced == 0);181assert(items == nullptr);182if (new_active == 0) return;183items = alloc.allocate(new_active);184for (size_t i=0; i<new_active; i++) ::new (&items[i]) T();185size_active = new_active;186size_alloced = new_active;187}188189__forceinline void internal_resize(size_t new_active, size_t new_alloced)190{191assert(new_active <= new_alloced);192193/* destroy elements */194if (new_active < size_active)195{196for (size_t i=new_active; i<size_active; i++){197items[i].~T();198}199size_active = new_active;200}201202/* only reallocate if necessary */203if (new_alloced == size_alloced) {204for (size_t i=size_active; i<new_active; i++) ::new (&items[i]) T;205size_active = new_active;206return;207}208209/* reallocate and copy items */210T* old_items = items;211items = alloc.allocate(new_alloced);212for (size_t i=0; i<size_active; i++) {213::new (&items[i]) T(std::move(old_items[i]));214old_items[i].~T();215}216217for (size_t i=size_active; i<new_active; i++) {218::new (&items[i]) T;219}220221alloc.deallocate(old_items,size_alloced);222size_active = new_active;223size_alloced = new_alloced;224}225226__forceinline size_t internal_grow_size(size_t new_alloced)227{228/* do nothing if container already large enough */229if (new_alloced <= size_alloced)230return size_alloced;231232/* if current size is 0 allocate exact requested size */233if (size_alloced == 0)234return new_alloced;235236/* resize to next power of 2 otherwise */237size_t new_size_alloced = size_alloced;238while (new_size_alloced < new_alloced) {239new_size_alloced = std::max(size_t(1),2*new_size_alloced);240}241return new_size_alloced;242}243244private:245allocator alloc;246size_t size_active; // number of valid items247size_t size_alloced; // number of items allocated248T* items; // data array249};250251/*! vector class that performs standard allocations */252template<typename T>253using vector = vector_t<T,std::allocator<T>>;254255/*! vector class that performs aligned allocations */256template<typename T>257using avector = vector_t<T,aligned_allocator<T,std::alignment_of<T>::value> >;258259/*! vector class that performs OS allocations */260template<typename T>261using ovector = vector_t<T,os_allocator<T> >;262263/*! vector class with externally managed data buffer */264template<typename T>265using evector = vector_t<T,no_allocator<T>>;266}267268269