Allocator Aware Array and List
This commit is contained in:
@@ -74,3 +74,4 @@ float4 fragmentMain(
|
|||||||
}
|
}
|
||||||
return float4(result, 1);
|
return float4(result, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ target_sources(SeeleEngine
|
|||||||
EngineTypes.h
|
EngineTypes.h
|
||||||
MinimalEngine.h
|
MinimalEngine.h
|
||||||
MinimalEngine.cpp
|
MinimalEngine.cpp
|
||||||
|
ThreadPool.h
|
||||||
|
ThreadPool.cpp
|
||||||
main.cpp)
|
main.cpp)
|
||||||
|
|
||||||
add_subdirectory(Asset/)
|
add_subdirectory(Asset/)
|
||||||
|
|||||||
+278
-178
@@ -12,120 +12,10 @@
|
|||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
enum class Init_t {
|
template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>>
|
||||||
NO_INIT
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
struct Array
|
struct Array
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Array()
|
|
||||||
: arraySize(0)
|
|
||||||
, allocated(DEFAULT_ALLOC_SIZE)
|
|
||||||
{
|
|
||||||
_data = new T[DEFAULT_ALLOC_SIZE];
|
|
||||||
assert(_data != nullptr);
|
|
||||||
//std::memset(_data, 0, sizeof(T) * DEFAULT_ALLOC_SIZE);
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
Array(Init_t)
|
|
||||||
: arraySize(0)
|
|
||||||
, allocated(0)
|
|
||||||
, beginIt(Iterator(nullptr))
|
|
||||||
, endIt(Iterator(nullptr))
|
|
||||||
, _data(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Array(size_t size, T value = T())
|
|
||||||
: arraySize(size)
|
|
||||||
, allocated(size)
|
|
||||||
{
|
|
||||||
_data = new T[size];
|
|
||||||
assert(_data != nullptr);
|
|
||||||
for (size_t i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
assert(i < size);
|
|
||||||
_data[i] = value;
|
|
||||||
}
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
Array(std::initializer_list<T> init)
|
|
||||||
: arraySize(init.size())
|
|
||||||
, allocated(init.size())
|
|
||||||
{
|
|
||||||
_data = new T[init.size()];
|
|
||||||
auto it = init.begin();
|
|
||||||
for (size_t i = 0; it != init.end(); i++, it++)
|
|
||||||
{
|
|
||||||
assert(i < init.size());
|
|
||||||
_data[i] = *it;
|
|
||||||
}
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
Array(const Array &other)
|
|
||||||
: arraySize(other.arraySize)
|
|
||||||
, allocated(other.allocated)
|
|
||||||
{
|
|
||||||
_data = new T[other.allocated];
|
|
||||||
assert(_data != nullptr);
|
|
||||||
markIteratorDirty();
|
|
||||||
std::copy(other.begin(), other.end(), begin());
|
|
||||||
}
|
|
||||||
Array(Array &&other) noexcept
|
|
||||||
: arraySize(std::move(other.arraySize))
|
|
||||||
, allocated(std::move(other.allocated))
|
|
||||||
{
|
|
||||||
_data = other._data;
|
|
||||||
other._data = nullptr;
|
|
||||||
other.allocated = 0;
|
|
||||||
other.arraySize = 0;
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
Array &operator=(const Array &other) noexcept
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
if (_data != nullptr)
|
|
||||||
{
|
|
||||||
if(other.arraySize > allocated)
|
|
||||||
{
|
|
||||||
delete[] _data;
|
|
||||||
_data = new T[other.allocated];
|
|
||||||
allocated = other.allocated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
arraySize = other.arraySize;
|
|
||||||
markIteratorDirty();
|
|
||||||
std::copy(other.begin(), other.end(), begin());
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
Array &operator=(Array &&other) noexcept
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
if (_data != nullptr)
|
|
||||||
{
|
|
||||||
delete[] _data;
|
|
||||||
_data = nullptr;
|
|
||||||
}
|
|
||||||
allocated = std::move(other.allocated);
|
|
||||||
arraySize = std::move(other.arraySize);
|
|
||||||
_data = other._data;
|
|
||||||
other._data = nullptr;
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
~Array()
|
|
||||||
{
|
|
||||||
if (_data)
|
|
||||||
{
|
|
||||||
delete[] _data;
|
|
||||||
_data = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename X>
|
template <typename X>
|
||||||
class IteratorBase
|
class IteratorBase
|
||||||
{
|
{
|
||||||
@@ -186,20 +76,179 @@ namespace Seele
|
|||||||
private:
|
private:
|
||||||
X *p;
|
X *p;
|
||||||
};
|
};
|
||||||
typedef IteratorBase<T> Iterator;
|
|
||||||
typedef IteratorBase<const T> ConstIterator;
|
|
||||||
|
|
||||||
bool operator==(const Array &other)
|
using value_type = T;
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
|
||||||
|
using Iterator = IteratorBase<T>;
|
||||||
|
using ConstIterator = IteratorBase<const T>;
|
||||||
|
using iterator = Iterator;
|
||||||
|
using const_iterator = ConstIterator;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
constexpr Array() noexcept(noexcept(Allocator()))
|
||||||
|
: arraySize(0)
|
||||||
|
, allocated(DEFAULT_ALLOC_SIZE)
|
||||||
|
, allocator(Allocator())
|
||||||
|
{
|
||||||
|
_data = allocateArray(DEFAULT_ALLOC_SIZE);
|
||||||
|
assert(_data != nullptr);
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit Array(const allocator_type& alloc)
|
||||||
|
: arraySize(0)
|
||||||
|
, allocated(DEFAULT_ALLOC_SIZE)
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateArray(DEFAULT_ALLOC_SIZE);
|
||||||
|
assert(_data != nullptr);
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr Array(size_type size, const T& value, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(size)
|
||||||
|
, allocated(size)
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateArray(size);
|
||||||
|
for (size_type i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
_data[i] = value;
|
||||||
|
}
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr explicit Array(size_type size, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(size)
|
||||||
|
, allocated(size)
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateArray(size);
|
||||||
|
for (size_type i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i]);
|
||||||
|
}
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr Array(std::initializer_list<T> init, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(init.size())
|
||||||
|
, allocated(init.size())
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateArray(init.size());
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(init.begin(), init.end(), begin());
|
||||||
|
}
|
||||||
|
Array(const Array &other)
|
||||||
|
: arraySize(other.arraySize)
|
||||||
|
, allocated(other.allocated)
|
||||||
|
, allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
||||||
|
{
|
||||||
|
_data = allocateArray(other.allocated);
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||||
|
}
|
||||||
|
Array(Array &&other) noexcept
|
||||||
|
: arraySize(std::move(other.arraySize))
|
||||||
|
, allocated(std::move(other.allocated))
|
||||||
|
, allocator(std::move(other.allocator))
|
||||||
|
{
|
||||||
|
_data = other._data;
|
||||||
|
other._data = nullptr;
|
||||||
|
other.allocated = 0;
|
||||||
|
other.arraySize = 0;
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
Array &operator=(const Array &other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value
|
||||||
|
&& !std::allocator_traits<allocator_type>::is_always_equal::value)
|
||||||
|
{
|
||||||
|
if(allocator != other.allocator)
|
||||||
|
{
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value)
|
||||||
|
{
|
||||||
|
allocator = other.allocator;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{}
|
||||||
|
if(other.arraySize > allocated)
|
||||||
|
{
|
||||||
|
if(_data != nullptr)
|
||||||
|
{
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
}
|
||||||
|
_data = allocateArray(other.allocated);
|
||||||
|
allocated = other.allocated;
|
||||||
|
}
|
||||||
|
arraySize = other.arraySize;
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Array &operator=(Array &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
|
||||||
|
&& !std::allocator_traits<allocator_type>::is_always_equal::value)
|
||||||
|
{
|
||||||
|
if(allocator != other.allocator)
|
||||||
|
{
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
|
||||||
|
{
|
||||||
|
allocator = std::move(other.allocator);
|
||||||
|
}
|
||||||
|
if (_data != nullptr)
|
||||||
|
{
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
allocated = std::move(other.allocated);
|
||||||
|
arraySize = std::move(other.arraySize);
|
||||||
|
_data = other._data;
|
||||||
|
other._data = nullptr;
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
~Array()
|
||||||
|
{
|
||||||
|
if (_data)
|
||||||
|
{
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
_data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const Array &other)
|
||||||
{
|
{
|
||||||
return _data == other._data;
|
return _data == other._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Array &other)
|
constexpr bool operator!=(const Array &other)
|
||||||
{
|
{
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator find(const T &item)
|
constexpr Iterator find(const T &item)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < arraySize; ++i)
|
for (uint32 i = 0; i < arraySize; ++i)
|
||||||
{
|
{
|
||||||
@@ -210,7 +259,7 @@ namespace Seele
|
|||||||
}
|
}
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
Iterator find(T&& item)
|
constexpr Iterator find(T&& item)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < arraySize; ++i)
|
for (uint32 i = 0; i < arraySize; ++i)
|
||||||
{
|
{
|
||||||
@@ -221,31 +270,35 @@ namespace Seele
|
|||||||
}
|
}
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
Iterator begin() const
|
constexpr Allocator get_allocator() const
|
||||||
|
{
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
constexpr Iterator begin() const
|
||||||
{
|
{
|
||||||
return beginIt;
|
return beginIt;
|
||||||
}
|
}
|
||||||
Iterator end() const
|
constexpr Iterator end() const
|
||||||
{
|
{
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
ConstIterator cbegin() const
|
constexpr ConstIterator cbegin() const
|
||||||
{
|
{
|
||||||
return beginIt;
|
return beginIt;
|
||||||
}
|
}
|
||||||
ConstIterator cend() const
|
constexpr ConstIterator cend() const
|
||||||
{
|
{
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
T &add(const T &item = T())
|
constexpr T &add(const T &item = T())
|
||||||
{
|
{
|
||||||
return addInternal(item);
|
return addInternal(item);
|
||||||
}
|
}
|
||||||
T &add(T&& item)
|
constexpr T &add(T&& item)
|
||||||
{
|
{
|
||||||
return addInternal(std::forward<T>(item));
|
return addInternal(std::forward<T>(item));
|
||||||
}
|
}
|
||||||
T &addUnique(const T &item = T())
|
constexpr T &addUnique(const T &item = T())
|
||||||
{
|
{
|
||||||
Iterator it;
|
Iterator it;
|
||||||
if((it = std::move(find(item))) != endIt)
|
if((it = std::move(find(item))) != endIt)
|
||||||
@@ -255,30 +308,30 @@ namespace Seele
|
|||||||
return addInternal(item);
|
return addInternal(item);
|
||||||
}
|
}
|
||||||
template<typename... args>
|
template<typename... args>
|
||||||
T &emplace(args... arguments)
|
constexpr T &emplace(args... arguments)
|
||||||
{
|
{
|
||||||
if (arraySize == allocated)
|
if (arraySize == allocated)
|
||||||
{
|
{
|
||||||
size_t newSize = arraySize + 1;
|
size_type newSize = arraySize + 1;
|
||||||
allocated = calculateGrowth(newSize);
|
allocated = calculateGrowth(newSize);
|
||||||
T *tempArray = new T[allocated];
|
T *tempArray = allocateArray(allocated);
|
||||||
assert(tempArray != nullptr);
|
assert(tempArray != nullptr);
|
||||||
for (size_t i = 0; i < arraySize; ++i)
|
for (size_type i = 0; i < arraySize; ++i)
|
||||||
{
|
{
|
||||||
tempArray[i] = _data[i];
|
tempArray[i] = std::move(_data[i]);
|
||||||
}
|
}
|
||||||
delete[] _data;
|
deallocateArray(_data, arraySize);
|
||||||
_data = tempArray;
|
_data = tempArray;
|
||||||
}
|
}
|
||||||
_data[arraySize++] = T(arguments...);
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[arraySize++], arguments...);
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
return _data[arraySize - 1];
|
return _data[arraySize - 1];
|
||||||
}
|
}
|
||||||
void remove(Iterator it, bool keepOrder = true)
|
constexpr void remove(Iterator it, bool keepOrder = true)
|
||||||
{
|
{
|
||||||
remove(it - beginIt, keepOrder);
|
remove(it - beginIt, keepOrder);
|
||||||
}
|
}
|
||||||
void remove(int index, bool keepOrder = true)
|
constexpr void remove(int index, bool keepOrder = true)
|
||||||
{
|
{
|
||||||
if (keepOrder)
|
if (keepOrder)
|
||||||
{
|
{
|
||||||
@@ -294,60 +347,51 @@ namespace Seele
|
|||||||
arraySize--;
|
arraySize--;
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
}
|
}
|
||||||
void clear()
|
constexpr void resize(size_type newSize)
|
||||||
{
|
{
|
||||||
delete[] _data;
|
resizeInternal(newSize, std::move(T()));
|
||||||
|
}
|
||||||
|
constexpr void resize(size_type newSize, const T& value)
|
||||||
|
{
|
||||||
|
resizeInternal(newSize, value);
|
||||||
|
}
|
||||||
|
constexpr void clear()
|
||||||
|
{
|
||||||
|
for(size_type i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
_data[i].~T();
|
||||||
|
}
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
arraySize = 0;
|
arraySize = 0;
|
||||||
allocated = 0;
|
allocated = 0;
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
}
|
}
|
||||||
void resize(size_t newSize)
|
inline size_type indexOf(Iterator iterator)
|
||||||
{
|
|
||||||
if (newSize <= allocated)
|
|
||||||
{
|
|
||||||
arraySize = newSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
T *newData = new T[newSize];
|
|
||||||
assert(newData != nullptr);
|
|
||||||
allocated = newSize;
|
|
||||||
for(uint32 i = 0; i < arraySize; ++i)
|
|
||||||
{
|
|
||||||
newData[i] = std::move(_data[i]);
|
|
||||||
}
|
|
||||||
arraySize = newSize;
|
|
||||||
delete _data;
|
|
||||||
_data = newData;
|
|
||||||
}
|
|
||||||
markIteratorDirty();
|
|
||||||
}
|
|
||||||
inline size_t indexOf(Iterator iterator)
|
|
||||||
{
|
{
|
||||||
return iterator - beginIt;
|
return iterator - beginIt;
|
||||||
}
|
}
|
||||||
inline size_t indexOf(ConstIterator iterator) const
|
inline size_type indexOf(ConstIterator iterator) const
|
||||||
{
|
{
|
||||||
return iterator.p - beginIt.p;
|
return iterator.p - beginIt.p;
|
||||||
}
|
}
|
||||||
inline size_t indexOf(T& t)
|
inline size_type indexOf(T& t)
|
||||||
{
|
{
|
||||||
return indexOf(find(t));
|
return indexOf(find(t));
|
||||||
}
|
}
|
||||||
inline size_t indexOf(const T& t) const
|
inline size_type indexOf(const T& t) const
|
||||||
{
|
{
|
||||||
return indexOf(find(t));
|
return indexOf(find(t));
|
||||||
}
|
}
|
||||||
inline size_t size() const
|
inline size_type size() const
|
||||||
{
|
{
|
||||||
return arraySize;
|
return arraySize;
|
||||||
}
|
}
|
||||||
inline size_t empty() const
|
inline size_type empty() const
|
||||||
{
|
{
|
||||||
return arraySize == 0;
|
return arraySize == 0;
|
||||||
}
|
}
|
||||||
inline size_t capacity() const
|
inline size_type capacity() const
|
||||||
{
|
{
|
||||||
return allocated;
|
return allocated;
|
||||||
}
|
}
|
||||||
@@ -364,27 +408,27 @@ namespace Seele
|
|||||||
arraySize--;
|
arraySize--;
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
}
|
}
|
||||||
constexpr inline T &operator[](size_t index)
|
constexpr inline T &operator[](size_type index)
|
||||||
{
|
{
|
||||||
assert(index < arraySize);
|
assert(index < arraySize);
|
||||||
return _data[index];
|
return _data[index];
|
||||||
}
|
}
|
||||||
constexpr inline const T &operator[](size_t index) const
|
constexpr inline const T &operator[](size_type index) const
|
||||||
{
|
{
|
||||||
assert(index < arraySize);
|
assert(index < arraySize);
|
||||||
return _data[index];
|
return _data[index];
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
size_t calculateGrowth(size_t newSize) const
|
size_type calculateGrowth(size_type newSize) const
|
||||||
{
|
{
|
||||||
const size_t oldCapacity = capacity();
|
const size_type oldCapacity = capacity();
|
||||||
|
|
||||||
if (oldCapacity > SIZE_MAX - oldCapacity / 2)
|
if (oldCapacity > SIZE_MAX - oldCapacity / 2)
|
||||||
{
|
{
|
||||||
return newSize; // geometric growth would overflow
|
return newSize; // geometric growth would overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t geometric = oldCapacity + oldCapacity / 2;
|
const size_type geometric = oldCapacity + oldCapacity / 2;
|
||||||
|
|
||||||
if (geometric < newSize)
|
if (geometric < newSize)
|
||||||
{
|
{
|
||||||
@@ -398,41 +442,97 @@ namespace Seele
|
|||||||
beginIt = Iterator(_data);
|
beginIt = Iterator(_data);
|
||||||
endIt = Iterator(_data + arraySize);
|
endIt = Iterator(_data + arraySize);
|
||||||
}
|
}
|
||||||
|
T* allocateArray(size_type size)
|
||||||
|
{
|
||||||
|
T* result = allocator.allocate(size);
|
||||||
|
assert(result != nullptr);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void deallocateArray(T* ptr, size_type size)
|
||||||
|
{
|
||||||
|
allocator.deallocate(ptr, size);
|
||||||
|
}
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
T& addInternal(Type&& t)
|
T& addInternal(Type&& t)
|
||||||
{
|
{
|
||||||
if (arraySize == allocated)
|
if (arraySize == allocated)
|
||||||
{
|
{
|
||||||
size_t newSize = arraySize + 1;
|
size_type newSize = arraySize + 1;
|
||||||
allocated = calculateGrowth(newSize);
|
allocated = calculateGrowth(newSize);
|
||||||
T *tempArray = new T[allocated];
|
T *tempArray = allocateArray(allocated);
|
||||||
assert(tempArray != nullptr);
|
for (size_type i = 0; i < arraySize; ++i)
|
||||||
for (size_t i = 0; i < arraySize; ++i)
|
|
||||||
{
|
{
|
||||||
tempArray[i] = std::forward<Type>(_data[i]);
|
std::allocator_traits<allocator_type>::construct(allocator, &tempArray[i], std::forward<Type>(_data[i]));
|
||||||
}
|
}
|
||||||
delete[] _data;
|
deallocateArray(_data, arraySize);
|
||||||
_data = tempArray;
|
_data = tempArray;
|
||||||
}
|
}
|
||||||
_data[arraySize++] = std::forward<Type>(t);
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[arraySize++], std::forward<Type>(t));
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
return _data[arraySize - 1];
|
return _data[arraySize - 1];
|
||||||
}
|
}
|
||||||
|
template<typename Type>
|
||||||
|
void resizeInternal(size_type newSize, Type&& value)
|
||||||
|
{
|
||||||
|
if (newSize <= allocated)
|
||||||
|
{
|
||||||
|
// The array is already big enough
|
||||||
|
if(newSize < arraySize)
|
||||||
|
{
|
||||||
|
// But since we are sizing down we destruct some of them
|
||||||
|
for(size_type i = newSize; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Or construct the new elements by default
|
||||||
|
for(size_type i = arraySize; i < newSize; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], std::move(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arraySize = newSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The array is not big enough, so we make a new one
|
||||||
|
T *newData = allocateArray(newSize);
|
||||||
|
|
||||||
|
// And move the current elements into that one
|
||||||
|
for(size_type i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
newData[i] = std::forward<Type>(_data[i]);
|
||||||
|
}
|
||||||
|
// As well as default initialize the others
|
||||||
|
for(size_type i = arraySize; i < newSize; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], std::move(value));
|
||||||
|
}
|
||||||
|
deallocateArray(_data, allocated);
|
||||||
|
arraySize = newSize;
|
||||||
|
allocated = newSize;
|
||||||
|
_data = newData;
|
||||||
|
}
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int)
|
void serialize(Archive& ar, const unsigned int)
|
||||||
{
|
{
|
||||||
ar & arraySize;
|
ar & arraySize;
|
||||||
resize(arraySize);
|
resize(arraySize);
|
||||||
for(size_t i = 0; i < arraySize; ++i)
|
for(size_type i = 0; i < arraySize; ++i)
|
||||||
ar & _data[i];
|
ar & _data[i];
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
}
|
}
|
||||||
size_t arraySize = 0;
|
size_type arraySize = 0;
|
||||||
size_t allocated = 0;
|
size_type allocated = 0;
|
||||||
Iterator beginIt;
|
Iterator beginIt;
|
||||||
Iterator endIt;
|
Iterator endIt;
|
||||||
T *_data = nullptr;
|
T *_data = nullptr;
|
||||||
|
allocator_type allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, size_t N>
|
template <typename T, size_t N>
|
||||||
|
|||||||
+133
-97
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
|
#include <xmemory>
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>>
|
||||||
class List
|
class List
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -12,83 +14,18 @@ private:
|
|||||||
Node *next;
|
Node *next;
|
||||||
T data;
|
T data;
|
||||||
};
|
};
|
||||||
|
using NodeAllocator = std::allocator_traits<Allocator>::template rebind_alloc<Node>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
List()
|
|
||||||
{
|
|
||||||
root = nullptr;
|
|
||||||
tail = nullptr;
|
|
||||||
beginIt = Iterator(root);
|
|
||||||
endIt = Iterator(tail);
|
|
||||||
_size = 0;
|
|
||||||
}
|
|
||||||
List(const List& other)
|
|
||||||
{
|
|
||||||
//TODO: improve
|
|
||||||
for(const auto& it : other)
|
|
||||||
{
|
|
||||||
add(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List(List&& other)
|
|
||||||
: root(std::move(other.root))
|
|
||||||
, tail(std::move(other.tail))
|
|
||||||
, beginIt(std::move(other.beginIt))
|
|
||||||
, endIt(std::move(other.endIt))
|
|
||||||
, _size(std::move(other._size))
|
|
||||||
{
|
|
||||||
other._size = 0;
|
|
||||||
}
|
|
||||||
~List()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
List& operator=(const List& other)
|
|
||||||
{
|
|
||||||
if(this != &other)
|
|
||||||
{
|
|
||||||
if(root != nullptr)
|
|
||||||
{
|
|
||||||
delete root;
|
|
||||||
}
|
|
||||||
if(tail != nullptr)
|
|
||||||
{
|
|
||||||
delete tail;
|
|
||||||
}
|
|
||||||
_size = 0;
|
|
||||||
for(const auto& it : other)
|
|
||||||
{
|
|
||||||
add(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
List& operator=(List&& other)
|
|
||||||
{
|
|
||||||
if(this != &other)
|
|
||||||
{
|
|
||||||
if(root != nullptr)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
root = other.root;
|
|
||||||
tail = other.tail;
|
|
||||||
beginIt = other.beginIt;
|
|
||||||
endIt = other.endIt;
|
|
||||||
_size = other._size;
|
|
||||||
other._size = 0;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
template <typename X>
|
template <typename X>
|
||||||
class IteratorBase
|
class IteratorBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::forward_iterator_tag iterator_category;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
typedef X value_type;
|
using value_type = X;
|
||||||
typedef std::ptrdiff_t difference_type;
|
using difference_type = std::ptrdiff_t;
|
||||||
typedef X &reference;
|
using reference = X&;
|
||||||
typedef X *pointer;
|
using pointer = X*;
|
||||||
|
|
||||||
IteratorBase(Node *x = nullptr)
|
IteratorBase(Node *x = nullptr)
|
||||||
: node(x)
|
: node(x)
|
||||||
@@ -164,8 +101,91 @@ public:
|
|||||||
Node *node;
|
Node *node;
|
||||||
friend class List<T>;
|
friend class List<T>;
|
||||||
};
|
};
|
||||||
typedef IteratorBase<T> Iterator;
|
|
||||||
typedef IteratorBase<const T> ConstIterator;
|
using Iterator = IteratorBase<T>;
|
||||||
|
using ConstIterator = IteratorBase<const T>;
|
||||||
|
|
||||||
|
using value_type = T;
|
||||||
|
using allocator_type = Allocator;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
|
||||||
|
using iterator = Iterator;
|
||||||
|
using const_iterator = ConstIterator;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
List()
|
||||||
|
: root(nullptr)
|
||||||
|
, tail(nullptr)
|
||||||
|
, beginIt(Iterator(root))
|
||||||
|
, endIt(Iterator(tail))
|
||||||
|
, _size(0)
|
||||||
|
, allocator(NodeAllocator())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
List(const List& other)
|
||||||
|
{
|
||||||
|
//TODO: improve
|
||||||
|
for(const auto& it : other)
|
||||||
|
{
|
||||||
|
add(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List(List&& other)
|
||||||
|
: root(std::move(other.root))
|
||||||
|
, tail(std::move(other.tail))
|
||||||
|
, beginIt(std::move(other.beginIt))
|
||||||
|
, endIt(std::move(other.endIt))
|
||||||
|
, _size(std::move(other._size))
|
||||||
|
{
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
~List()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
List& operator=(const List& other)
|
||||||
|
{
|
||||||
|
if(this != &other)
|
||||||
|
{
|
||||||
|
if(root != nullptr)
|
||||||
|
{
|
||||||
|
delete root;
|
||||||
|
}
|
||||||
|
if(tail != nullptr)
|
||||||
|
{
|
||||||
|
delete tail;
|
||||||
|
}
|
||||||
|
_size = 0;
|
||||||
|
for(const auto& it : other)
|
||||||
|
{
|
||||||
|
add(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
List& operator=(List&& other)
|
||||||
|
{
|
||||||
|
if(this != &other)
|
||||||
|
{
|
||||||
|
if(root != nullptr)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
root = other.root;
|
||||||
|
tail = other.tail;
|
||||||
|
beginIt = other.beginIt;
|
||||||
|
endIt = other.endIt;
|
||||||
|
_size = other._size;
|
||||||
|
other._size = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
T &front()
|
T &front()
|
||||||
{
|
{
|
||||||
@@ -184,40 +204,40 @@ public:
|
|||||||
for (Node *tmp = root; tmp != tail;)
|
for (Node *tmp = root; tmp != tail;)
|
||||||
{
|
{
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
delete tmp->prev;
|
deallocateNode(tmp->prev);
|
||||||
}
|
}
|
||||||
delete tail;
|
deallocateNode(tail);
|
||||||
tail = nullptr;
|
tail = nullptr;
|
||||||
root = nullptr;
|
root = nullptr;
|
||||||
}
|
}
|
||||||
//Insert at the end
|
//Insert at the end
|
||||||
Iterator add(const T &value)
|
iterator add(const T &value)
|
||||||
{
|
{
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
{
|
{
|
||||||
root = new Node();
|
root = allocateNode();
|
||||||
tail = root;
|
tail = root;
|
||||||
}
|
}
|
||||||
tail->data = value;
|
tail->data = value;
|
||||||
Node *newTail = new Node();
|
Node *newTail = allocateNode();
|
||||||
newTail->prev = tail;
|
newTail->prev = tail;
|
||||||
newTail->next = nullptr;
|
newTail->next = nullptr;
|
||||||
tail->next = newTail;
|
tail->next = newTail;
|
||||||
Iterator insertedElement(tail);
|
iterator insertedElement(tail);
|
||||||
tail = newTail;
|
tail = newTail;
|
||||||
markIteratorDirty();
|
markIteratorDirty();
|
||||||
_size++;
|
_size++;
|
||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
Iterator add(T&& value)
|
iterator add(T&& value)
|
||||||
{
|
{
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
{
|
{
|
||||||
root = new Node();
|
root = allocateNode();
|
||||||
tail = root;
|
tail = root;
|
||||||
}
|
}
|
||||||
tail->data = std::move(value);
|
tail->data = std::move(value);
|
||||||
Node *newTail = new Node();
|
Node *newTail = allocateNode();
|
||||||
newTail->prev = tail;
|
newTail->prev = tail;
|
||||||
newTail->next = nullptr;
|
newTail->next = nullptr;
|
||||||
tail->next = newTail;
|
tail->next = newTail;
|
||||||
@@ -227,7 +247,7 @@ public:
|
|||||||
_size++;
|
_size++;
|
||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
Iterator remove(Iterator pos)
|
iterator remove(iterator pos)
|
||||||
{
|
{
|
||||||
_size--;
|
_size--;
|
||||||
Node *prev = pos.node->prev;
|
Node *prev = pos.node->prev;
|
||||||
@@ -262,14 +282,14 @@ public:
|
|||||||
assert(_size > 0);
|
assert(_size > 0);
|
||||||
remove(Iterator(root));
|
remove(Iterator(root));
|
||||||
}
|
}
|
||||||
Iterator insert(Iterator pos, const T &value)
|
iterator insert(iterator pos, const T &value)
|
||||||
{
|
{
|
||||||
_size++;
|
_size++;
|
||||||
if (root == nullptr)
|
if (root == nullptr)
|
||||||
{
|
{
|
||||||
root = new Node();
|
root = allocateNode();
|
||||||
root->data = value;
|
root->data = value;
|
||||||
tail = new Node();
|
tail = allocateNode();
|
||||||
root->next = tail;
|
root->next = tail;
|
||||||
root->prev = nullptr;
|
root->prev = nullptr;
|
||||||
tail->prev = root;
|
tail->prev = root;
|
||||||
@@ -278,7 +298,7 @@ public:
|
|||||||
return beginIt;
|
return beginIt;
|
||||||
}
|
}
|
||||||
Node *tmp = pos.node->prev;
|
Node *tmp = pos.node->prev;
|
||||||
Node *newNode = new Node();
|
Node *newNode = allocateNode();
|
||||||
newNode->data = value;
|
newNode->data = value;
|
||||||
tmp->next = newNode;
|
tmp->next = newNode;
|
||||||
newNode->prev = tmp;
|
newNode->prev = tmp;
|
||||||
@@ -286,13 +306,13 @@ public:
|
|||||||
pos.node->prev = newNode;
|
pos.node->prev = newNode;
|
||||||
return Iterator(newNode);
|
return Iterator(newNode);
|
||||||
}
|
}
|
||||||
Iterator find(const T &value)
|
iterator find(const T &value)
|
||||||
{
|
{
|
||||||
for (Node *i = root; i != tail; i = i->next)
|
for (Node *i = root; i != tail; i = i->next)
|
||||||
{
|
{
|
||||||
if (!(i->data < value) && !(value < i->data))
|
if (!(i->data < value) && !(value < i->data))
|
||||||
{
|
{
|
||||||
return Iterator(i);
|
return iterator(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return endIt;
|
return endIt;
|
||||||
@@ -301,37 +321,53 @@ public:
|
|||||||
{
|
{
|
||||||
return _size == 0;
|
return _size == 0;
|
||||||
}
|
}
|
||||||
uint32 size()
|
size_type size()
|
||||||
{
|
{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
Iterator begin()
|
iterator begin()
|
||||||
{
|
{
|
||||||
return beginIt;
|
return beginIt;
|
||||||
}
|
}
|
||||||
const Iterator begin() const
|
const_iterator begin() const
|
||||||
{
|
{
|
||||||
return beginIt;
|
return cbeginIt;
|
||||||
}
|
}
|
||||||
Iterator end()
|
iterator end()
|
||||||
{
|
{
|
||||||
return endIt;
|
return endIt;
|
||||||
}
|
}
|
||||||
const Iterator end() const
|
const_iterator end() const
|
||||||
{
|
{
|
||||||
return endIt;
|
return cendIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Node* allocateNode()
|
||||||
|
{
|
||||||
|
Node* node = allocator.allocate(1);
|
||||||
|
std::memset(node, 0, sizeof(Node));
|
||||||
|
assert(node != nullptr);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
void deallocateNode(Node* node)
|
||||||
|
{
|
||||||
|
allocator.deallocate(node, 1);
|
||||||
|
}
|
||||||
void markIteratorDirty()
|
void markIteratorDirty()
|
||||||
{
|
{
|
||||||
beginIt = Iterator(root);
|
beginIt = Iterator(root);
|
||||||
endIt = Iterator(tail);
|
endIt = Iterator(tail);
|
||||||
|
cbeginIt = ConstIterator(root);
|
||||||
|
cendIt = ConstIterator(tail);
|
||||||
}
|
}
|
||||||
Node *root;
|
Node *root;
|
||||||
Node *tail;
|
Node *tail;
|
||||||
Iterator beginIt;
|
Iterator beginIt;
|
||||||
Iterator endIt;
|
Iterator endIt;
|
||||||
|
ConstIterator cbeginIt;
|
||||||
|
ConstIterator cendIt;
|
||||||
uint32 _size;
|
uint32 _size;
|
||||||
|
NodeAllocator allocator;
|
||||||
};
|
};
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -171,7 +171,7 @@ public:
|
|||||||
using pointer = Pair<K, V>*;
|
using pointer = Pair<K, V>*;
|
||||||
|
|
||||||
Iterator(Node *x = nullptr)
|
Iterator(Node *x = nullptr)
|
||||||
: node(x), traversal(Init_t::NO_INIT)
|
: node(x)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Iterator(Node *x, Array<Node *> &&beginIt)
|
Iterator(Node *x, Array<Node *> &&beginIt)
|
||||||
|
|||||||
@@ -70,13 +70,9 @@ ShaderCollection& ShaderMap::createShaders(
|
|||||||
modifyRenderPassMacros(renderPass, createInfo.defines);
|
modifyRenderPassMacros(renderPass, createInfo.defines);
|
||||||
createInfo.name = getShaderNameFromRenderPassType(renderPass) + " Material " + material->getName();
|
createInfo.name = getShaderNameFromRenderPassType(renderPass) + " Material " + material->getName();
|
||||||
|
|
||||||
std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass), std::ios::ate);
|
std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass));
|
||||||
auto fileSize = codeStream.tellg();
|
|
||||||
codeStream.seekg(0);
|
|
||||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
|
||||||
codeStream.read(buffer.data(), fileSize);
|
|
||||||
|
|
||||||
createInfo.shaderCode.add(std::string(buffer.data(), 0, fileSize));
|
createInfo.shaderCode.add(std::string(std::istreambuf_iterator<char>{codeStream}, {}));
|
||||||
|
|
||||||
collection.vertexShader = graphics->createVertexShader(createInfo);
|
collection.vertexShader = graphics->createVertexShader(createInfo);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Containers/Map.h"
|
#include "Containers/Map.h"
|
||||||
#include "EngineTypes.h"
|
#include "EngineTypes.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
//#include "ThreadPool.h"
|
||||||
|
|
||||||
#define DEFINE_REF(x) \
|
#define DEFINE_REF(x) \
|
||||||
typedef RefPtr<x> P##x; \
|
typedef RefPtr<x> P##x; \
|
||||||
@@ -197,7 +198,7 @@ public:
|
|||||||
|
|
||||||
RefPtr &operator=(const RefPtr &other)
|
RefPtr &operator=(const RefPtr &other)
|
||||||
{
|
{
|
||||||
if (*this != other)
|
if (this != &other)
|
||||||
{
|
{
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
{
|
{
|
||||||
@@ -213,7 +214,7 @@ public:
|
|||||||
}
|
}
|
||||||
RefPtr &operator=(RefPtr &&rhs)
|
RefPtr &operator=(RefPtr &&rhs)
|
||||||
{
|
{
|
||||||
if (*this != rhs)
|
if (this != &rhs)
|
||||||
{
|
{
|
||||||
if (object != nullptr)
|
if (object != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
#include "Containers/List.h"
|
#include "Containers/List.h"
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
static ThreadPool gThreadPool;
|
|
||||||
|
void Event::await_suspend(std::coroutine_handle<JobPromise> h)
|
||||||
|
{
|
||||||
|
getGlobalThreadPool().addJob(Job(h));
|
||||||
|
}
|
||||||
|
|
||||||
Job JobPromise::get_return_object() noexcept {
|
Job JobPromise::get_return_object() noexcept {
|
||||||
return Job { std::coroutine_handle<JobPromise>::from_promise(*this) };
|
return Job { std::coroutine_handle<JobPromise>::from_promise(*this) };
|
||||||
@@ -14,7 +18,16 @@ ThreadPool::ThreadPool(uint32 threadCount)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ThreadPool& getGlobalThreadPool()
|
ThreadPool::~ThreadPool()
|
||||||
{
|
{
|
||||||
return gThreadPool;
|
for(auto& thread : workers)
|
||||||
|
{
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPool& Seele::getGlobalThreadPool()
|
||||||
|
{
|
||||||
|
static ThreadPool threadPool;
|
||||||
|
return threadPool;
|
||||||
}
|
}
|
||||||
+26
-16
@@ -1,23 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <coroutine>
|
#include <coroutine>
|
||||||
#include "MinimalEngine.h"
|
#include "Containers/List.h"
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
enum class JobStage
|
struct JobPromise;
|
||||||
|
struct Event
|
||||||
{
|
{
|
||||||
INPUT,
|
public:
|
||||||
GAMELOGIC,
|
void raise()
|
||||||
RENDER,
|
{
|
||||||
DONT_CARE
|
flag.test_and_set();
|
||||||
|
flag.notify_all();
|
||||||
|
}
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
flag.clear();
|
||||||
|
}
|
||||||
|
bool await_ready() { return flag.test(); }
|
||||||
|
void await_suspend(std::coroutine_handle<JobPromise> h);
|
||||||
|
void await_resume() {}
|
||||||
|
private:
|
||||||
|
std::atomic_flag flag;
|
||||||
};
|
};
|
||||||
struct [[nodiscard]] Job;
|
struct [[nodiscard]] Job;
|
||||||
struct JobPromise
|
struct JobPromise
|
||||||
{
|
{
|
||||||
Job get_return_object() noexcept;
|
Job get_return_object() noexcept;
|
||||||
|
|
||||||
std::suspend_never initial_suspend() const noexcept { return {}; }
|
std::suspend_always initial_suspend() const noexcept { return {}; }
|
||||||
std::suspend_never final_suspend() const noexcept { return {}; }
|
std::suspend_never final_suspend() const noexcept { return {}; }
|
||||||
|
|
||||||
void return_void() noexcept {}
|
void return_void() noexcept {}
|
||||||
@@ -31,9 +43,8 @@ struct [[nodiscard]] Job
|
|||||||
public:
|
public:
|
||||||
using promise_type = JobPromise;
|
using promise_type = JobPromise;
|
||||||
|
|
||||||
explicit Job(std::coroutine_handle<task_promise> handle, JobStage stage = JobStage::DONT_CARE)
|
explicit Job(std::coroutine_handle<JobPromise> handle)
|
||||||
: handle(handle)
|
: handle(handle)
|
||||||
, stage(stage)
|
|
||||||
{}
|
{}
|
||||||
~Job()
|
~Job()
|
||||||
{
|
{
|
||||||
@@ -44,22 +55,21 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::coroutine_handle<JobPromise> handle;
|
std::coroutine_handle<JobPromise> handle;
|
||||||
JobStage stage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadPool
|
class ThreadPool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency);
|
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
|
||||||
virtual ~ThreadPool();
|
virtual ~ThreadPool();
|
||||||
void schedule(std::function<void()> function)
|
void addJob(Job&& job)
|
||||||
{
|
{
|
||||||
|
jobs.add(std::move(job));
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Array<std::thread> workers;
|
std::vector<std::thread> workers;
|
||||||
Map<JobStage, List<Job>> jobs;
|
List<Job> jobs;
|
||||||
void threadLoop();
|
void threadLoop();
|
||||||
};
|
};
|
||||||
static ThreadPool& getGlobalThreadPool();
|
extern ThreadPool& getGlobalThreadPool();
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ void Window::addView(PView view)
|
|||||||
{
|
{
|
||||||
WindowView* windowView = new WindowView();
|
WindowView* windowView = new WindowView();
|
||||||
windowView->view = view;
|
windowView->view = view;
|
||||||
windowView->worker = std::thread(&Window::viewWorker, this, windowView);
|
//windowView->worker = std::thread(&Window::viewWorker, this, windowView);
|
||||||
views.add(windowView);
|
views.add(windowView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,8 +27,16 @@ void Window::render()
|
|||||||
{
|
{
|
||||||
windowView->view->beginUpdate();
|
windowView->view->beginUpdate();
|
||||||
windowView->view->update();
|
windowView->view->update();
|
||||||
|
{
|
||||||
|
std::unique_lock lock(windowView->workerMutex);
|
||||||
windowView->view->commitUpdate();
|
windowView->view->commitUpdate();
|
||||||
|
}
|
||||||
|
windowView->updateFinished.raise();
|
||||||
|
{
|
||||||
|
std::unique_lock lock(windowView->workerMutex);
|
||||||
windowView->view->prepareRender();
|
windowView->view->prepareRender();
|
||||||
|
}
|
||||||
|
windowView->updateFinished.reset();
|
||||||
windowView->view->render();
|
windowView->view->render();
|
||||||
}
|
}
|
||||||
gfxHandle->endFrame();
|
gfxHandle->endFrame();
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/GraphicsResources.h"
|
#include "Graphics/GraphicsResources.h"
|
||||||
#include "View.h"
|
#include "View.h"
|
||||||
|
#include "ThreadPool.h"
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
struct WindowView
|
struct WindowView
|
||||||
{
|
{
|
||||||
PView view;
|
PView view;
|
||||||
|
Event updateFinished;
|
||||||
std::thread worker;
|
std::thread worker;
|
||||||
std::mutex workerMutex;
|
std::mutex workerMutex;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,12 +35,3 @@ PWindow WindowManager::addWindow(const WindowCreateInfo &createInfo)
|
|||||||
windows.add(window);
|
windows.add(window);
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::render()
|
|
||||||
{
|
|
||||||
for(auto window : windows)
|
|
||||||
{
|
|
||||||
window->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ public:
|
|||||||
WindowManager();
|
WindowManager();
|
||||||
~WindowManager();
|
~WindowManager();
|
||||||
PWindow addWindow(const WindowCreateInfo &createInfo);
|
PWindow addWindow(const WindowCreateInfo &createInfo);
|
||||||
void render();
|
|
||||||
static Gfx::PGraphics getGraphics()
|
static Gfx::PGraphics getGraphics()
|
||||||
{
|
{
|
||||||
return graphics;
|
return graphics;
|
||||||
|
|||||||
+2
-2
@@ -34,9 +34,9 @@ int main()
|
|||||||
PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
|
PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
|
||||||
window->addView(inspectorView);
|
window->addView(inspectorView);
|
||||||
sceneView->setFocused();
|
sceneView->setFocused();
|
||||||
while (windowManager->isActive())
|
while(true)
|
||||||
{
|
{
|
||||||
windowManager->render();
|
window->render();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user