mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
dtoolutil: Add small_vector implementation and use it
This vector implementation does is optimized for the case of having only a small number of elements, which are stored directly on the vector object rather than being allocated from the heap. If the capacity exceeds this small number, then a heap allocation is done. This should improve performance in a couple of cases where vectors typically store 1 element and rarely more than that.
This commit is contained in:
parent
35348fd74a
commit
eefb51f510
@ -654,9 +654,8 @@ void CInterval::
|
||||
mark_dirty() {
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
Parents::iterator pi;
|
||||
for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
|
||||
(*pi)->mark_dirty();
|
||||
for (CInterval *parent : _parents) {
|
||||
parent->mark_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "directbase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
#include "config_interval.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "extension.h"
|
||||
@ -178,7 +178,7 @@ private:
|
||||
// We keep a record of the "parent" intervals (that is, any CMetaInterval
|
||||
// objects that keep a pointer to this one) strictly so we can mark all of
|
||||
// our parents dirty when this interval gets dirty.
|
||||
typedef pvector<CInterval *> Parents;
|
||||
typedef small_vector<CInterval *> Parents;
|
||||
Parents _parents;
|
||||
|
||||
static PStatCollector _root_pcollector;
|
||||
|
@ -70,9 +70,9 @@ clear_intervals() {
|
||||
IntervalDef &def = (*di);
|
||||
if (def._c_interval != nullptr) {
|
||||
CInterval::Parents::iterator pi =
|
||||
find(def._c_interval->_parents.begin(),
|
||||
def._c_interval->_parents.end(),
|
||||
this);
|
||||
std::find(def._c_interval->_parents.begin(),
|
||||
def._c_interval->_parents.end(),
|
||||
this);
|
||||
nassertv(pi != def._c_interval->_parents.end());
|
||||
def._c_interval->_parents.erase(pi);
|
||||
}
|
||||
@ -798,7 +798,7 @@ do_event_forward(CMetaInterval::PlaybackEvent *event,
|
||||
// Erase the event from either the new active or the current active
|
||||
// lists.
|
||||
ActiveEvents::iterator ai;
|
||||
ai = find(new_active.begin(), new_active.end(), event->_begin_event);
|
||||
ai = std::find(new_active.begin(), new_active.end(), event->_begin_event);
|
||||
if (ai != new_active.end()) {
|
||||
new_active.erase(ai);
|
||||
// This interval was new this frame; we must invoke it as an instant
|
||||
@ -806,7 +806,7 @@ do_event_forward(CMetaInterval::PlaybackEvent *event,
|
||||
enqueue_event(event->_n, ET_instant, is_initial);
|
||||
|
||||
} else {
|
||||
ai = find(_active.begin(), _active.end(), event->_begin_event);
|
||||
ai = std::find(_active.begin(), _active.end(), event->_begin_event);
|
||||
if (ai != _active.end()) {
|
||||
_active.erase(ai);
|
||||
enqueue_event(event->_n, ET_finalize, is_initial);
|
||||
@ -872,14 +872,14 @@ do_event_reverse(CMetaInterval::PlaybackEvent *event,
|
||||
// Erase the event from either the new active or the current active
|
||||
// lists.
|
||||
ActiveEvents::iterator ai;
|
||||
ai = find(new_active.begin(), new_active.end(), event);
|
||||
ai = std::find(new_active.begin(), new_active.end(), event);
|
||||
if (ai != new_active.end()) {
|
||||
new_active.erase(ai);
|
||||
// This interval was new this frame; we invoke it as an instant event.
|
||||
enqueue_event(event->_n, ET_reverse_instant, is_initial);
|
||||
|
||||
} else {
|
||||
ai = find(_active.begin(), _active.end(), event);
|
||||
ai = std::find(_active.begin(), _active.end(), event);
|
||||
if (ai != _active.end()) {
|
||||
_active.erase(ai);
|
||||
enqueue_event(event->_n, ET_reverse_finalize, is_initial);
|
||||
|
@ -13,6 +13,7 @@ set(P3DTOOLUTIL_HEADERS
|
||||
panda_getopt.h panda_getopt_long.h panda_getopt_impl.h
|
||||
pfstream.h pfstream.I pfstreamBuf.h
|
||||
preprocess_argv.h
|
||||
small_vector.h small_vector.I
|
||||
string_utils.h string_utils.I
|
||||
stringDecoder.h stringDecoder.I
|
||||
textEncoder.h textEncoder.I
|
||||
|
694
dtool/src/dtoolutil/small_vector.I
Normal file
694
dtool/src/dtoolutil/small_vector.I
Normal file
@ -0,0 +1,694 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file small_vector.I
|
||||
* @author rdb
|
||||
* @date 2023-01-25
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N>::
|
||||
small_vector(TypeHandle type_handle) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializer list constructor.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N>::
|
||||
small_vector(std::initializer_list<T> init) :
|
||||
_storage(init.size() > N ? (T *)PANDA_MALLOC_ARRAY(sizeof(T) * init.size()) : nullptr),
|
||||
_size(init.size()),
|
||||
_capacity(std::max((size_type)N, (size_type)init.size())) {
|
||||
|
||||
T *to = this->data();
|
||||
for (const T &value : init) {
|
||||
new (to++) T(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N>::
|
||||
small_vector(const small_vector ©) :
|
||||
_storage(copy._size > N ? (T *)PANDA_MALLOC_ARRAY(sizeof(T) * copy._size) : nullptr),
|
||||
_size(copy._size),
|
||||
_capacity(std::max((size_type)N, copy._size)) {
|
||||
|
||||
const T *from = copy.data();
|
||||
T *to = this->data();
|
||||
for (size_type i = 0; i < _size; ++i) {
|
||||
new (to + i) T(from[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N>::
|
||||
small_vector(small_vector &&other) noexcept :
|
||||
_storage(other._storage._large),
|
||||
_size(other._size),
|
||||
_capacity(other._capacity) {
|
||||
|
||||
if (_size <= N) {
|
||||
T *to = _storage._small;
|
||||
T *from = other.data();
|
||||
for (size_type i = 0; i < _size; ++i) {
|
||||
new (to + i) T(std::move(from[i]));
|
||||
from[i].~T();
|
||||
}
|
||||
_capacity = N;
|
||||
}
|
||||
other._storage._large = nullptr;
|
||||
other._size = 0;
|
||||
other._capacity = N;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N>::
|
||||
~small_vector() {
|
||||
this->clear();
|
||||
if (!this->is_small()) {
|
||||
PANDA_FREE_ARRAY(_storage._large);
|
||||
_capacity = N;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N> &small_vector<T, N>::
|
||||
operator =(const small_vector ©) {
|
||||
this->clear();
|
||||
this->reserve(copy._size);
|
||||
|
||||
const T *from = copy.data();
|
||||
T *to = this->data();
|
||||
for (size_type i = 0; i < copy._size; ++i) {
|
||||
new (to + i) T(from[i]);
|
||||
}
|
||||
_size = copy._size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE small_vector<T, N> &small_vector<T, N>::
|
||||
operator =(small_vector &&from) noexcept {
|
||||
if (UNLIKELY(this == &from)) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
this->clear();
|
||||
if (!this->is_small()) {
|
||||
PANDA_FREE_ARRAY(_storage._large);
|
||||
_capacity = N;
|
||||
}
|
||||
|
||||
_storage._large = from._storage._large;
|
||||
_size = from._size;
|
||||
_capacity = from._capacity;
|
||||
|
||||
if (this->is_small()) {
|
||||
#if defined(__has_builtin) && __has_builtin(__builtin_assume)
|
||||
__builtin_assume(_size <= N);
|
||||
#endif
|
||||
T *to = this->_storage._small;
|
||||
for (size_type i = 0; i < _size; ++i) {
|
||||
new (to + i) T(std::move(from._storage._small[i]));
|
||||
from._storage._small[i].~T();
|
||||
}
|
||||
}
|
||||
from._storage._large = nullptr;
|
||||
from._size = 0;
|
||||
from._capacity = N;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are no elements in this vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
constexpr bool small_vector<T, N>::
|
||||
empty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements stored in the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
constexpr typename small_vector<T, N>::size_type small_vector<T, N>::
|
||||
size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total capacity of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
constexpr typename small_vector<T, N>::size_type small_vector<T, N>::
|
||||
capacity() const {
|
||||
return _capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum size of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
constexpr typename small_vector<T, N>::size_type small_vector<T, N>::
|
||||
max_size() const {
|
||||
return SIZE_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ith element with bounds checking.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::reference small_vector<T, N>::
|
||||
at(size_type i) {
|
||||
assert(i < size());
|
||||
return *(this->begin() + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ith element with bounds checking.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::const_reference small_vector<T, N>::
|
||||
at(size_type i) const {
|
||||
assert(i < size());
|
||||
return *(this->begin() + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ith element without bounds checking.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::reference small_vector<T, N>::
|
||||
operator [](size_type i) {
|
||||
return *(this->begin() + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ith element without bounds checking.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_reference small_vector<T, N>::
|
||||
operator [](size_type i) const {
|
||||
return *(this->begin() + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the first element.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::reference small_vector<T, N>::
|
||||
front() {
|
||||
return *(this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const reference to the first element.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::const_reference small_vector<T, N>::
|
||||
front() const {
|
||||
return *(this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the last element.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::reference small_vector<T, N>::
|
||||
back() {
|
||||
return *(this->end() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const reference to the last element.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::const_reference small_vector<T, N>::
|
||||
back() const {
|
||||
return *(this->end() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the data.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE T *small_vector<T, N>::
|
||||
data() {
|
||||
return this->is_small() ? this->_storage._small : this->_storage._large;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the data.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE const T *small_vector<T, N>::
|
||||
data() const {
|
||||
return this->is_small() ? this->_storage._small : this->_storage._large;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the first element of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
begin() {
|
||||
return this->is_small() ? this->_storage._small : this->_storage._large;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator one element past the last element in the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
end() {
|
||||
return this->begin() + _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator to the first element of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_iterator small_vector<T, N>::
|
||||
begin() const {
|
||||
return this->is_small() ? this->_storage._small : this->_storage._large;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator one element past the last element in the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_iterator small_vector<T, N>::
|
||||
end() const {
|
||||
return this->begin() + _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator to the first element of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_iterator small_vector<T, N>::
|
||||
cbegin() const {
|
||||
return this->is_small() ? this->_storage._small : this->_storage._large;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator one element past the last element in the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_iterator small_vector<T, N>::
|
||||
cend() const {
|
||||
return this->begin() + _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::reverse_iterator small_vector<T, N>::
|
||||
rbegin() {
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the beginning of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::reverse_iterator small_vector<T, N>::
|
||||
rend() {
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_reverse_iterator small_vector<T, N>::
|
||||
rbegin() const {
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the beginning of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_reverse_iterator small_vector<T, N>::
|
||||
rend() const {
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_reverse_iterator small_vector<T, N>::
|
||||
crbegin() const {
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reverse iterator to the beginning of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
ALWAYS_INLINE typename small_vector<T, N>::const_reverse_iterator small_vector<T, N>::
|
||||
crend() const {
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from the vector. Does not deallocate storage, consider
|
||||
* calling shrink_to_fit afterwards.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
clear() {
|
||||
for (T &element : *this) {
|
||||
element.~T();
|
||||
}
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reallocates the size down to the current content size.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
shrink_to_fit() {
|
||||
if (_capacity > N && _capacity > _size) {
|
||||
T *from = _storage._large;
|
||||
T *to;
|
||||
if (_size > N) {
|
||||
_capacity = _size;
|
||||
to = (T *)PANDA_MALLOC_ARRAY(sizeof(T) * _size);
|
||||
} else {
|
||||
_capacity = N;
|
||||
to = _storage._small;
|
||||
}
|
||||
for (size_type i = 0; i < _size; ++i) {
|
||||
new (to + i) T(std::move(from[i]));
|
||||
from[i].~T();
|
||||
}
|
||||
PANDA_FREE_ARRAY(from);
|
||||
_capacity = std::max(_size, (size_type)N);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates enough capacity for the given number of elements.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
reserve(size_type n) {
|
||||
if (n > _capacity) {
|
||||
T *from = this->data();
|
||||
T *to = (T *)PANDA_MALLOC_ARRAY(sizeof(T) * n);
|
||||
for (size_type i = 0; i < _size; ++i) {
|
||||
new (to + i) T(std::move(from[i]));
|
||||
from[i].~T();
|
||||
}
|
||||
|
||||
if (!this->is_small()) {
|
||||
PANDA_FREE_ARRAY(from);
|
||||
}
|
||||
|
||||
//NB. It's not safe to overwrite this until we're done reading from the
|
||||
// internal storage (which overlaps with this pointer).
|
||||
_storage._large = to;
|
||||
_capacity = n;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the vector to the given number of elements.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
resize(size_type n, T value) {
|
||||
if (n > _size) {
|
||||
this->reserve(n);
|
||||
|
||||
T *to = this->data();
|
||||
for (size_type i = _size; i < n; ++i) {
|
||||
new (to + i) T(std::move(value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
T *to = this->data();
|
||||
for (size_type i = n; i < _size; ++i) {
|
||||
to[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
_size = n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new element at the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
template<class... Args>
|
||||
INLINE typename small_vector<T, N>::reference small_vector<T, N>::
|
||||
emplace_back(Args&&... args) {
|
||||
iterator it = this->append();
|
||||
new (it) T(std::forward<Args>(args)...);
|
||||
return *it;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an element to the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
push_back(const T &value) {
|
||||
new (this->append()) T(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an element to the end of the vector.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
push_back(T &&value) {
|
||||
new (this->append()) T(std::move(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last element from the vector. Does not deallocate storage,
|
||||
* consider calling shrink_to_fit afterwards.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE void small_vector<T, N>::
|
||||
pop_back() {
|
||||
assert(!this->empty());
|
||||
|
||||
(this->data() + --_size)->~T();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given element before the indicated position.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
insert(const_iterator pos, const T &value) {
|
||||
iterator new_pos = this->insert_gap(pos, 1);
|
||||
new (new_pos) T(value);
|
||||
return new_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the given element before the indicated position.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
insert(const_iterator pos, T &&value) {
|
||||
iterator new_pos = this->insert_gap(pos, 1);
|
||||
new (new_pos) T(std::move(value));
|
||||
return new_pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the given position from the vector. Usually does not
|
||||
* reallocate storage (except when removing from the beginning if the new size
|
||||
* is smaller than the preallocated storage), consider calling shrink_to_fit()
|
||||
* afterwards.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
erase(const_iterator pos) {
|
||||
T *data = this->data();
|
||||
size_type i = pos - data;
|
||||
assert(i < _size);
|
||||
--_size;
|
||||
|
||||
T *to = (T *)pos;
|
||||
T *to_end = data + _size;
|
||||
T *from = to + 1;
|
||||
|
||||
T *free_ptr = nullptr;
|
||||
if (i == 0 && _size <= N && !this->is_small()) {
|
||||
// We're moving everything anyway, just move it to internal storage
|
||||
to = this->_storage._small;
|
||||
to_end = to + _size;
|
||||
_capacity = N;
|
||||
free_ptr = data;
|
||||
}
|
||||
|
||||
pos->~T();
|
||||
|
||||
while (to < to_end) {
|
||||
new (to++) T(std::move(*from));
|
||||
from->~T();
|
||||
++from;
|
||||
}
|
||||
|
||||
if (free_ptr != nullptr) {
|
||||
PANDA_FREE_ARRAY(free_ptr);
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given range of elements from the vector. Usually does not
|
||||
* reallocate storage (except when removing from the beginning if the new size
|
||||
* is smaller than the preallocated storage), consider calling shrink_to_fit()
|
||||
* afterwards.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
erase(const_iterator begin, const_iterator end) {
|
||||
if (begin == end) {
|
||||
return (iterator)end;
|
||||
}
|
||||
|
||||
T *data = this->data();
|
||||
size_type i = begin - data;
|
||||
assert(i < _size);
|
||||
_size -= (end - begin);
|
||||
assert(_size <= _capacity);
|
||||
|
||||
T *to = (T *)begin;
|
||||
T *to_end = data + _size;
|
||||
T *from = (T *)end;
|
||||
|
||||
T *free_ptr = nullptr;
|
||||
if (i == 0 && _size <= N && !this->is_small()) {
|
||||
// We're moving everything anyway, just move it to internal storage
|
||||
to = this->_storage._small;
|
||||
to_end = to + _size;
|
||||
_capacity = N;
|
||||
free_ptr = data;
|
||||
}
|
||||
|
||||
while (begin < end) {
|
||||
begin->~T();
|
||||
++begin;
|
||||
}
|
||||
|
||||
while (to < to_end) {
|
||||
new (to++) T(std::move(*from));
|
||||
from->~T();
|
||||
++from;
|
||||
}
|
||||
|
||||
if (free_ptr != nullptr) {
|
||||
PANDA_FREE_ARRAY(free_ptr);
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts elements right starting from the given position. The gap remains
|
||||
* uninitialized.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
insert_gap(const_iterator pos, size_type count) {
|
||||
T *data = this->data();
|
||||
size_type offset = pos - data;
|
||||
assert(offset <= _size);
|
||||
_size += count;
|
||||
|
||||
if (_size <= _capacity) {
|
||||
// Just move everything back.
|
||||
for (size_type i = _size - 1; i >= offset + count; --i) {
|
||||
new (data + i) T(std::move(data[i - count]));
|
||||
data[i - count].~T();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Need to resize, so move everything to the new array.
|
||||
size_type new_cap = std::max(_size, _capacity << 1u);
|
||||
|
||||
T *old_data = data;
|
||||
data = (T *)PANDA_MALLOC_ARRAY(sizeof(T) * new_cap);
|
||||
|
||||
T *from = old_data;
|
||||
T *to = data;
|
||||
for (size_type i = 0; i < offset; ++i) {
|
||||
new (to++) T(std::move(*from));
|
||||
from->~T();
|
||||
++from;
|
||||
}
|
||||
|
||||
to += count;
|
||||
|
||||
T *to_end = data + _size;
|
||||
while (to < to_end) {
|
||||
new (to++) T(std::move(*from));
|
||||
from->~T();
|
||||
++from;
|
||||
}
|
||||
|
||||
if (old_data != _storage._small) {
|
||||
PANDA_FREE_ARRAY(old_data);
|
||||
}
|
||||
|
||||
//NB. It's not safe to overwrite this until we're done reading from the
|
||||
// internal storage (which overlaps with this pointer).
|
||||
_storage._large = data;
|
||||
_capacity = new_cap;
|
||||
}
|
||||
|
||||
return data + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the vector in size by one, leaving the new element uninitialized.
|
||||
* Returns an iterator to the back.
|
||||
*/
|
||||
template<class T, unsigned N>
|
||||
INLINE typename small_vector<T, N>::iterator small_vector<T, N>::
|
||||
append() {
|
||||
size_type size = _size;
|
||||
if (size == _capacity) {
|
||||
this->reserve(_capacity << 1u);
|
||||
}
|
||||
++_size;
|
||||
return this->begin() + size;
|
||||
}
|
132
dtool/src/dtoolutil/small_vector.h
Normal file
132
dtool/src/dtoolutil/small_vector.h
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file small_vector.h
|
||||
* @author rdb
|
||||
* @date 2023-01-25
|
||||
*/
|
||||
|
||||
#ifndef SMALL_VECTOR_H
|
||||
#define SMALL_VECTOR_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "typeHandle.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
/**
|
||||
* A vector type that is particularly optimized for the case where there is a
|
||||
* small number of elements (by default as many as fit inside the space of a
|
||||
* single pointer, but at least one). No heap allocations are required as long
|
||||
* as the vector stays below this size. It also has the same footprint as
|
||||
* std::vector if the element is only a single pointer in size.
|
||||
*
|
||||
* The number of preallocated elements may also be 0, in which case the vector
|
||||
* behaves as a regular vector, only benefiting from the reduced footprint.
|
||||
*
|
||||
* Furthermore, it can be safely used at static init time due to the existence
|
||||
* of a constexpr constructor.
|
||||
*
|
||||
* However, some other operations are probably less efficient. For example,
|
||||
* swapping a small_vector is more expensive, so this operation is not provided.
|
||||
*
|
||||
* If memory is allocated, it is not automatically deallocated (even if the
|
||||
* vector is resized down to zero) but see shrink_to_fit() to accomplish this.
|
||||
*/
|
||||
template<class T, unsigned N = (sizeof(T) >= sizeof(void *) ? 1 : sizeof(void *) / sizeof(T))>
|
||||
class small_vector {
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
ALWAYS_INLINE constexpr small_vector() = default;
|
||||
INLINE small_vector(TypeHandle type_handle);
|
||||
INLINE small_vector(std::initializer_list<T> init);
|
||||
INLINE small_vector(const small_vector ©);
|
||||
INLINE small_vector(small_vector &&from) noexcept;
|
||||
INLINE ~small_vector();
|
||||
|
||||
INLINE small_vector &operator =(const small_vector ©);
|
||||
INLINE small_vector &operator =(small_vector &&from) noexcept;
|
||||
|
||||
constexpr bool empty() const;
|
||||
constexpr size_type size() const;
|
||||
constexpr size_type capacity() const;
|
||||
constexpr size_type max_size() const;
|
||||
|
||||
INLINE reference at(size_type i);
|
||||
INLINE const_reference at(size_type i) const;
|
||||
ALWAYS_INLINE reference operator [](size_type i);
|
||||
ALWAYS_INLINE const_reference operator [](size_type i) const;
|
||||
|
||||
ALWAYS_INLINE reference front();
|
||||
ALWAYS_INLINE const_reference front() const;
|
||||
ALWAYS_INLINE reference back();
|
||||
ALWAYS_INLINE const_reference back() const;
|
||||
ALWAYS_INLINE T *data();
|
||||
ALWAYS_INLINE const T *data() const;
|
||||
|
||||
ALWAYS_INLINE iterator begin();
|
||||
ALWAYS_INLINE iterator end();
|
||||
ALWAYS_INLINE const_iterator begin() const;
|
||||
ALWAYS_INLINE const_iterator end() const;
|
||||
ALWAYS_INLINE const_iterator cbegin() const;
|
||||
ALWAYS_INLINE const_iterator cend() const;
|
||||
|
||||
ALWAYS_INLINE reverse_iterator rbegin();
|
||||
ALWAYS_INLINE reverse_iterator rend();
|
||||
ALWAYS_INLINE const_reverse_iterator rbegin() const;
|
||||
ALWAYS_INLINE const_reverse_iterator rend() const;
|
||||
ALWAYS_INLINE const_reverse_iterator crbegin() const;
|
||||
ALWAYS_INLINE const_reverse_iterator crend() const;
|
||||
|
||||
INLINE void clear();
|
||||
INLINE void shrink_to_fit();
|
||||
INLINE void reserve(size_type n);
|
||||
INLINE void resize(size_type n, T value = T());
|
||||
|
||||
template<class... Args>
|
||||
INLINE reference emplace_back(Args&&... args);
|
||||
INLINE void push_back(const T &value);
|
||||
INLINE void push_back(T &&value);
|
||||
INLINE void pop_back();
|
||||
INLINE iterator insert(const_iterator pos, const T &value);
|
||||
INLINE iterator insert(const_iterator pos, T &&value);
|
||||
INLINE iterator erase(const_iterator pos);
|
||||
INLINE iterator erase(const_iterator begin, const_iterator end);
|
||||
|
||||
private:
|
||||
INLINE iterator insert_gap(const_iterator pos, size_type count);
|
||||
INLINE iterator append();
|
||||
|
||||
constexpr bool is_small() const { return LIKELY(_capacity <= N); }
|
||||
|
||||
union Storage {
|
||||
constexpr Storage() : _large(nullptr) {}
|
||||
constexpr Storage(T *large) : _large(large) {}
|
||||
~Storage() {}
|
||||
|
||||
T *_large;
|
||||
T _small[N];
|
||||
} _storage;
|
||||
|
||||
size_type _size = 0;
|
||||
size_type _capacity = N;
|
||||
};
|
||||
|
||||
#include "small_vector.I"
|
||||
|
||||
#endif
|
@ -20,8 +20,7 @@
|
||||
#include "vector_string.h"
|
||||
#include "numeric_types.h"
|
||||
#include "filename.h"
|
||||
|
||||
#include <vector>
|
||||
#include "small_vector.h"
|
||||
|
||||
class ConfigVariableCore;
|
||||
|
||||
@ -114,7 +113,7 @@ private:
|
||||
short _flags;
|
||||
};
|
||||
|
||||
typedef std::vector<Word> Words;
|
||||
typedef small_vector<Word> Words;
|
||||
Words _words;
|
||||
bool _got_words;
|
||||
|
||||
|
@ -158,7 +158,7 @@ public:
|
||||
*/
|
||||
void AnimGroup::
|
||||
sort_descendants() {
|
||||
sort(_children.begin(), _children.end(), AnimGroupAlphabeticalOrder());
|
||||
std::sort(_children.begin(), _children.end(), AnimGroupAlphabeticalOrder());
|
||||
|
||||
Children::iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "partGroup.h"
|
||||
#include "partBundle.h"
|
||||
#include "animChannelBase.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* This is the base class for a single animatable piece that may be bound to
|
||||
@ -75,7 +76,7 @@ protected:
|
||||
virtual void determine_effective_channels(const CycleData *root_cdata);
|
||||
|
||||
// This is the vector of all channels bound to this part.
|
||||
typedef pvector< PT(AnimChannelBase) > Channels;
|
||||
typedef small_vector< PT(AnimChannelBase) > Channels;
|
||||
Channels _channels;
|
||||
|
||||
// This is the single channel that has an effect on this part, as determined
|
||||
|
@ -632,7 +632,7 @@ do_bind_anim(AnimControl *control, AnimBundle *anim,
|
||||
*/
|
||||
void PartBundle::
|
||||
add_node(PartBundleNode *node) {
|
||||
nassertv(find(_nodes.begin(), _nodes.end(), node) == _nodes.end());
|
||||
nassertv(std::find(_nodes.begin(), _nodes.end(), node) == _nodes.end());
|
||||
_nodes.push_back(node);
|
||||
}
|
||||
|
||||
@ -643,7 +643,7 @@ add_node(PartBundleNode *node) {
|
||||
*/
|
||||
void PartBundle::
|
||||
remove_node(PartBundleNode *node) {
|
||||
Nodes::iterator ni = find(_nodes.begin(), _nodes.end(), node);
|
||||
Nodes::iterator ni = std::find(_nodes.begin(), _nodes.end(), node);
|
||||
nassertv(ni != _nodes.end());
|
||||
_nodes.erase(ni);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ private:
|
||||
|
||||
COWPT(AnimPreloadTable) _anim_preload;
|
||||
|
||||
typedef pvector<PartBundleNode *> Nodes;
|
||||
typedef small_vector<PartBundleNode *> Nodes;
|
||||
Nodes _nodes;
|
||||
|
||||
typedef pmap<WCPT(TransformState), WPT(PartBundle), std::owner_less<WCPT(TransformState)> > AppliedTransforms;
|
||||
|
@ -97,7 +97,7 @@ add_bundle(PartBundle *bundle) {
|
||||
*/
|
||||
void PartBundleNode::
|
||||
do_add_bundle_handle(PartBundleHandle *handle) {
|
||||
Bundles::iterator bi = find(_bundles.begin(), _bundles.end(), handle);
|
||||
Bundles::iterator bi = std::find(_bundles.begin(), _bundles.end(), handle);
|
||||
if (bi != _bundles.end()) {
|
||||
// This handle is already within the node.
|
||||
return;
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "lightMutex.h"
|
||||
#include "pandaNode.h"
|
||||
#include "dcast.h"
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* This is a node that contains a pointer to an PartBundle. Like
|
||||
@ -66,7 +66,7 @@ protected:
|
||||
|
||||
protected:
|
||||
LightMutex _lock;
|
||||
typedef pvector< PT(PartBundleHandle) > Bundles;
|
||||
typedef small_vector< PT(PartBundleHandle) > Bundles;
|
||||
Bundles _bundles;
|
||||
|
||||
public:
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "pandaNode.h"
|
||||
#include "nodePathCollection.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class JointVertexTransform;
|
||||
class Character;
|
||||
@ -77,11 +78,11 @@ private:
|
||||
// Not a reference-counted pointer.
|
||||
Character *_character;
|
||||
|
||||
typedef ov_set< PT(PandaNode) > NodeList;
|
||||
typedef ov_set<PT(PandaNode), std::less<PT(PandaNode)>, small_vector<PT(PandaNode)> > NodeList;
|
||||
NodeList _net_transform_nodes;
|
||||
NodeList _local_transform_nodes;
|
||||
|
||||
typedef ov_set<JointVertexTransform *> VertexTransforms;
|
||||
typedef ov_set<JointVertexTransform *, std::less<JointVertexTransform *>, small_vector<JointVertexTransform *> > VertexTransforms;
|
||||
VertexTransforms _vertex_transforms;
|
||||
|
||||
public:
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "cullTraverser.h"
|
||||
#include "callbackObject.h"
|
||||
#include "luse.h"
|
||||
#include "epvector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class GraphicsOutput;
|
||||
class GraphicsPipe;
|
||||
@ -197,7 +197,7 @@ public:
|
||||
LVecBase4i _pixels;
|
||||
LVecBase4i _pixels_i;
|
||||
};
|
||||
typedef epvector<Region> Regions;
|
||||
typedef small_vector<Region> Regions;
|
||||
|
||||
private:
|
||||
class CData;
|
||||
|
@ -777,7 +777,7 @@ render_frame() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_windows.swap(new_windows);
|
||||
_windows = std::move(new_windows);
|
||||
|
||||
// Go ahead and release any textures' ram images for textures that were
|
||||
// drawn in the previous frame.
|
||||
@ -969,7 +969,7 @@ open_windows() {
|
||||
|
||||
ReMutexHolder holder(_lock, current_thread);
|
||||
|
||||
pvector<PT(GraphicsOutput)> new_windows;
|
||||
NewWindows new_windows;
|
||||
{
|
||||
MutexHolder new_windows_holder(_new_windows_lock, current_thread);
|
||||
if (_new_windows.empty()) {
|
||||
@ -1016,7 +1016,7 @@ open_windows() {
|
||||
}
|
||||
|
||||
// Steal the list, since remove_window() may remove from _new_windows.
|
||||
new_windows.swap(_new_windows);
|
||||
new_windows = std::move(_new_windows);
|
||||
}
|
||||
|
||||
do_resort_windows();
|
||||
|
@ -322,7 +322,8 @@ private:
|
||||
// This lock protects the next two fields.
|
||||
Mutex _new_windows_lock;
|
||||
unsigned int _window_sort_index;
|
||||
pvector<PT(GraphicsOutput)> _new_windows;
|
||||
typedef small_vector<PT(GraphicsOutput)> NewWindows;
|
||||
NewWindows _new_windows;
|
||||
|
||||
WindowRenderer _app;
|
||||
typedef pmap<std::string, PT(RenderThread) > Threads;
|
||||
|
@ -1866,7 +1866,7 @@ make_lod(EggBin *egg_bin, PandaNode *parent) {
|
||||
|
||||
// Now that we've created all of our children, put them in the proper order
|
||||
// and tell the LOD node about them.
|
||||
sort(instances.begin(), instances.end());
|
||||
std::sort(instances.begin(), instances.end());
|
||||
|
||||
if (!instances.empty()) {
|
||||
// Set up the LOD node's center. All of the children should have the same
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "eventParameter.h"
|
||||
#include "patomic.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class AsyncTaskManager;
|
||||
class AsyncTask;
|
||||
@ -131,7 +132,7 @@ protected:
|
||||
std::string _done_event;
|
||||
|
||||
// Tasks and gathering futures waiting for this one to complete.
|
||||
Futures _waiting;
|
||||
small_vector<PT(AsyncFuture)> _waiting;
|
||||
|
||||
friend class AsyncGatheringFuture;
|
||||
friend class AsyncTaskChain;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "pandabase.h"
|
||||
#include "eventParameter.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class EventReceiver;
|
||||
|
||||
@ -60,7 +61,7 @@ PUBLISHED:
|
||||
MAKE_PROPERTY2(receiver, has_receiver, get_receiver, set_receiver, clear_receiver);
|
||||
|
||||
protected:
|
||||
typedef pvector<EventParameter> ParameterList;
|
||||
typedef small_vector<EventParameter> ParameterList;
|
||||
ParameterList _parameters;
|
||||
EventReceiver *_receiver;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
#include "pvector.h"
|
||||
|
||||
#ifndef CPPPARSER
|
||||
#include <functional>
|
||||
|
@ -587,7 +587,7 @@ INLINE void ordered_vector<Key, Compare, Vector>::
|
||||
sort_unique() {
|
||||
TAU_PROFILE("ordered_vector::sort_unique()", " ", TAU_USER);
|
||||
sort(begin(), end(), _compare);
|
||||
iterator new_end = unique(begin(), end(), EquivalentTest(_compare));
|
||||
iterator new_end = std::unique(begin(), end(), EquivalentTest(_compare));
|
||||
erase(new_end, end());
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "genericAsyncTask.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* This class serves to provide a high-level framework for basic applications
|
||||
@ -176,7 +177,7 @@ private:
|
||||
EventHandler &_event_handler;
|
||||
AsyncTaskManager &_task_mgr;
|
||||
|
||||
typedef pvector< PT(WindowFramework) > Windows;
|
||||
typedef small_vector< PT(WindowFramework) > Windows;
|
||||
Windows _windows;
|
||||
|
||||
typedef pmap< const GraphicsOutput *, NodePath > Mouses;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "textNode.h"
|
||||
#include "eventHandler.h"
|
||||
#include "genericAsyncTask.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class PandaFramework;
|
||||
class AmbientLight;
|
||||
@ -166,7 +167,7 @@ private:
|
||||
PT(DisplayRegion) _display_region_3d;
|
||||
|
||||
NodePath _camera_group;
|
||||
typedef pvector< PT(Camera) > Cameras;
|
||||
typedef small_vector< PT(Camera) > Cameras;
|
||||
Cameras _cameras;
|
||||
|
||||
NodePath _render;
|
||||
|
@ -98,7 +98,7 @@ PStatCollector CLP(GraphicsStateGuardian)::_copy_texture_finish_pcollector("Draw
|
||||
|
||||
#if defined(HAVE_CG) && !defined(OPENGLES)
|
||||
AtomicAdjust::Integer CLP(GraphicsStateGuardian)::_num_gsgs_with_cg_contexts = 0;
|
||||
pvector<CGcontext> CLP(GraphicsStateGuardian)::_destroyed_cg_contexts;
|
||||
small_vector<CGcontext> CLP(GraphicsStateGuardian)::_destroyed_cg_contexts;
|
||||
#endif
|
||||
|
||||
// The following noop functions are assigned to the corresponding glext
|
||||
|
@ -723,7 +723,7 @@ protected:
|
||||
#if defined(HAVE_CG) && !defined(OPENGLES)
|
||||
CGcontext _cg_context;
|
||||
static AtomicAdjust::Integer _num_gsgs_with_cg_contexts;
|
||||
static pvector<CGcontext> _destroyed_cg_contexts;
|
||||
static small_vector<CGcontext> _destroyed_cg_contexts;
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_IMMEDIATE_MODE
|
||||
@ -1201,7 +1201,7 @@ public:
|
||||
GLint64 _gpu_sync_time;
|
||||
double _cpu_sync_time;
|
||||
pvector<std::pair<GLuint, int> > _queries;
|
||||
pvector<GLint64> _latency_refs;
|
||||
small_vector<GLint64> _latency_refs;
|
||||
};
|
||||
pdeque<FrameTiming> _frame_timings;
|
||||
FrameTiming *_current_frame_timing = nullptr;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "shaderContext.h"
|
||||
#include "deletedChain.h"
|
||||
#include "paramTexture.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class CLP(GraphicsStateGuardian);
|
||||
|
||||
@ -68,7 +69,7 @@ public:
|
||||
private:
|
||||
bool _validated;
|
||||
GLuint _glsl_program;
|
||||
typedef pvector<GLuint> GLSLShaders;
|
||||
typedef small_vector<GLuint, 2> GLSLShaders;
|
||||
GLSLShaders _glsl_shaders;
|
||||
|
||||
WCPT(RenderState) _state_rs;
|
||||
|
@ -364,15 +364,13 @@ void GeomVertexFormat::
|
||||
remove_empty_arrays() {
|
||||
nassertv(!is_registered());
|
||||
|
||||
Arrays orig_arrays;
|
||||
orig_arrays.swap(_arrays);
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
|
||||
GeomVertexArrayFormat *array_format = (*ai);
|
||||
Arrays new_arrays;
|
||||
for (PT(GeomVertexArrayFormat) &array_format : _arrays) {
|
||||
if (array_format->get_num_columns() != 0) {
|
||||
_arrays.push_back(array_format);
|
||||
new_arrays.push_back(std::move(array_format));
|
||||
}
|
||||
}
|
||||
_arrays = std::move(new_arrays);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -382,9 +380,8 @@ remove_empty_arrays() {
|
||||
size_t GeomVertexFormat::
|
||||
get_num_columns() const {
|
||||
size_t num_columns = 0;
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
|
||||
num_columns += (*ai)->get_num_columns();
|
||||
for (GeomVertexArrayFormat *array_format : _arrays) {
|
||||
num_columns += array_format->get_num_columns();
|
||||
}
|
||||
return num_columns;
|
||||
}
|
||||
@ -394,12 +391,11 @@ get_num_columns() const {
|
||||
*/
|
||||
const GeomVertexColumn *GeomVertexFormat::
|
||||
get_column(size_t i) const {
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
|
||||
if (i < (size_t)(*ai)->get_num_columns()) {
|
||||
return (*ai)->get_column(i);
|
||||
for (GeomVertexArrayFormat *array_format : _arrays) {
|
||||
if (i < (size_t)array_format->get_num_columns()) {
|
||||
return array_format->get_column(i);
|
||||
}
|
||||
i -= (*ai)->get_num_columns();
|
||||
i -= array_format->get_num_columns();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -410,12 +406,11 @@ get_column(size_t i) const {
|
||||
*/
|
||||
const InternalName *GeomVertexFormat::
|
||||
get_column_name(size_t i) const {
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
|
||||
if (i < (size_t)(*ai)->get_num_columns()) {
|
||||
return (*ai)->get_column(i)->get_name();
|
||||
for (GeomVertexArrayFormat *array_format : _arrays) {
|
||||
if (i < (size_t)array_format->get_num_columns()) {
|
||||
return array_format->get_column(i)->get_name();
|
||||
}
|
||||
i -= (*ai)->get_num_columns();
|
||||
i -= array_format->get_num_columns();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -717,7 +712,7 @@ do_register() {
|
||||
nassertv(_columns_by_name.empty());
|
||||
|
||||
Arrays orig_arrays;
|
||||
orig_arrays.swap(_arrays);
|
||||
std::swap(orig_arrays, _arrays);
|
||||
Arrays::const_iterator ai;
|
||||
for (ai = orig_arrays.begin(); ai != orig_arrays.end(); ++ai) {
|
||||
CPT(GeomVertexArrayFormat) array_format = (*ai);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "pmap.h"
|
||||
#include "pset.h"
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
#include "indirectCompareTo.h"
|
||||
#include "lightReMutex.h"
|
||||
|
||||
@ -197,7 +198,7 @@ private:
|
||||
|
||||
GeomVertexAnimationSpec _animation;
|
||||
|
||||
typedef pvector< PT(GeomVertexArrayFormat) > Arrays;
|
||||
typedef small_vector<PT(GeomVertexArrayFormat), 2> Arrays;
|
||||
Arrays _arrays;
|
||||
|
||||
class DataTypeRecord {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "updateSeq.h"
|
||||
#include "luse.h"
|
||||
#include "ordered_vector.h"
|
||||
#include "small_vector.h"
|
||||
#include "cycleData.h"
|
||||
#include "cycleDataReader.h"
|
||||
#include "cycleDataWriter.h"
|
||||
@ -54,7 +55,7 @@ protected:
|
||||
void mark_modified(Thread *current_thread);
|
||||
|
||||
private:
|
||||
typedef ov_set<TransformTable *> Palettes;
|
||||
typedef ov_set<TransformTable *, std::less<TransformTable *>, small_vector<TransformTable *>> Palettes;
|
||||
Palettes _tables;
|
||||
|
||||
// This is the data that must be cycled between pipeline stages.
|
||||
|
@ -109,7 +109,7 @@ add_gsg(GraphicsStateGuardianBase *gsg) {
|
||||
|
||||
LightMutexHolder holder(gsg_list->_lock);
|
||||
|
||||
if (find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg) != gsg_list->_gsgs.end()) {
|
||||
if (std::find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg) != gsg_list->_gsgs.end()) {
|
||||
// Already on the list.
|
||||
return;
|
||||
}
|
||||
@ -135,7 +135,7 @@ remove_gsg(GraphicsStateGuardianBase *gsg) {
|
||||
LightMutexHolder holder(gsg_list->_lock);
|
||||
|
||||
GSGList::GSGs::iterator gi;
|
||||
gi = find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg);
|
||||
gi = std::find(gsg_list->_gsgs.begin(), gsg_list->_gsgs.end(), gsg);
|
||||
if (gi == gsg_list->_gsgs.end()) {
|
||||
// Already removed, or never added.
|
||||
return;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "luse.h"
|
||||
#include "lightMutex.h"
|
||||
#include "patomic.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
// A handful of forward references.
|
||||
|
||||
@ -263,7 +264,7 @@ private:
|
||||
struct GSGList {
|
||||
LightMutex _lock;
|
||||
|
||||
typedef pvector<GraphicsStateGuardianBase *> GSGs;
|
||||
typedef small_vector<GraphicsStateGuardianBase *> GSGs;
|
||||
GSGs _gsgs;
|
||||
GraphicsStateGuardianBase *_default_gsg = nullptr;
|
||||
};
|
||||
|
@ -213,7 +213,7 @@ wrap_hpr() {
|
||||
*/
|
||||
void CurveFitter::
|
||||
sort_points() {
|
||||
sort(_data.begin(), _data.end());
|
||||
std::sort(_data.begin(), _data.end());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -249,7 +249,7 @@ add_display_region(DisplayRegion *display_region) {
|
||||
void Camera::
|
||||
remove_display_region(DisplayRegion *display_region) {
|
||||
DisplayRegions::iterator dri =
|
||||
find(_display_regions.begin(), _display_regions.end(), display_region);
|
||||
std::find(_display_regions.begin(), _display_regions.end(), display_region);
|
||||
if (dri != _display_regions.end()) {
|
||||
_display_regions.erase(dri);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "renderState.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pmap.h"
|
||||
#include "small_vector.h"
|
||||
#include "auxSceneData.h"
|
||||
|
||||
class DisplayRegion;
|
||||
@ -115,7 +116,7 @@ private:
|
||||
DrawMask _camera_mask;
|
||||
PN_stdfloat _lod_scale;
|
||||
|
||||
typedef pvector<DisplayRegion *> DisplayRegions;
|
||||
typedef small_vector<DisplayRegion *> DisplayRegions;
|
||||
DisplayRegions _display_regions;
|
||||
|
||||
CPT(RenderState) _initial_state;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "lens.h"
|
||||
#include "perspectiveLens.h"
|
||||
#include "pointerTo.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* A node that contains a Lens. The most important example of this kind of
|
||||
@ -67,7 +68,7 @@ protected:
|
||||
bool _is_active;
|
||||
};
|
||||
|
||||
typedef pvector<LensSlot> Lenses;
|
||||
typedef small_vector<LensSlot> Lenses;
|
||||
Lenses _lenses;
|
||||
|
||||
public:
|
||||
|
@ -4030,8 +4030,7 @@ complete_up_list(PandaNode::Up &up_list, const string &tag,
|
||||
new_up_list.sort();
|
||||
|
||||
// Make it permanent.
|
||||
up_list.swap(new_up_list);
|
||||
new_up_list.clear();
|
||||
up_list = std::move(new_up_list);
|
||||
|
||||
return pi;
|
||||
}
|
||||
@ -4060,8 +4059,7 @@ complete_down_list(PandaNode::Down &down_list, const string &tag,
|
||||
// should be preserved from one session to the next.
|
||||
|
||||
// Make it permanent.
|
||||
down_list.swap(new_down_list);
|
||||
new_down_list.clear();
|
||||
down_list = std::move(new_down_list);
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "extension.h"
|
||||
#include "simpleHashMap.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
class NodePathComponent;
|
||||
class CullTraverser;
|
||||
@ -520,7 +521,7 @@ private:
|
||||
// children do not circularly reference each other.
|
||||
PandaNode *_parent;
|
||||
};
|
||||
typedef ov_set<UpConnection> UpList;
|
||||
typedef ov_set<UpConnection, std::less<UpConnection>, small_vector<UpConnection> > UpList;
|
||||
typedef CopyOnWriteObj1< UpList, TypeHandle > Up;
|
||||
|
||||
// We also maintain a set of NodePathComponents in the node. This
|
||||
|
@ -548,11 +548,10 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
// For now, read in a linear list of the modes we will assign to each
|
||||
// associated TextureStage pointer. Later, in complete_pointers, we'll fill
|
||||
// up the map the with appropriate TextureStageMode pairing.
|
||||
_read_modes.clear();
|
||||
_read_modes.reserve(num_stages);
|
||||
_read_modes.resize(num_stages);
|
||||
for (size_t i = 0; i < num_stages; i++) {
|
||||
manager->read_pointer(scan);
|
||||
Mode mode = (Mode)scan.get_uint8();
|
||||
_read_modes.push_back(mode);
|
||||
_read_modes[i] = mode;
|
||||
}
|
||||
}
|
||||
|
@ -319,8 +319,8 @@ filter_to_max(int max_texture_stages) const {
|
||||
RenderStages priority_stages = _render_stages;
|
||||
|
||||
// This sort function uses the STL function object defined above.
|
||||
sort(priority_stages.begin(), priority_stages.end(),
|
||||
CompareTextureStagePriorities());
|
||||
std::sort(priority_stages.begin(), priority_stages.end(),
|
||||
CompareTextureStagePriorities());
|
||||
|
||||
// Now lop off all of the stages after the first max_texture_stages.
|
||||
priority_stages.erase(priority_stages.begin() + max_texture_stages,
|
||||
@ -979,8 +979,8 @@ sort_on_stages() {
|
||||
_render_stages.push_back(&sn);
|
||||
}
|
||||
|
||||
sort(_render_stages.begin(), _render_stages.end(), CompareTextureStageSort());
|
||||
sort(_render_ff_stages.begin(), _render_ff_stages.end(), CompareTextureStageSort());
|
||||
std::sort(_render_stages.begin(), _render_stages.end(), CompareTextureStageSort());
|
||||
std::sort(_render_ff_stages.begin(), _render_ff_stages.end(), CompareTextureStageSort());
|
||||
|
||||
// We'd like to clear the _filtered map, in case the TextureStage priority
|
||||
// values have changed as well, but we can't do that here: it's too
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ordered_vector.h"
|
||||
#include "vector_int.h"
|
||||
#include "epvector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* Indicates the set of TextureStages and their associated Textures that
|
||||
@ -147,7 +148,7 @@ private:
|
||||
typedef ov_set<StageNode, CompareTextureStagePointer, epvector<StageNode> > Stages;
|
||||
Stages _on_stages; // set of all "on" stages, indexed by pointer.
|
||||
|
||||
typedef pvector<StageNode *> RenderStages;
|
||||
typedef small_vector<StageNode *> RenderStages;
|
||||
RenderStages _render_stages; // all "on" stages, sorted in render order.
|
||||
RenderStages _render_ff_stages; // fixed-function stages only, in render order.
|
||||
unsigned int _next_implicit_sort;
|
||||
|
@ -125,9 +125,8 @@ do_callback(CallbackData *cbdata) {
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
|
||||
Dispatches::const_iterator it;
|
||||
for (it = cdata->_dispatches.begin(); it != cdata->_dispatches.end(); ++it) {
|
||||
gsg->dispatch_compute(it->get_x(), it->get_y(), it->get_z());
|
||||
for (const LVecBase3i &dispatch : cdata->_dispatches) {
|
||||
gsg->dispatch_compute(dispatch[0], dispatch[1], dispatch[2]);
|
||||
}
|
||||
|
||||
// No need to upcall; we don't have any geometry, after all.
|
||||
@ -194,9 +193,8 @@ void ComputeNode::Dispatcher::CData::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) const {
|
||||
dg.add_uint16(_dispatches.size());
|
||||
|
||||
Dispatches::const_iterator it;
|
||||
for (it = _dispatches.begin(); it != _dispatches.end(); ++it) {
|
||||
generic_write_datagram(dg, *it);
|
||||
for (const LVecBase3i &dispatch : _dispatches) {
|
||||
generic_write_datagram(dg, dispatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "callbackObject.h"
|
||||
#include "callbackNode.h"
|
||||
#include "pointerTo.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* A special node, the sole purpose of which is to invoke a dispatch operation
|
||||
@ -61,7 +62,7 @@ public:
|
||||
|
||||
virtual void do_callback(CallbackData *cbdata);
|
||||
|
||||
typedef pvector<LVecBase3i> Dispatches;
|
||||
typedef small_vector<LVecBase3i> Dispatches;
|
||||
|
||||
class EXPCL_PANDA_PGRAPHNODES CData : public CycleData {
|
||||
public:
|
||||
|
@ -698,10 +698,8 @@ get_text_def(int state) const {
|
||||
// If we don't have a definition, use the global one.
|
||||
return get_text_node();
|
||||
}
|
||||
if (_text_defs[state] == nullptr) {
|
||||
return get_text_node();
|
||||
}
|
||||
return _text_defs[state];
|
||||
TextNode *text_def = _text_defs[state];
|
||||
return text_def ? text_def : get_text_node();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -750,8 +748,8 @@ is_wtext() const {
|
||||
*/
|
||||
void PGEntry::
|
||||
slot_text_def(int state) {
|
||||
while (state >= (int)_text_defs.size()) {
|
||||
_text_defs.push_back(nullptr);
|
||||
if (state >= (int)_text_defs.size()) {
|
||||
_text_defs.resize(state + 1, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include "textNode.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
#include "clockObject.h"
|
||||
#include "textAssembler.h"
|
||||
#include "pipeline.h"
|
||||
@ -168,7 +168,8 @@ private:
|
||||
std::string _candidate_active;
|
||||
std::string _candidate_inactive;
|
||||
|
||||
typedef pvector< PT(TextNode) > TextDefs;
|
||||
// Most entries have 3 states.
|
||||
typedef small_vector<PT(TextNode), 3> TextDefs;
|
||||
TextDefs _text_defs;
|
||||
|
||||
// This is the subgraph that renders both the text and the cursor.
|
||||
|
@ -403,7 +403,7 @@ write_status(std::ostream &out) const {
|
||||
out << "Sleeping:";
|
||||
// Copy and sort for convenience.
|
||||
Sleeping s2 = _sleeping;
|
||||
sort(s2.begin(), s2.end(), CompareStartTime());
|
||||
std::sort(s2.begin(), s2.end(), CompareStartTime());
|
||||
for (si = s2.begin(); si != s2.end(); ++si) {
|
||||
out << " " << *(*si)->_parent_obj << "(" << (*si)->_wake_time - now
|
||||
<< "s)";
|
||||
|
@ -604,7 +604,7 @@ write_data(xel *array, xelval *alpha_data) {
|
||||
|
||||
// Re-sort the palette to put the semitransparent pixels at the
|
||||
// beginning.
|
||||
sort(palette.begin(), palette.end(), LowAlphaCompare());
|
||||
std::sort(palette.begin(), palette.end(), LowAlphaCompare());
|
||||
|
||||
double palette_scale = 255.0 / _maxval;
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#define SIMPLEHASHMAP_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "pvector.h"
|
||||
#include "config_putil.h"
|
||||
|
||||
/**
|
||||
|
@ -16,12 +16,13 @@
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "dataNode.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "buttonEventList.h"
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
#include "dataNode.h"
|
||||
#include "eventParameter.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "pmap.h"
|
||||
#include "pvector.h"
|
||||
#include "small_vector.h"
|
||||
|
||||
/**
|
||||
* Throws Panda Events for button down/up events generated within the data
|
||||
@ -115,7 +116,7 @@ private:
|
||||
bool _time_flag;
|
||||
ModifierButtons _mods;
|
||||
|
||||
typedef pvector<EventParameter> ParameterList;
|
||||
typedef small_vector<EventParameter> ParameterList;
|
||||
ParameterList _parameters;
|
||||
|
||||
typedef pvector<ModifierButtons> ThrowButtonDef;
|
||||
|
@ -575,7 +575,7 @@ get_over_regions(MouseWatcher::Regions ®ions, const LPoint2 &pos) const {
|
||||
// Now sort the regions by pointer. By convention, the Regions vectors are
|
||||
// always kept in order by pointer, so we can do easy linear comparison and
|
||||
// intersection operations.
|
||||
sort(regions.begin(), regions.end());
|
||||
std::sort(regions.begin(), regions.end());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user