Program Listing for File data_view.hpp¶
↰ Return to documentation for file (/home/runner/work/Legion-Engine/Legion-Engine/legion/engine/core/containers/data_view.hpp
)
#pragma once
#include <cstdint>
#include <cstddef>
#include <atomic>
#include <stdexcept>
#include "core/platform/platform.hpp"
namespace legion::core
{
template <class DataType>
class data_view
{
public:
using value_type = DataType;
using iterator = DataType*;
using ptr_type = DataType*;
using const_ptr_type = const DataType *;
using size_type = std::size_t;
using const_value_type = const DataType;
using const_iterator = const DataType *;
explicit data_view(nullptr_t) : data_view(nullptr,0,0,false){}
explicit data_view(ptr_type ptr,size_type size,size_type offset = 0,bool take_ownership = false) :
m_targetArray(ptr),
m_targetOffset(offset),
m_targetSize(size)
{
if(take_ownership)
m_referenceCount = new std::atomic<uint32_t>(1);
}
data_view(const data_view& other) :
m_referenceCount(other.m_referenceCount),
m_targetArray(other.m_targetArray),
m_targetOffset(other.m_targetOffset),
m_targetSize(other.m_targetSize)
{
try_inc_ref_count();
}
data_view(data_view&& other) noexcept:
m_referenceCount(std::move(other.m_referenceCount)),
m_targetArray(std::move(other.m_targetArray)),
m_targetOffset(std::move(other.m_targetOffset)),
m_targetSize(std::move(other.m_targetSize))
{
try_inc_ref_count();
}
data_view& operator=(const data_view& other)
{
if (this == &other)
return *this;
m_referenceCount = other.m_referenceCount;
m_targetArray = other.m_targetArray;
m_targetOffset = other.m_targetOffset;
m_targetSize = other.m_targetSize;
try_inc_ref_count();
return *this;
}
data_view& operator=(data_view&& other) noexcept
{
if (this == &other)
return *this;
m_referenceCount = other.m_referenceCount;
m_targetArray = other.m_targetArray;
m_targetOffset = other.m_targetOffset;
m_targetSize = other.m_targetSize;
try_inc_ref_count();
return *this;
}
~data_view()
{
if(m_referenceCount)
{
if(try_dec_ref_count() == 0)
{
//TODO(algo-ryth-mix): there might be a bug here but it is really hard to tell for me:
//TODO(cont.): basically we are deleting the atomic without being in a critical section
//TODO(cont.): which means we could be deleting something, that someone else wants to access
//TODO(cont.): but we are also deleting with the assumption that we are the last element (ref_count was 1)
//TODO(cont.): so I am not quite sure what is going on here
delete[] m_targetArray;
delete m_referenceCount;
}
}
}
L_NODISCARD value_type at(size_type idx) const
{
if(idx > m_targetSize) throw std::out_of_range("data_view subscript out of range");
return this->operator[](idx);
}
value_type& operator[](size_type idx)
{
if(idx > m_targetSize) throw std::out_of_range("data_view subscript out of range");
return *(m_targetArray + m_targetOffset + static_cast<ptrdiff_t>(idx));
}
L_NODISCARD value_type operator[](size_type idx) const
{
if(idx > m_targetSize) throw std::out_of_range("data_view subscript out of range");
return *(m_targetArray + m_targetOffset + static_cast<ptrdiff_t>(idx));
}
L_NODISCARD iterator begin()
{
return m_targetArray + m_targetOffset;
}
L_NODISCARD iterator end()
{
return begin() + m_targetSize;
}
L_NODISCARD ptr_type data()
{
return begin();
}
L_NODISCARD const_iterator begin() const
{
return m_targetArray + m_targetOffset;
}
L_NODISCARD const_iterator end() const
{
return begin() + m_targetSize;
}
L_NODISCARD const_ptr_type data() const
{
return begin();
}
L_NODISCARD size_type size() const noexcept
{
return m_targetSize;
}
L_NODISCARD size_type max_size() const noexcept
{
return m_targetSize;
}
private:
void try_inc_ref_count() const
{
if(m_referenceCount)
{
m_referenceCount->fetch_add(1);
}
}
uint32_t try_dec_ref_count() const
{
if(m_referenceCount)
{
// for some reason c++ calls execution order fetch_sub does exactly that, it fetches first, subtracts then and returns what it fetched beforehand
return m_referenceCount->fetch_sub(1) - 1;
}
return 1;
}
mutable std::atomic<uint32_t>* m_referenceCount = nullptr;
ptr_type m_targetArray;
ptrdiff_t m_targetOffset;
size_type m_targetSize;
};
}