osrm-backend/DataStructures/DeallocatingVector.h

325 lines
11 KiB
C
Raw Normal View History

2012-05-23 15:22:33 -04:00
/*
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
2012-05-23 15:22:33 -04:00
#ifndef DEALLOCATINGVECTOR_H_
#define DEALLOCATINGVECTOR_H_
#include <cassert>
2013-10-13 11:55:50 -04:00
#include <cstring>
2012-05-23 15:22:33 -04:00
#include <vector>
#if __cplusplus > 199711L
#define DEALLOCATION_VECTOR_NULL_PTR nullptr
#else
#define DEALLOCATION_VECTOR_NULL_PTR NULL
#endif
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
2012-05-23 15:22:33 -04:00
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
protected:
class DeallocatingVectorIteratorState {
private:
2012-05-23 15:22:33 -04:00
//make constructors explicit, so we do not mix random access and deallocation iterators.
DeallocatingVectorIteratorState();
public:
2013-10-15 05:56:27 -04:00
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
2012-05-23 15:22:33 -04:00
}
std::size_t mIndex;
2012-05-23 15:22:33 -04:00
std::vector<ElementT *> & mBucketList;
2012-08-27 10:16:59 -04:00
2012-05-23 15:22:33 -04:00
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
2013-10-15 05:56:27 -04:00
return mIndex != other.mIndex;
2012-05-23 15:22:33 -04:00
}
inline bool operator==(const DeallocatingVectorIteratorState &other) {
2013-10-15 05:56:27 -04:00
return mIndex == other.mIndex;
2012-05-23 15:22:33 -04:00
}
bool operator<(const DeallocatingVectorIteratorState &other) const {
2012-05-23 15:22:33 -04:00
return mIndex < other.mIndex;
}
bool operator>(const DeallocatingVectorIteratorState &other) const {
return mIndex > other.mIndex;
}
bool operator>=(const DeallocatingVectorIteratorState &other) const {
return mIndex >= other.mIndex;
}
2012-05-23 15:22:33 -04:00
//This is a hack to make assignment operator possible with reference member
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
if (this != &a) {
this->DeallocatingVectorIteratorState::~DeallocatingVectorIteratorState(); // explicit non-virtual destructor
new (this) DeallocatingVectorIteratorState(a); // placement new
}
return *this;
}
};
DeallocatingVectorIteratorState mState;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::value_type value_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::difference_type difference_type;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::reference reference;
typedef typename std::iterator<std::random_access_iterator_tag, ElementT>::pointer pointer;
DeallocatingVectorIterator() {}
template<typename T2>
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
2012-08-27 10:16:59 -04:00
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
2012-05-23 15:22:33 -04:00
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
template<typename T2>
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
if(DeallocateC) assert(false);
mState = r.mState; return *this;
}
inline DeallocatingVectorIterator& operator++() { //prefix
2013-10-15 05:56:27 -04:00
++mState.mIndex;
return *this;
2012-05-23 15:22:33 -04:00
}
inline DeallocatingVectorIterator& operator--() { //prefix
if(DeallocateC) assert(false);
2013-10-15 05:56:27 -04:00
--mState.mIndex;
return *this;
2012-05-23 15:22:33 -04:00
}
inline DeallocatingVectorIterator operator++(int) { //postfix
DeallocatingVectorIteratorState _myState(mState);
2013-10-15 05:56:27 -04:00
mState.mIndex++;
2012-05-23 15:22:33 -04:00
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator operator--(int) { //postfix
2012-05-23 15:22:33 -04:00
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
2013-10-15 05:56:27 -04:00
mState.mIndex--;
2012-05-23 15:22:33 -04:00
return DeallocatingVectorIterator(_myState);
}
2012-11-22 09:41:29 -05:00
2012-05-23 15:22:33 -04:00
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
DeallocatingVectorIteratorState _myState(mState);
2013-10-15 05:56:27 -04:00
_myState.mIndex+=n;
2012-05-23 15:22:33 -04:00
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
2012-05-23 15:22:33 -04:00
mState.mIndex+=n; return *this;
}
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
if(DeallocateC) assert(false);
DeallocatingVectorIteratorState _myState(mState);
2013-10-15 05:56:27 -04:00
_myState.mIndex-=n;
2012-05-23 15:22:33 -04:00
return DeallocatingVectorIterator(_myState);
}
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
if(DeallocateC) assert(false);
mState.mIndex-=n; return *this;
}
2013-10-15 05:56:27 -04:00
inline reference operator*() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return (mState.mBucketList[_bucket][_index]);
}
inline pointer operator->() const {
std::size_t _bucket = mState.mIndex/bucketSizeC;
std::size_t _index = mState.mIndex%bucketSizeC;
return &(mState.mBucketList[_bucket][_index]);
2012-05-23 15:22:33 -04:00
}
inline bool operator!=(const DeallocatingVectorIterator & other) {
return mState != other.mState;
}
inline bool operator==(const DeallocatingVectorIterator & other) {
return mState == other.mState;
}
inline bool operator<(const DeallocatingVectorIterator & other) const {
2012-05-23 15:22:33 -04:00
return mState < other.mState;
}
inline bool operator>(const DeallocatingVectorIterator & other) const {
return mState > other.mState;
}
inline bool operator>=(const DeallocatingVectorIterator & other) const {
return mState >= other.mState;
}
2012-05-23 15:22:33 -04:00
difference_type operator-(const DeallocatingVectorIterator & other) {
if(DeallocateC) assert(false);
return mState.mIndex-other.mState.mIndex;
}
};
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
2012-05-23 15:22:33 -04:00
class DeallocatingVector {
private:
std::size_t mCurrentSize;
2012-05-23 15:22:33 -04:00
std::vector<ElementT *> mBucketList;
public:
typedef ElementT value_type;
2012-05-23 15:22:33 -04:00
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> iterator;
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, false> const_iterator;
//this iterator deallocates all buckets that have been visited. Iterators to visited objects become invalid.
typedef DeallocatingVectorIterator<ElementT, bucketSizeC, true> deallocation_iterator;
DeallocatingVector() : mCurrentSize(0) {
//initial bucket
mBucketList.push_back(new ElementT[bucketSizeC]);
}
~DeallocatingVector() {
clear();
}
inline void swap(DeallocatingVector<ElementT, bucketSizeC> & other) {
std::swap(mCurrentSize, other.mCurrentSize);
mBucketList.swap(other.mBucketList);
}
inline void clear() {
//Delete[]'ing ptr's to all Buckets
for(unsigned i = 0; i < mBucketList.size(); ++i) {
if(DEALLOCATION_VECTOR_NULL_PTR != mBucketList[i]) {
2012-11-22 09:41:29 -05:00
delete[] mBucketList[i];
mBucketList[i] = DEALLOCATION_VECTOR_NULL_PTR;
2012-05-23 15:22:33 -04:00
}
}
//Removing all ptrs from vector
std::vector<ElementT *>().swap(mBucketList);
2012-11-22 09:41:29 -05:00
mCurrentSize = 0;
2012-05-23 15:22:33 -04:00
}
inline void push_back(const ElementT & element) {
std::size_t _capacity = capacity();
2012-05-23 15:22:33 -04:00
if(mCurrentSize == _capacity) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
std::size_t _index = size()%bucketSizeC;
2012-05-23 15:22:33 -04:00
mBucketList.back()[_index] = element;
++mCurrentSize;
}
inline void reserve(const std::size_t) const {
2012-08-27 10:16:59 -04:00
//don't do anything
}
inline void resize(const std::size_t new_size) {
2012-08-27 10:16:59 -04:00
if(new_size > mCurrentSize) {
while(capacity() < new_size) {
mBucketList.push_back(new ElementT[bucketSizeC]);
}
mCurrentSize = new_size;
}
if(new_size < mCurrentSize) {
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
2012-08-27 10:16:59 -04:00
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
delete[] mBucketList[i];
}
mBucketList.resize(number_of_necessary_buckets);
mCurrentSize = new_size;
}
}
inline std::size_t size() const {
2012-05-23 15:22:33 -04:00
return mCurrentSize;
}
inline std::size_t capacity() const {
2012-05-23 15:22:33 -04:00
return mBucketList.size() * bucketSizeC;
}
inline iterator begin() {
return iterator(static_cast<std::size_t>(0), mBucketList);
2012-05-23 15:22:33 -04:00
}
inline iterator end() {
return iterator(size(), mBucketList);
}
inline deallocation_iterator dbegin() {
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
2012-05-23 15:22:33 -04:00
}
inline deallocation_iterator dend() {
return deallocation_iterator(size(), mBucketList);
}
inline const_iterator begin() const {
return const_iterator(static_cast<std::size_t>(0), mBucketList);
2012-05-23 15:22:33 -04:00
}
inline const_iterator end() const {
return const_iterator(size(), mBucketList);
}
inline ElementT & operator[](const std::size_t index) {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
2012-05-23 15:22:33 -04:00
return (mBucketList[_bucket][_index]);
}
const inline ElementT & operator[](const std::size_t index) const {
std::size_t _bucket = index / bucketSizeC;
std::size_t _index = index % bucketSizeC;
2012-05-23 15:22:33 -04:00
return (mBucketList[_bucket][_index]);
}
inline ElementT & back() {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
const inline ElementT & back() const {
std::size_t _bucket = mCurrentSize / bucketSizeC;
std::size_t _index = mCurrentSize % bucketSizeC;
return (mBucketList[_bucket][_index]);
}
2012-05-23 15:22:33 -04:00
};
#endif /* DEALLOCATINGVECTOR_H_ */