Changeset View
Changeset View
Standalone View
Standalone View
src/prevector.h
Show First 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | |||||
private: | private: | ||||
#pragma pack(push, 1) | #pragma pack(push, 1) | ||||
union direct_or_indirect { | union direct_or_indirect { | ||||
char direct[sizeof(T) * N]; | char direct[sizeof(T) * N]; | ||||
struct { | struct { | ||||
char *indirect; | char *indirect; | ||||
size_type capacity; | size_type capacity; | ||||
}; | } indirect_contents; | ||||
}; | }; | ||||
#pragma pack(pop) | #pragma pack(pop) | ||||
alignas(char *) direct_or_indirect _union = {}; | alignas(char *) direct_or_indirect _union = {}; | ||||
size_type _size = 0; | size_type _size = 0; | ||||
static_assert(alignof(char *) % alignof(size_type) == 0 && | static_assert(alignof(char *) % alignof(size_type) == 0 && | ||||
sizeof(char *) % alignof(size_type) == 0, | sizeof(char *) % alignof(size_type) == 0, | ||||
"size_type cannot have more restrictive alignment " | "size_type cannot have more restrictive alignment " | ||||
"requirement than pointer"); | "requirement than pointer"); | ||||
static_assert(alignof(char *) % alignof(T) == 0, | static_assert(alignof(char *) % alignof(T) == 0, | ||||
"value_type T cannot have more restrictive alignment " | "value_type T cannot have more restrictive alignment " | ||||
"requirement than pointer"); | "requirement than pointer"); | ||||
T *direct_ptr(difference_type pos) { | T *direct_ptr(difference_type pos) { | ||||
return reinterpret_cast<T *>(_union.direct) + pos; | return reinterpret_cast<T *>(_union.direct) + pos; | ||||
} | } | ||||
const T *direct_ptr(difference_type pos) const { | const T *direct_ptr(difference_type pos) const { | ||||
return reinterpret_cast<const T *>(_union.direct) + pos; | return reinterpret_cast<const T *>(_union.direct) + pos; | ||||
} | } | ||||
T *indirect_ptr(difference_type pos) { | T *indirect_ptr(difference_type pos) { | ||||
return reinterpret_cast<T *>(_union.indirect) + pos; | return reinterpret_cast<T *>(_union.indirect_contents.indirect) + pos; | ||||
} | } | ||||
const T *indirect_ptr(difference_type pos) const { | const T *indirect_ptr(difference_type pos) const { | ||||
return reinterpret_cast<const T *>(_union.indirect) + pos; | return reinterpret_cast<const T *>(_union.indirect_contents.indirect) + | ||||
pos; | |||||
} | } | ||||
bool is_direct() const { return _size <= N; } | bool is_direct() const { return _size <= N; } | ||||
void change_capacity(size_type new_capacity) { | void change_capacity(size_type new_capacity) { | ||||
if (new_capacity <= N) { | if (new_capacity <= N) { | ||||
if (!is_direct()) { | if (!is_direct()) { | ||||
T *indirect = indirect_ptr(0); | T *indirect = indirect_ptr(0); | ||||
T *src = indirect; | T *src = indirect; | ||||
T *dst = direct_ptr(0); | T *dst = direct_ptr(0); | ||||
memcpy(dst, src, size() * sizeof(T)); | memcpy(dst, src, size() * sizeof(T)); | ||||
free(indirect); | free(indirect); | ||||
_size -= N + 1; | _size -= N + 1; | ||||
} | } | ||||
} else { | } else { | ||||
if (!is_direct()) { | if (!is_direct()) { | ||||
// FIXME: Because malloc/realloc here won't call new_handler if | // FIXME: Because malloc/realloc here won't call new_handler if | ||||
// allocation fails, assert success. These should instead use an | // allocation fails, assert success. These should instead use an | ||||
// allocator or new/delete so that handlers are called as | // allocator or new/delete so that handlers are called as | ||||
// necessary, but performance would be slightly degraded by | // necessary, but performance would be slightly degraded by | ||||
// doing so. | // doing so. | ||||
_union.indirect = static_cast<char *>(realloc( | _union.indirect_contents.indirect = static_cast<char *>( | ||||
_union.indirect, ((size_t)sizeof(T)) * new_capacity)); | realloc(_union.indirect_contents.indirect, | ||||
assert(_union.indirect); | ((size_t)sizeof(T)) * new_capacity)); | ||||
_union.capacity = new_capacity; | assert(_union.indirect_contents.indirect); | ||||
_union.indirect_contents.capacity = new_capacity; | |||||
} else { | } else { | ||||
char *new_indirect = static_cast<char *>( | char *new_indirect = static_cast<char *>( | ||||
malloc(((size_t)sizeof(T)) * new_capacity)); | malloc(((size_t)sizeof(T)) * new_capacity)); | ||||
assert(new_indirect); | assert(new_indirect); | ||||
T *src = direct_ptr(0); | T *src = direct_ptr(0); | ||||
T *dst = reinterpret_cast<T *>(new_indirect); | T *dst = reinterpret_cast<T *>(new_indirect); | ||||
memcpy(dst, src, size() * sizeof(T)); | memcpy(dst, src, size() * sizeof(T)); | ||||
_union.indirect = new_indirect; | _union.indirect_contents.indirect = new_indirect; | ||||
_union.capacity = new_capacity; | _union.indirect_contents.capacity = new_capacity; | ||||
_size += N + 1; | _size += N + 1; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
T *item_ptr(difference_type pos) { | T *item_ptr(difference_type pos) { | ||||
return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); | return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | public: | ||||
const_reverse_iterator rend() const { | const_reverse_iterator rend() const { | ||||
return const_reverse_iterator(item_ptr(-1)); | return const_reverse_iterator(item_ptr(-1)); | ||||
} | } | ||||
size_t capacity() const { | size_t capacity() const { | ||||
if (is_direct()) { | if (is_direct()) { | ||||
return N; | return N; | ||||
} else { | } else { | ||||
return _union.capacity; | return _union.indirect_contents.capacity; | ||||
} | } | ||||
} | } | ||||
T &operator[](size_type pos) { return *item_ptr(pos); } | T &operator[](size_type pos) { return *item_ptr(pos); } | ||||
const T &operator[](size_type pos) const { return *item_ptr(pos); } | const T &operator[](size_type pos) const { return *item_ptr(pos); } | ||||
void resize(size_type new_size) { | void resize(size_type new_size) { | ||||
▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | void swap(prevector<N, T, Size, Diff> &other) { | ||||
std::swap(_size, other._size); | std::swap(_size, other._size); | ||||
} | } | ||||
~prevector() { | ~prevector() { | ||||
if (!std::is_trivially_destructible<T>::value) { | if (!std::is_trivially_destructible<T>::value) { | ||||
clear(); | clear(); | ||||
} | } | ||||
if (!is_direct()) { | if (!is_direct()) { | ||||
free(_union.indirect); | free(_union.indirect_contents.indirect); | ||||
_union.indirect = nullptr; | _union.indirect_contents.indirect = nullptr; | ||||
} | } | ||||
} | } | ||||
bool operator==(const prevector<N, T, Size, Diff> &other) const { | bool operator==(const prevector<N, T, Size, Diff> &other) const { | ||||
if (other.size() != size()) { | if (other.size() != size()) { | ||||
return false; | return false; | ||||
} | } | ||||
const_iterator b1 = begin(); | const_iterator b1 = begin(); | ||||
Show All 35 Lines | bool operator<(const prevector<N, T, Size, Diff> &other) const { | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
size_t allocated_memory() const { | size_t allocated_memory() const { | ||||
if (is_direct()) { | if (is_direct()) { | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
return ((size_t)(sizeof(T))) * _union.capacity; | return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity; | ||||
} | } | ||||
} | } | ||||
value_type *data() { return item_ptr(0); } | value_type *data() { return item_ptr(0); } | ||||
const value_type *data() const { return item_ptr(0); } | const value_type *data() const { return item_ptr(0); } | ||||
}; | }; | ||||
#endif // BITCOIN_PREVECTOR_H | #endif // BITCOIN_PREVECTOR_H |