Skip to content

Commit

Permalink
Changed OEL_DEBUG_HEADER_OF to function, got rid of _makeIter
Browse files Browse the repository at this point in the history
Also refined dynarray_iterator a little.
And [[nodiscard]] dynarray::empty
  • Loading branch information
OleErikPeistorpet committed Sep 29, 2023
1 parent 9d1ef72 commit c91858b
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 66 deletions.
19 changes: 11 additions & 8 deletions auxi/allocate_with_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ namespace oel::_detail

inline constexpr DebugAllocationHeader headerNoAllocation{};

#define OEL_DEBUG_HEADER_OF(ptr) ( (DebugAllocationHeader *)static_cast<void *>(ptr) - 1)
#define OEL_DEBUG_HEADER_OF_C(ptr) ((const DebugAllocationHeader *)static_cast<const void *>(ptr) - 1)
OEL_ALWAYS_INLINE inline DebugAllocationHeader * DebugHeaderOf(void * p)
{
return static_cast<DebugAllocationHeader *>(p) - 1;
}

template< typename T >
inline bool HasValidIndex(const T * arrayElem, const DebugAllocationHeader & h)
{
size_t index = arrayElem - reinterpret_cast<const T *>(&h + 1);
return index < h.nObjects;
auto index = arrayElem - reinterpret_cast<const T *>(&h + 1);
return static_cast<size_t>(index) < h.nObjects;
}

template< typename Alloc, typename Ptr >
Expand All @@ -45,7 +47,8 @@ namespace oel::_detail
{
p += sizeForHeader;

auto const h = OEL_DEBUG_HEADER_OF(p);
auto const h = _detail::DebugHeaderOf(p);
// Take address, set highest and lowest bits for a hopefully unique bit pattern to compare later
constexpr auto maxMinBits = ~(~std::uintptr_t{} >> 1) | 1u;
new(h) DebugAllocationHeader{reinterpret_cast<std::uintptr_t>(&a) | maxMinBits, 0};

Expand All @@ -68,7 +71,7 @@ namespace oel::_detail
#if OEL_MEM_BOUND_DEBUG_LVL
if (p)
{ // volatile to make sure the write isn't optimized away
static_cast<volatile std::uintptr_t &>(OEL_DEBUG_HEADER_OF(p)->id) = 0;
static_cast<volatile std::uintptr_t &>(_detail::DebugHeaderOf(p)->id) = 0;
p -= sizeForHeader;
}
n += sizeForHeader;
Expand All @@ -82,7 +85,7 @@ namespace oel::_detail
static void dealloc(Alloc & a, Ptr p, size_t n) noexcept(noexcept( a.deallocate(p, n) ))
{
#if OEL_MEM_BOUND_DEBUG_LVL
static_cast<volatile std::uintptr_t &>(OEL_DEBUG_HEADER_OF(p)->id) = 0;
static_cast<volatile std::uintptr_t &>(_detail::DebugHeaderOf(p)->id) = 0;
p -= sizeForHeader;
n += sizeForHeader;
#endif
Expand All @@ -102,7 +105,7 @@ namespace oel::_detail
{
if (container.data)
{
auto h = OEL_DEBUG_HEADER_OF(container.data);
auto h = _detail::DebugHeaderOf(container.data);
h->nObjects = container.end - container.data;
}
}
Expand Down
69 changes: 38 additions & 31 deletions auxi/dynarray_iterator.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

// Copyright 2014, 2015 Ole Erik Peistorpet
// Copyright 2015 Ole Erik Peistorpet
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand Down Expand Up @@ -35,9 +35,9 @@ class dynarray_iterator

#if OEL_MEM_BOUND_DEBUG_LVL >= 2
// Test for iterator pair pointing to same container
#define OEL_ITER_CHECK_COMPATIBLE(other) OEL_ASSERT(_allocationId == other._allocationId)
#define OEL_ITER_CHECK_COMPATIBLE(a, b) OEL_ASSERT((a)._allocationId == (b)._allocationId)
#else
#define OEL_ITER_CHECK_COMPATIBLE(other)
#define OEL_ITER_CHECK_COMPATIBLE(a, b)
#endif

public:
Expand Down Expand Up @@ -71,26 +71,26 @@ class dynarray_iterator
}

dynarray_iterator & operator++() & OEL_ALWAYS_INLINE
{ // preincrement
{
++_pElem;
return *this;
}

dynarray_iterator operator++(int) &
{ // postincrement
{ // post-increment
auto tmp = *this;
++_pElem;
return tmp;
}

dynarray_iterator & operator--() & OEL_ALWAYS_INLINE
{ // predecrement
{
--_pElem;
return *this;
}

dynarray_iterator operator--(int) &
{ // postdecrement
{ // post-decrement
auto tmp = *this;
--_pElem;
return tmp;
Expand All @@ -108,66 +108,67 @@ class dynarray_iterator
return *this;
}

friend dynarray_iterator operator +(difference_type offset, dynarray_iterator it)
[[nodiscard]] friend dynarray_iterator operator +(difference_type offset, dynarray_iterator it)
{
return it += offset;
it._pElem += offset;
return it;
}

friend dynarray_iterator operator +(dynarray_iterator it, difference_type offset)
[[nodiscard]] friend dynarray_iterator operator +(dynarray_iterator it, difference_type offset)
{
return it += offset;
it._pElem += offset;
return it;
}

friend dynarray_iterator operator -(dynarray_iterator it, difference_type offset)
[[nodiscard]] friend dynarray_iterator operator -(dynarray_iterator it, difference_type offset)
{
return it -= offset;
it._pElem -= offset;
return it;
}

difference_type operator -(const const_iterator & right) const
{ // difference of iterators
OEL_ITER_CHECK_COMPATIBLE(right);
return _pElem - right._pElem;
friend difference_type operator -(const dynarray_iterator & left, const dynarray_iterator & right)
{
OEL_ITER_CHECK_COMPATIBLE(left, right);
return left._pElem - right._pElem;
}

reference operator[](difference_type offset) const
{
auto tmp = *this;
tmp += offset; // not operator + to save a call in non-optimized builds
return *tmp;
return *(*this + offset);
}

template< typename Ptr1 >
bool operator==(const dynarray_iterator<Ptr1> & right) const
{
OEL_ITER_CHECK_COMPATIBLE(right);
OEL_ITER_CHECK_COMPATIBLE(*this, right);
return _pElem == right._pElem;
}

template< typename Ptr1 >
bool operator!=(const dynarray_iterator<Ptr1> & right) const
{
OEL_ITER_CHECK_COMPATIBLE(right);
OEL_ITER_CHECK_COMPATIBLE(*this, right);
return _pElem != right._pElem;
}

template< typename Ptr1 >
bool operator <(const dynarray_iterator<Ptr1> & right) const
{
OEL_ITER_CHECK_COMPATIBLE(right);
OEL_ITER_CHECK_COMPATIBLE(*this, right);
return _pElem < right._pElem;
}

template< typename Ptr1 >
bool operator >(const dynarray_iterator<Ptr1> & right) const
{
OEL_ITER_CHECK_COMPATIBLE(right);
OEL_ITER_CHECK_COMPATIBLE(*this, right);
return _pElem > right._pElem;
}

template< typename Ptr1 >
bool operator<=(const dynarray_iterator<Ptr1> & right) const
{
return !(*this > right);
return !(right < *this);
}

template< typename Ptr1 >
Expand Down Expand Up @@ -212,16 +213,22 @@ struct std::pointer_traits< oel::dynarray_iterator<Ptr> >

namespace oel::_detail
{
template< typename Ptr >
dynarray_iterator<Ptr> MakeDynarrayIter(Ptr const pos, Ptr const begin, const void * parent) noexcept
template< typename Ptr, typename P2 >
auto MakeDynarrIter(const DynarrBase<P2> & parent, Ptr const pos) noexcept
{
if (begin)
#if OEL_MEM_BOUND_DEBUG_LVL
if (parent.data)
{
auto const h = OEL_DEBUG_HEADER_OF_C(begin);
return {pos, h, h->id};
auto const h = _detail::DebugHeaderOf(parent.data);
return dynarray_iterator<Ptr>{pos, h, h->id};
}
else
{ return {pos, &_detail::headerNoAllocation, reinterpret_cast<std::uintptr_t>(parent)};
{ auto id = reinterpret_cast<std::uintptr_t>(&parent);
return dynarray_iterator<Ptr>{pos, &_detail::headerNoAllocation, id};
}
#else
(void) parent;
return pos;
#endif
}
}
43 changes: 16 additions & 27 deletions dynarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ class dynarray
//! Equivalent to `erase(first, end())`, but potentially faster and does not require assignable T
void erase_to_end(iterator first) noexcept;

void clear() noexcept { erase_to_end(begin()); }
void clear() noexcept { erase_to_end(begin()); }

bool empty() const noexcept { return _m.data == _m.end; }
[[nodiscard]] bool empty() const noexcept { return _m.data == _m.end; }

size_type size() const noexcept { return _m.end - _m.data; }
size_type size() const noexcept { return _m.end - _m.data; }

void reserve(size_type minCap)
{
Expand All @@ -243,28 +243,28 @@ class dynarray

allocator_type get_allocator() const noexcept { return _m; }

iterator begin() noexcept OEL_ALWAYS_INLINE { return _makeIter(_m.data); }
const_iterator begin() const noexcept OEL_ALWAYS_INLINE { return _makeIter<const T *>(_m.data); }
iterator begin() noexcept { return _detail::MakeDynarrIter (_m, _m.data); }
const_iterator begin() const noexcept { return _detail::MakeDynarrIter<const T *>(_m, _m.data); }
const_iterator cbegin() const noexcept OEL_ALWAYS_INLINE { return begin(); }

iterator end() noexcept OEL_ALWAYS_INLINE { return _makeIter(_m.end); }
const_iterator end() const noexcept OEL_ALWAYS_INLINE { return _makeIter<const T *>(_m.end); }
iterator end() noexcept { return _detail::MakeDynarrIter (_m, _m.end); }
const_iterator end() const noexcept { return _detail::MakeDynarrIter<const T *>(_m, _m.end); }
const_iterator cend() const noexcept OEL_ALWAYS_INLINE { return end(); }

reverse_iterator rbegin() noexcept OEL_ALWAYS_INLINE { return reverse_iterator{end()}; }
reverse_iterator rbegin() noexcept OEL_ALWAYS_INLINE { return reverse_iterator{end()}; }
const_reverse_iterator rbegin() const noexcept OEL_ALWAYS_INLINE { return const_reverse_iterator{end()}; }

reverse_iterator rend() noexcept OEL_ALWAYS_INLINE { return reverse_iterator{begin()}; }
reverse_iterator rend() noexcept OEL_ALWAYS_INLINE { return reverse_iterator{begin()}; }
const_reverse_iterator rend() const noexcept OEL_ALWAYS_INLINE { return const_reverse_iterator{begin()}; }

T * data() noexcept OEL_ALWAYS_INLINE { return _m.data; }
const T * data() const noexcept OEL_ALWAYS_INLINE { return _m.data; }

reference front() noexcept { return *begin(); }
const_reference front() const noexcept { return *begin(); }
reference front() noexcept { return (*this)[0]; }
const_reference front() const noexcept { return (*this)[0]; }

reference back() noexcept { return *_makeIter(_m.end - 1); }
const_reference back() const noexcept { return *_makeIter<const T *>(_m.end - 1); }
reference back() noexcept { return *_detail::MakeDynarrIter (_m, _m.end - 1); }
const_reference back() const noexcept { return *_detail::MakeDynarrIter<const T *>(_m, _m.end - 1); }

reference at(size_type index);
const_reference at(size_type index) const;
Expand Down Expand Up @@ -367,17 +367,6 @@ class dynarray
}


template< typename Ptr >
OEL_ALWAYS_INLINE auto _makeIter(Ptr pos) const noexcept
{
#if OEL_MEM_BOUND_DEBUG_LVL
return _detail::MakeDynarrayIter<Ptr>(pos, _m.data, this);
#else
return pos;
#endif
}


void _moveInternBase(_internBase & src) noexcept
{
static_cast<_internBase &>(_m) = src;
Expand Down Expand Up @@ -541,7 +530,7 @@ class dynarray
if (newEnd < _m.end)
{ // downsizing, assign new and destroy rest
src = copy(std::move(src), _m.data, newEnd);
erase_to_end(_makeIter(newEnd));
erase_to_end(_detail::MakeDynarrIter(_m, newEnd));
}
else // assign to old elements as far as we can
{ src = copy(std::move(src), _m.data, _m.end);
Expand Down Expand Up @@ -693,7 +682,7 @@ typename dynarray<T, Alloc>::iterator
{ pPos = _insertRealloc< _emplaceHelper, _detail::ForwardT<Args>... >
(pPos, static_cast<Args &&>(args)...);
}
return _makeIter(pPos);
return _detail::MakeDynarrIter(_m, pPos);
}

template< typename T, typename Alloc >
Expand Down Expand Up @@ -749,7 +738,7 @@ typename dynarray<T, Alloc>::iterator
else
{ pPos = _insertRealloc<_insertRHelper>(pPos, std::move(first), count);
}
return _makeIter(pPos);
return _detail::MakeDynarrIter(_m, pPos);
}

template< typename T, typename Alloc >
Expand Down
15 changes: 15 additions & 0 deletions unit_test/dynarray_other_gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ namespace
static_assert(!oel::allocator_can_realloc< oel::allocator<MoveOnly> >);
}

void testCompileDynarrayMembers()
{
dynarray<int> const d{0};
dynarray<int>::allocate_size_overhead();
d.get_allocator();
d.cbegin();
d.cend();
d.rbegin();
d.rend();
d.data();
d.front();
d.back();
d.at(0);
}

TEST(dynarrayOtherTest, zeroBitRepresentation)
{
{
Expand Down

0 comments on commit c91858b

Please sign in to comment.