Works, but with memory leaks
This commit is contained in:
Vendored
+5
-5
@@ -12,7 +12,7 @@
|
|||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceRoot}/bin/Debug",
|
"cwd": "${workspaceRoot}/bin/Debug",
|
||||||
"console": "internalConsole",
|
"console": "integratedTerminal",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"externalConsole": false,
|
"externalConsole": false,
|
||||||
"setupCommands": [
|
"setupCommands": [
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceRoot}/bin/Debug",
|
"cwd": "${workspaceRoot}/bin/Debug",
|
||||||
"console": "internalConsole",
|
"console": "integratedTerminal",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
||||||
"requireExactSource": false,
|
"requireExactSource": false,
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceRoot}/bin/Release",
|
"cwd": "${workspaceRoot}/bin/Release",
|
||||||
"console": "internalConsole",
|
"console": "integratedTerminal",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
||||||
"requireExactSource": false,
|
"requireExactSource": false,
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests",
|
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests",
|
||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"console": "internalConsole",
|
"console": "integratedTerminal",
|
||||||
"cwd": "${workspaceRoot}/bin/Debug",
|
"cwd": "${workspaceRoot}/bin/Debug",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
},
|
},
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
|
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
|
||||||
"args": ["--detect_memory_leaks=15533"],
|
"args": ["--detect_memory_leaks=15533"],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"console": "internalConsole",
|
"console": "integratedTerminal",
|
||||||
"cwd": "${workspaceRoot}/bin/Debug",
|
"cwd": "${workspaceRoot}/bin/Debug",
|
||||||
"visualizerFile": "${workspaceRoot}/Seele.natvis",
|
"visualizerFile": "${workspaceRoot}/Seele.natvis",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
|
|||||||
+1
-1
@@ -111,7 +111,7 @@ add_subdirectory(src/)
|
|||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
set(_CRT_SECURE_NO_WARNINGS)
|
set(_CRT_SECURE_NO_WARNINGS)
|
||||||
target_compile_options(Engine PRIVATE /Zi /MP)
|
target_compile_options(Engine PRIVATE /Zi /MP /DEBUG:FASTLINK)
|
||||||
else()
|
else()
|
||||||
target_compile_options(Engine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
|
target_compile_options(Engine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -33,13 +33,6 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"CMAKE_PLATFORM": "x64"
|
"CMAKE_PLATFORM": "x64"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"x86": {
|
|
||||||
"short": "x86",
|
|
||||||
"long": "x86 platform",
|
|
||||||
"settings": {
|
|
||||||
"CMAKE_PLATFORM": "x86"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,414 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
template<typename T, Allocator = std::pmr::polymorphic_allocator<T>>
|
||||||
|
class RingBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename X>
|
||||||
|
class IteratorBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category = std::random_access_iterator_tag;
|
||||||
|
using value_type = X;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using reference = X&;
|
||||||
|
using pointer = X*;
|
||||||
|
|
||||||
|
IteratorBase(Array<T>& arr, size_t index)
|
||||||
|
: arr(arr)
|
||||||
|
, index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
reference operator*() const
|
||||||
|
{
|
||||||
|
return arr[index];
|
||||||
|
}
|
||||||
|
pointer operator->() const
|
||||||
|
{
|
||||||
|
return &arr[index];
|
||||||
|
}
|
||||||
|
inline bool operator!=(const IteratorBase &other) const
|
||||||
|
{
|
||||||
|
return arr != other.arr && index != other.index;
|
||||||
|
}
|
||||||
|
inline bool operator==(const IteratorBase &other) const
|
||||||
|
{
|
||||||
|
return arr == other.arr && index == other.index;
|
||||||
|
}
|
||||||
|
inline int operator-(const IteratorBase &other) const
|
||||||
|
{
|
||||||
|
return (int)(index - other.index);
|
||||||
|
}
|
||||||
|
IteratorBase &operator++()
|
||||||
|
{
|
||||||
|
index = (index + 1) % arr.size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
IteratorBase &operator--()
|
||||||
|
{
|
||||||
|
index = (index + 1) % arr.size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
IteratorBase operator++(int)
|
||||||
|
{
|
||||||
|
IteratorBase tmp(*this);
|
||||||
|
++*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
IteratorBase operator--(int)
|
||||||
|
{
|
||||||
|
IteratorBase tmp(*this);
|
||||||
|
--*this;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Array<T, Allocator>& arr;
|
||||||
|
size_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 RingBuffer() noexcept(noexcept(Allocator()))
|
||||||
|
{
|
||||||
|
refreshIterators();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit RingBuffer(const allocator_type& alloc)
|
||||||
|
: data(alloc)
|
||||||
|
{
|
||||||
|
refreshIterators();
|
||||||
|
}
|
||||||
|
constexpr RingBuffer(size_type size, const value_type& value, const allocator_type& alloc = allocator_type())
|
||||||
|
: data(size, value, alloc)
|
||||||
|
, end(size)
|
||||||
|
{
|
||||||
|
refreshIterators();
|
||||||
|
}
|
||||||
|
constexpr explicit RingBuffer(size_type size, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(size)
|
||||||
|
, allocated(size)
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateRingBuffer(size);
|
||||||
|
assert(_data != nullptr);
|
||||||
|
for (size_type i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[i]);
|
||||||
|
}
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr RingBuffer(std::initializer_list<T> init, const allocator_type& alloc = allocator_type())
|
||||||
|
: arraySize(init.size())
|
||||||
|
, allocated(init.size())
|
||||||
|
, allocator(alloc)
|
||||||
|
{
|
||||||
|
_data = allocateRingBuffer(init.size());
|
||||||
|
assert(_data != nullptr);
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(init.begin(), init.end(), begin());
|
||||||
|
}
|
||||||
|
RingBuffer(const RingBuffer &other)
|
||||||
|
: arraySize(other.arraySize)
|
||||||
|
, allocated(other.allocated)
|
||||||
|
, allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
|
||||||
|
{
|
||||||
|
_data = allocateRingBuffer(other.allocated);
|
||||||
|
assert(_data != nullptr);
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||||
|
}
|
||||||
|
RingBuffer(RingBuffer &&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();
|
||||||
|
}
|
||||||
|
RingBuffer &operator=(const RingBuffer &other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value )
|
||||||
|
{
|
||||||
|
if (!std::allocator_traits<allocator_type>::is_always_equal::value
|
||||||
|
&& allocator != other.allocator)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
allocator = other.allocator;
|
||||||
|
}
|
||||||
|
if (other.arraySize > allocated)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
if(_data == nullptr)
|
||||||
|
{
|
||||||
|
_data = allocateRingBuffer(other.allocated);
|
||||||
|
allocated = other.allocated;
|
||||||
|
}
|
||||||
|
arraySize = other.arraySize;
|
||||||
|
markIteratorDirty();
|
||||||
|
std::uninitialized_copy(other.begin(), other.end(), begin());
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
RingBuffer &operator=(RingBuffer &&other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
|
||||||
|
{
|
||||||
|
allocator = std::move(other.allocator);
|
||||||
|
}
|
||||||
|
if (_data != nullptr)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
allocated = std::move(other.allocated);
|
||||||
|
arraySize = std::move(other.arraySize);
|
||||||
|
_data = other._data;
|
||||||
|
other._data = nullptr;
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
~RingBuffer()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const RingBuffer &other)
|
||||||
|
{
|
||||||
|
return _data == other._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(const RingBuffer &other)
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator find(const value_type &item)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
if (_data[i] == item)
|
||||||
|
{
|
||||||
|
return iterator(&_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endIt;
|
||||||
|
}
|
||||||
|
constexpr iterator find(value_type&& item)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
if (_data[i] == item)
|
||||||
|
{
|
||||||
|
return iterator(&_data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endIt;
|
||||||
|
}
|
||||||
|
constexpr allocator_type get_allocator() const
|
||||||
|
{
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
constexpr iterator begin() const
|
||||||
|
{
|
||||||
|
return beginIt;
|
||||||
|
}
|
||||||
|
constexpr iterator end() const
|
||||||
|
{
|
||||||
|
return endIt;
|
||||||
|
}
|
||||||
|
constexpr const_iterator cbegin() const
|
||||||
|
{
|
||||||
|
return beginIt;
|
||||||
|
}
|
||||||
|
constexpr const_iterator cend() const
|
||||||
|
{
|
||||||
|
return endIt;
|
||||||
|
}
|
||||||
|
constexpr reference add(const value_type &item = value_type())
|
||||||
|
{
|
||||||
|
return addInternal(item);
|
||||||
|
}
|
||||||
|
constexpr reference add(value_type&& item)
|
||||||
|
{
|
||||||
|
return addInternal(std::forward<T>(item));
|
||||||
|
}
|
||||||
|
constexpr void addAll(RingBuffer other)
|
||||||
|
{
|
||||||
|
for(auto value : other)
|
||||||
|
{
|
||||||
|
addInternal(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
constexpr reference addUnique(const value_type &item = value_type())
|
||||||
|
{
|
||||||
|
iterator it;
|
||||||
|
if((it = std::move(find(item))) != endIt)
|
||||||
|
{
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
return addInternal(item);
|
||||||
|
}
|
||||||
|
template<typename... args>
|
||||||
|
constexpr reference emplace(args... arguments)
|
||||||
|
{
|
||||||
|
if (arraySize == allocated)
|
||||||
|
{
|
||||||
|
size_type newSize = arraySize + 1;
|
||||||
|
allocated = calculateGrowth(newSize);
|
||||||
|
T *tempRingBuffer = allocateRingBuffer(allocated);
|
||||||
|
assert(tempRingBuffer != nullptr);
|
||||||
|
|
||||||
|
std::uninitialized_move(begin(), end(), Iterator(tempRingBuffer));
|
||||||
|
deallocateRingBuffer(_data, arraySize);
|
||||||
|
_data = tempRingBuffer;
|
||||||
|
}
|
||||||
|
std::allocator_traits<allocator_type>::construct(allocator, &_data[arraySize++], arguments...);
|
||||||
|
markIteratorDirty();
|
||||||
|
return _data[arraySize - 1];
|
||||||
|
}
|
||||||
|
constexpr void remove(iterator it, bool keepOrder = true)
|
||||||
|
{
|
||||||
|
remove(it - beginIt, keepOrder);
|
||||||
|
}
|
||||||
|
constexpr void remove(size_type index, bool keepOrder = true)
|
||||||
|
{
|
||||||
|
if (keepOrder)
|
||||||
|
{
|
||||||
|
for(uint32 i = index; i < arraySize-1; ++i)
|
||||||
|
{
|
||||||
|
_data[i] = std::move(_data[i+1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_data[index] = std::move(_data[arraySize - 1]);
|
||||||
|
}
|
||||||
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[--arraySize]);
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr void resize(size_type newSize)
|
||||||
|
{
|
||||||
|
resizeInternal(newSize, std::move(T()));
|
||||||
|
}
|
||||||
|
constexpr void resize(size_type newSize, const value_type& value)
|
||||||
|
{
|
||||||
|
resizeInternal(newSize, value);
|
||||||
|
}
|
||||||
|
constexpr void clear()
|
||||||
|
{
|
||||||
|
if(_data == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(size_type i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[i]);
|
||||||
|
}
|
||||||
|
deallocateRingBuffer(_data, allocated);
|
||||||
|
_data = nullptr;
|
||||||
|
arraySize = 0;
|
||||||
|
allocated = 0;
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
inline size_type indexOf(iterator iterator)
|
||||||
|
{
|
||||||
|
return iterator - beginIt;
|
||||||
|
}
|
||||||
|
inline size_type indexOf(const_iterator iterator) const
|
||||||
|
{
|
||||||
|
return iterator.p - beginIt.p;
|
||||||
|
}
|
||||||
|
inline size_type indexOf(T& t)
|
||||||
|
{
|
||||||
|
return indexOf(find(t));
|
||||||
|
}
|
||||||
|
inline size_type indexOf(const T& t) const
|
||||||
|
{
|
||||||
|
return indexOf(find(t));
|
||||||
|
}
|
||||||
|
inline size_type size() const
|
||||||
|
{
|
||||||
|
return arraySize;
|
||||||
|
}
|
||||||
|
inline size_type empty() const
|
||||||
|
{
|
||||||
|
return arraySize == 0;
|
||||||
|
}
|
||||||
|
inline size_type capacity() const
|
||||||
|
{
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
inline pointer data() const
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
inline reference front() const
|
||||||
|
{
|
||||||
|
assert(arraySize > 0);
|
||||||
|
return _data[0];
|
||||||
|
}
|
||||||
|
inline reference back() const
|
||||||
|
{
|
||||||
|
assert(arraySize > 0);
|
||||||
|
return _data[arraySize - 1];
|
||||||
|
}
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
std::allocator_traits<allocator_type>::destroy(allocator, &_data[--arraySize]);
|
||||||
|
markIteratorDirty();
|
||||||
|
}
|
||||||
|
constexpr inline reference operator[](size_type index)
|
||||||
|
{
|
||||||
|
assert(index < arraySize);
|
||||||
|
return _data[index];
|
||||||
|
}
|
||||||
|
constexpr inline const reference operator[](size_type index) const
|
||||||
|
{
|
||||||
|
assert(index < arraySize);
|
||||||
|
return _data[index];
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void refreshIterators()
|
||||||
|
{
|
||||||
|
beginIt = Iterator(data, begin);
|
||||||
|
endIt = Iterator(data, end);
|
||||||
|
}
|
||||||
|
size_type begin = 0;
|
||||||
|
size_type end = 0;
|
||||||
|
iterator beginIt;
|
||||||
|
iterator endIt;
|
||||||
|
Array<T, Allocator> data;
|
||||||
|
};
|
||||||
|
class StaticRingBuffer
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace Seele
|
||||||
@@ -171,12 +171,6 @@ void CmdBuffer::waitForCommand(uint32 timeout)
|
|||||||
refreshFence();
|
refreshFence();
|
||||||
}
|
}
|
||||||
|
|
||||||
Event CmdBuffer::asyncWait() const
|
|
||||||
{
|
|
||||||
return fence->asyncWait();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PFence CmdBuffer::getFence()
|
PFence CmdBuffer::getFence()
|
||||||
{
|
{
|
||||||
return fence;
|
return fence;
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ public:
|
|||||||
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
|
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
|
||||||
void refreshFence();
|
void refreshFence();
|
||||||
void waitForCommand(uint32 timeToWait = 1000000u);
|
void waitForCommand(uint32 timeToWait = 1000000u);
|
||||||
Event asyncWait() const;
|
Fence* operator co_await()
|
||||||
|
{
|
||||||
|
return fence.getHandle();
|
||||||
|
}
|
||||||
PFence getFence();
|
PFence getFence();
|
||||||
PCommandBufferManager getManager();
|
PCommandBufferManager getManager();
|
||||||
enum State
|
enum State
|
||||||
|
|||||||
@@ -80,11 +80,6 @@ void Fence::wait(uint32 timeout)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event Fence::asyncWait() const
|
|
||||||
{
|
|
||||||
return signaled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList)
|
VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList)
|
||||||
: elementList(elementList)
|
: elementList(elementList)
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ public:
|
|||||||
return fence;
|
return fence;
|
||||||
}
|
}
|
||||||
void wait(uint32 timeout);
|
void wait(uint32 timeout);
|
||||||
Event asyncWait() const;
|
Event& operator co_await()
|
||||||
|
{
|
||||||
|
return signaled;
|
||||||
|
}
|
||||||
bool operator<(const Fence &other) const
|
bool operator<(const Fence &other) const
|
||||||
{
|
{
|
||||||
return fence < other.fence;
|
return fence < other.fence;
|
||||||
|
|||||||
@@ -146,15 +146,15 @@ Vector Transform::getScale() const
|
|||||||
|
|
||||||
Vector Transform::getForward() const
|
Vector Transform::getForward() const
|
||||||
{
|
{
|
||||||
return Vector(0, 0, 1) * rotation;
|
return glm::normalize(Vector(0, 0, 1) * rotation);
|
||||||
}
|
}
|
||||||
Vector Transform::getRight() const
|
Vector Transform::getRight() const
|
||||||
{
|
{
|
||||||
return Vector(1, 0, 0) * rotation;
|
return glm::normalize(Vector(1, 0, 0) * rotation);
|
||||||
}
|
}
|
||||||
Vector Transform::getUp() const
|
Vector Transform::getUp() const
|
||||||
{
|
{
|
||||||
return Vector(0, 1, 0) * rotation;
|
return glm::normalize(Vector(0, 1, 0) * rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transform::equals(const Transform &other, float tolerance)
|
bool Transform::equals(const Transform &other, float tolerance)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ CameraActor::CameraActor()
|
|||||||
cameraComponent->aspectRatio = 1.777778f;
|
cameraComponent->aspectRatio = 1.777778f;
|
||||||
cameraComponent->setParent(sceneComponent);
|
cameraComponent->setParent(sceneComponent);
|
||||||
cameraComponent->setOwner(this);
|
cameraComponent->setOwner(this);
|
||||||
|
sceneComponent->addChildComponent(cameraComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraActor::~CameraActor()
|
CameraActor::~CameraActor()
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ CameraComponent::CameraComponent()
|
|||||||
, projectionMatrix(Matrix4())
|
, projectionMatrix(Matrix4())
|
||||||
, viewMatrix(Matrix4())
|
, viewMatrix(Matrix4())
|
||||||
{
|
{
|
||||||
rotationX = 0;
|
yaw = 0;
|
||||||
rotationY = 0;
|
pitch = 0;
|
||||||
setRelativeLocation(Vector(0, 10, -50));
|
setRelativeLocation(Vector(0, 10, -50));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,12 +22,16 @@ CameraComponent::~CameraComponent()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraComponent::mouseMove(float deltaX, float deltaY)
|
void CameraComponent::mouseMove(float deltaYaw, float deltaPitch)
|
||||||
{
|
{
|
||||||
rotationX -= deltaX / 1000.f;
|
yaw -= deltaYaw / 500.f;
|
||||||
rotationY += deltaY / 1000.f;
|
pitch += deltaPitch / 500.f;
|
||||||
//std::cout << "X:" << rotationX << " Y: " << rotationY << std::endl;
|
//std::cout << "Yaw: " << yaw << " Pitch: " << pitch << std::endl;
|
||||||
setRelativeRotation(Vector(rotationY, rotationX, 0));
|
Vector cameraDirection = glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
|
||||||
|
Vector xyz = glm::cross(cameraDirection, Vector(0, 0, 1));
|
||||||
|
Quaternion result = Quaternion(glm::dot(cameraDirection, Vector(0, 0, 1)) + 1, xyz.x, xyz.y, xyz.z);
|
||||||
|
//std::cout << "Result " << Vector(0, 0, 1) * glm::normalize(result) << " cameraDirection: " << cameraDirection << std::endl;
|
||||||
|
setRelativeRotation(result);
|
||||||
bNeedsViewBuild = true;
|
bNeedsViewBuild = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +55,9 @@ void CameraComponent::moveY(float amount)
|
|||||||
|
|
||||||
void CameraComponent::buildViewMatrix()
|
void CameraComponent::buildViewMatrix()
|
||||||
{
|
{
|
||||||
Vector eyePos = getTransform().getPosition();
|
Vector eyePos = getAbsoluteTransform().getPosition();
|
||||||
Vector lookAt = eyePos + getTransform().getForward();
|
Vector lookAt = eyePos + glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
|
||||||
std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
|
//std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
|
||||||
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
|
||||||
|
|
||||||
bNeedsViewBuild = false;
|
bNeedsViewBuild = false;
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ private:
|
|||||||
//Transforms relative to actor
|
//Transforms relative to actor
|
||||||
Matrix4 viewMatrix;
|
Matrix4 viewMatrix;
|
||||||
Matrix4 projectionMatrix;
|
Matrix4 projectionMatrix;
|
||||||
float rotationX;
|
float yaw;
|
||||||
float rotationY;
|
float pitch;
|
||||||
};
|
};
|
||||||
DEFINE_REF(CameraComponent)
|
DEFINE_REF(CameraComponent)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -128,18 +128,22 @@ void Component::notifySceneAttach(PScene scene)
|
|||||||
void Component::setRelativeLocation(Vector location)
|
void Component::setRelativeLocation(Vector location)
|
||||||
{
|
{
|
||||||
transform = Transform(location, transform.getRotation(), transform.getScale());
|
transform = Transform(location, transform.getRotation(), transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
void Component::setRelativeRotation(Vector rotation)
|
void Component::setRelativeRotation(Vector rotation)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
void Component::setRelativeRotation(Quaternion rotation)
|
void Component::setRelativeRotation(Quaternion rotation)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition(), rotation, transform.getScale());
|
transform = Transform(transform.getPosition(), rotation, transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
void Component::setRelativeScale(Vector scale)
|
void Component::setRelativeScale(Vector scale)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
|
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
//void Component::addAbsoluteTranslation(Vector translation)
|
//void Component::addAbsoluteTranslation(Vector translation)
|
||||||
@@ -161,14 +165,17 @@ void Component::setRelativeScale(Vector scale)
|
|||||||
void Component::addRelativeLocation(Vector translation)
|
void Component::addRelativeLocation(Vector translation)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
void Component::addRelativeRotation(Vector rotation)
|
void Component::addRelativeRotation(Vector rotation)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition(), transform.getRotation() + Quaternion(rotation), transform.getScale());
|
transform = Transform(transform.getPosition(), transform.getRotation() * Quaternion(rotation), transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
void Component::addRelativeRotation(Quaternion rotation)
|
void Component::addRelativeRotation(Quaternion rotation)
|
||||||
{
|
{
|
||||||
transform = Transform(transform.getPosition(), transform.getRotation(), transform.getScale());
|
transform = Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
|
||||||
|
propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform Component::getTransform() const
|
Transform Component::getTransform() const
|
||||||
@@ -177,10 +184,22 @@ Transform Component::getTransform() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Transform Component::getAbsoluteTransform() const
|
Transform Component::getAbsoluteTransform() const
|
||||||
|
{
|
||||||
|
return absoluteTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Component::propagateTransformUpdate()
|
||||||
{
|
{
|
||||||
if(parent != nullptr)
|
if(parent != nullptr)
|
||||||
{
|
{
|
||||||
return transform + parent->getAbsoluteTransform();
|
absoluteTransform = transform + parent->getAbsoluteTransform();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
absoluteTransform = transform;
|
||||||
|
}
|
||||||
|
for(auto child : children)
|
||||||
|
{
|
||||||
|
child->propagateTransformUpdate();
|
||||||
}
|
}
|
||||||
return transform;
|
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,9 @@ private:
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
void propagateTransformUpdate();
|
||||||
Transform transform;
|
Transform transform;
|
||||||
|
Transform absoluteTransform;
|
||||||
PScene owningScene;
|
PScene owningScene;
|
||||||
PActor owner;
|
PActor owner;
|
||||||
PComponent parent;
|
PComponent parent;
|
||||||
|
|||||||
+75
-94
@@ -3,55 +3,69 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
|
std::mutex Seele::promisesLock;
|
||||||
Event::Event()
|
List<Promise*> Seele::promises;
|
||||||
: flag(std::make_shared<StateStore>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::Event(nullptr_t)
|
Event::Event(nullptr_t)
|
||||||
: flag(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::Event(const std::string &name)
|
Event::Event(const std::string &name, const std::source_location &location)
|
||||||
: flag(std::make_shared<StateStore>())
|
: name(name)
|
||||||
|
, location(location)
|
||||||
{
|
{
|
||||||
flag->name = name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Event::Event(const std::source_location &location)
|
Event::Event(const std::source_location &location)
|
||||||
: flag(std::make_shared<StateStore>())
|
: name(location.function_name())
|
||||||
|
, location(location)
|
||||||
{
|
{
|
||||||
flag->name = location.function_name();
|
|
||||||
flag->location = location;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Event::raise()
|
void Event::raise()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(flag->lock);
|
std::scoped_lock lock(eventLock);
|
||||||
flag->data = 1;
|
data = true;
|
||||||
getGlobalThreadPool().notify(*this);
|
if(waitingJobs.size() > 0)
|
||||||
|
{
|
||||||
|
getGlobalThreadPool().scheduleBatch(waitingJobs);
|
||||||
|
}
|
||||||
|
if(waitingMainJobs.size() > 0)
|
||||||
|
{
|
||||||
|
getGlobalThreadPool().scheduleBatch(waitingMainJobs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void Event::reset()
|
void Event::reset()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(flag->lock);
|
std::scoped_lock lock(eventLock);
|
||||||
flag->data = 0;
|
data = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Event::await_ready()
|
bool Event::await_ready()
|
||||||
{
|
{
|
||||||
flag->lock.lock();
|
eventLock.lock();
|
||||||
bool result = flag->data;
|
bool result = data;
|
||||||
if(result)
|
if(result)
|
||||||
{
|
{
|
||||||
flag->lock.unlock();
|
eventLock.unlock();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Event::await_suspend(std::coroutine_handle<JobPromiseBase<false>> h)
|
||||||
|
{
|
||||||
|
//h.promise().enqueue(this);
|
||||||
|
waitingJobs.add(JobBase<false>(&h.promise()));
|
||||||
|
eventLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Event::await_suspend(std::coroutine_handle<JobPromiseBase<true>> h)
|
||||||
|
{
|
||||||
|
//h.promise().enqueue(this);
|
||||||
|
waitingMainJobs.add(JobBase<true>(&h.promise()));
|
||||||
|
eventLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
ThreadPool::ThreadPool(uint32 threadCount)
|
ThreadPool::ThreadPool(uint32 threadCount)
|
||||||
: workers(threadCount)
|
: workers(threadCount)
|
||||||
{
|
{
|
||||||
@@ -59,13 +73,24 @@ ThreadPool::ThreadPool(uint32 threadCount)
|
|||||||
for (uint32 i = 0; i < threadCount; ++i)
|
for (uint32 i = 0; i < threadCount; ++i)
|
||||||
{
|
{
|
||||||
workers[i] = std::thread(&ThreadPool::threadLoop, this);
|
workers[i] = std::thread(&ThreadPool::threadLoop, this);
|
||||||
workers[i].detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPool::~ThreadPool()
|
ThreadPool::~ThreadPool()
|
||||||
{
|
{
|
||||||
workers.clear();
|
running.store(false);
|
||||||
|
{
|
||||||
|
std::unique_lock lock(mainJobLock);
|
||||||
|
mainJobCV.notify_all();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_lock lock(jobQueueLock);
|
||||||
|
jobQueueCV.notify_all();
|
||||||
|
}
|
||||||
|
for(auto& worker : workers)
|
||||||
|
{
|
||||||
|
worker.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::waitIdle()
|
void ThreadPool::waitIdle()
|
||||||
@@ -73,108 +98,63 @@ void ThreadPool::waitIdle()
|
|||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
std::unique_lock lock(numIdlingLock);
|
std::unique_lock lock(numIdlingLock);
|
||||||
numIdlingIncr.wait(lock);
|
|
||||||
if(numIdling == workers.size())
|
if(numIdling == workers.size())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
numIdlingIncr.wait(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void ThreadPool::enqueueWaiting(Event &event, Promise* job)
|
void ThreadPool::scheduleJob(Job job)
|
||||||
{
|
{
|
||||||
assert(!job->done());
|
assert(!job.done());
|
||||||
std::scoped_lock lock(waitingLock);
|
|
||||||
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
|
|
||||||
waitingJobs[event].add(job);
|
|
||||||
job->addRef();
|
|
||||||
}
|
|
||||||
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
|
|
||||||
{
|
|
||||||
assert(!job->done());
|
|
||||||
std::scoped_lock lock(waitingMainLock);
|
|
||||||
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
|
|
||||||
waitingMainJobs[event].add(job);
|
|
||||||
job->addRef();
|
|
||||||
}
|
|
||||||
void ThreadPool::scheduleJob(Promise* job)
|
|
||||||
{
|
|
||||||
assert(!job->done());
|
|
||||||
std::scoped_lock lock(jobQueueLock);
|
std::scoped_lock lock(jobQueueLock);
|
||||||
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
|
jobQueue.add(std::move(job));
|
||||||
jobQueue.add(job);
|
|
||||||
jobQueueCV.notify_one();
|
jobQueueCV.notify_one();
|
||||||
job->addRef();
|
|
||||||
}
|
}
|
||||||
void ThreadPool::scheduleJob(MainPromise* job)
|
void ThreadPool::scheduleJob(MainJob job)
|
||||||
{
|
{
|
||||||
assert(!job->done());
|
assert(!job.done());
|
||||||
std::scoped_lock lock(mainJobLock);
|
std::scoped_lock lock(mainJobLock);
|
||||||
//std::cout << "Queueing job " << job->finishedEvent << std::endl;
|
mainJobs.add(std::move(job));
|
||||||
mainJobs.add(job);
|
|
||||||
mainJobCV.notify_one();
|
mainJobCV.notify_one();
|
||||||
job->addRef();
|
|
||||||
}
|
}
|
||||||
void ThreadPool::notify(Event &event)
|
|
||||||
{
|
|
||||||
//std::cout << "Event " << event.name << " raised" << std::endl;
|
|
||||||
{
|
|
||||||
std::scoped_lock lock(jobQueueLock, waitingLock);
|
|
||||||
List<Promise*> jobs = std::move(waitingJobs[event]);
|
|
||||||
waitingJobs.erase(event);
|
|
||||||
for (auto &job : jobs)
|
|
||||||
{
|
|
||||||
//assert(job.id != -1ull);
|
|
||||||
//std::cout << "Waking up " << job->finishedEvent.name << std::endl;
|
|
||||||
job->state = Promise::State::SCHEDULED;
|
|
||||||
jobQueue.add(job);
|
|
||||||
jobQueueCV.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::scoped_lock lock(mainJobLock, waitingMainLock);
|
|
||||||
List<MainPromise*> jobs = std::move(waitingMainJobs[event]);
|
|
||||||
waitingMainJobs.erase(event);
|
|
||||||
for (auto &job : jobs)
|
|
||||||
{
|
|
||||||
//assert(job.id != -1ull);
|
|
||||||
//std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
|
|
||||||
job->state = MainPromise::State::SCHEDULED;
|
|
||||||
mainJobs.add(job);
|
|
||||||
mainJobCV.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadPool::mainLoop()
|
void ThreadPool::mainLoop()
|
||||||
{
|
{
|
||||||
while(true)
|
while(running.load())
|
||||||
{
|
{
|
||||||
MainPromise* job;
|
MainJob job;
|
||||||
{
|
{
|
||||||
std::unique_lock lock(mainJobLock);
|
std::unique_lock lock(mainJobLock);
|
||||||
if(mainJobs.empty())
|
if(mainJobs.empty())
|
||||||
{
|
{
|
||||||
mainJobCV.wait(lock);
|
mainJobCV.wait(lock);
|
||||||
}
|
}
|
||||||
job = mainJobs.front();
|
[[likely]]
|
||||||
mainJobs.popFront();
|
if(!mainJobs.empty())
|
||||||
|
{
|
||||||
|
job = mainJobs.front();
|
||||||
|
mainJobs.popFront();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
job->resume();
|
job.resume();
|
||||||
job->removeRef();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::threadLoop()
|
void ThreadPool::threadLoop()
|
||||||
{
|
{
|
||||||
List<Promise*> localQueue;
|
List<Job> localQueue;
|
||||||
while (true)
|
while (running.load())
|
||||||
{
|
{
|
||||||
[[likely]]
|
[[likely]]
|
||||||
if(!localQueue.empty())
|
if(!localQueue.empty())
|
||||||
{
|
{
|
||||||
Promise* job = localQueue.retrieve();
|
Job job = localQueue.retrieve();
|
||||||
job->resume();
|
job.resume();
|
||||||
job->removeRef();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -194,7 +174,8 @@ void ThreadPool::threadLoop()
|
|||||||
}
|
}
|
||||||
// take 1/numThreads jobs, maybe make this a parameter that
|
// take 1/numThreads jobs, maybe make this a parameter that
|
||||||
// adjusts based on past workload
|
// adjusts based on past workload
|
||||||
uint32 numTaken = std::max(jobQueue.size() / workers.size(), 1ull);
|
uint32 partitionedWorkload = (uint32)(jobQueue.size() / workers.size());
|
||||||
|
uint32 numTaken = std::clamp(partitionedWorkload, 1u, localQueueSize);
|
||||||
while (!jobQueue.empty() && localQueue.size() < numTaken)
|
while (!jobQueue.empty() && localQueue.size() < numTaken)
|
||||||
{
|
{
|
||||||
localQueue.add(jobQueue.retrieve());
|
localQueue.add(jobQueue.retrieve());
|
||||||
|
|||||||
+79
-90
@@ -9,67 +9,66 @@
|
|||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
extern class ThreadPool& getGlobalThreadPool();
|
extern class ThreadPool& getGlobalThreadPool();
|
||||||
|
template<bool MainJob>
|
||||||
|
struct JobBase;
|
||||||
template<bool MainJob>
|
template<bool MainJob>
|
||||||
struct JobPromiseBase;
|
struct JobPromiseBase;
|
||||||
struct Event
|
struct Event
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event();
|
|
||||||
Event(nullptr_t);
|
Event(nullptr_t);
|
||||||
Event(const std::string& name);
|
Event(const std::string& name, const std::source_location& location = std::source_location::current());
|
||||||
Event(const std::source_location& location);
|
Event(const std::source_location& location = std::source_location::current());
|
||||||
|
Event(const Event& other) = delete;
|
||||||
|
Event(Event&& other) = default;
|
||||||
~Event() = default;
|
~Event() = default;
|
||||||
|
Event& operator=(const Event& other) = delete;
|
||||||
|
Event& operator=(Event&& other) = default;
|
||||||
auto operator<=>(const Event& other) const
|
auto operator<=>(const Event& other) const
|
||||||
{
|
{
|
||||||
return flag <=> other.flag;
|
return name <=> other.name;
|
||||||
}
|
}
|
||||||
bool operator==(const Event& other) const
|
bool operator==(const Event& other) const
|
||||||
{
|
{
|
||||||
return flag == other.flag;
|
return name == other.name;
|
||||||
}
|
|
||||||
Event operator co_await()
|
|
||||||
{
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(flag->lock);
|
std::scoped_lock lock(eventLock);
|
||||||
return flag->data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& stream, const Event& event)
|
friend std::ostream& operator<<(std::ostream& stream, const Event& event)
|
||||||
{
|
{
|
||||||
stream
|
stream
|
||||||
<< event.flag->location.file_name()
|
<< event.location.file_name()
|
||||||
<< "("
|
<< "("
|
||||||
<< event.flag->location.line()
|
<< event.location.line()
|
||||||
<< ":"
|
<< ":"
|
||||||
<< event.flag->location.column()
|
<< event.location.column()
|
||||||
<< "): "
|
<< "): "
|
||||||
<< event.flag->location.function_name();
|
<< event.location.function_name();
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void raise();
|
void raise();
|
||||||
void reset();
|
void reset();
|
||||||
bool await_ready();
|
bool await_ready();
|
||||||
template<bool MainJob>
|
void await_suspend(std::coroutine_handle<JobPromiseBase<false>> h);
|
||||||
constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h);
|
void await_suspend(std::coroutine_handle<JobPromiseBase<true>> h);
|
||||||
constexpr void await_resume() {}
|
constexpr void await_resume() {}
|
||||||
private:
|
private:
|
||||||
struct StateStore
|
std::mutex eventLock;
|
||||||
{
|
std::string name;
|
||||||
std::mutex lock;
|
std::source_location location;
|
||||||
std::string name;
|
bool data = false;
|
||||||
std::source_location location;
|
Array<JobBase<false>> waitingJobs;
|
||||||
bool data;
|
Array<JobBase<true>> waitingMainJobs;
|
||||||
};
|
|
||||||
std::shared_ptr<StateStore> flag;
|
|
||||||
friend class ThreadPool;
|
friend class ThreadPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool MainJob>
|
extern std::mutex promisesLock;
|
||||||
struct JobBase;
|
extern List<JobPromiseBase<false>*> promises;
|
||||||
template<bool MainJob>
|
template<bool MainJob>
|
||||||
struct JobPromiseBase
|
struct JobPromiseBase
|
||||||
{
|
{
|
||||||
@@ -82,12 +81,24 @@ struct JobPromiseBase
|
|||||||
DONE
|
DONE
|
||||||
};
|
};
|
||||||
JobPromiseBase(const std::source_location& location = std::source_location::current())
|
JobPromiseBase(const std::source_location& location = std::source_location::current())
|
||||||
|
: handle(std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this))
|
||||||
|
, finishedEvent(Event(location))
|
||||||
{
|
{
|
||||||
handle = std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this);
|
if constexpr(!MainJob)
|
||||||
finishedEvent = Event(location);
|
{
|
||||||
|
std::scoped_lock lock(promisesLock);
|
||||||
|
promises.add(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
~JobPromiseBase()
|
~JobPromiseBase()
|
||||||
{}
|
{
|
||||||
|
if constexpr (!MainJob)
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(promisesLock);
|
||||||
|
promises.remove(promises.find(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JobBase<MainJob> get_return_object() noexcept;
|
JobBase<MainJob> get_return_object() noexcept;
|
||||||
|
|
||||||
inline auto initial_suspend() noexcept;
|
inline auto initial_suspend() noexcept;
|
||||||
@@ -102,7 +113,6 @@ struct JobPromiseBase
|
|||||||
|
|
||||||
void resume()
|
void resume()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(promiseLock);
|
|
||||||
if(!handle || handle.done() || executing())
|
if(!handle || handle.done() || executing())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -116,17 +126,16 @@ struct JobPromiseBase
|
|||||||
finishedEvent.raise();
|
finishedEvent.raise();
|
||||||
if(continuation)
|
if(continuation)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(continuation->promiseLock);
|
getGlobalThreadPool().scheduleJob(JobBase<MainJob>(continuation));
|
||||||
getGlobalThreadPool().scheduleJob(continuation);
|
|
||||||
continuation->removeRef();
|
continuation->removeRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void setContinuation(JobPromiseBase* cont)
|
void setContinuation(JobPromiseBase* cont)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(promiseLock, cont->promiseLock);
|
|
||||||
assert(cont->ready());
|
assert(cont->ready());
|
||||||
continuation = cont;
|
continuation = cont;
|
||||||
cont->state = State::SCHEDULED;
|
cont->state = State::SCHEDULED;
|
||||||
|
cont->waitingFor = &finishedEvent;
|
||||||
cont->addRef();
|
cont->addRef();
|
||||||
}
|
}
|
||||||
bool done()
|
bool done()
|
||||||
@@ -149,29 +158,25 @@ struct JobPromiseBase
|
|||||||
{
|
{
|
||||||
return state == State::READY;
|
return state == State::READY;
|
||||||
}
|
}
|
||||||
void reset()
|
void enqueue(Event* event)
|
||||||
{
|
|
||||||
std::scoped_lock lock(promiseLock);
|
|
||||||
finishedEvent.reset();
|
|
||||||
}
|
|
||||||
void enqueue(Event& event)
|
|
||||||
{
|
{
|
||||||
if(!handle || handle.done() || waiting() || scheduled())
|
if(!handle || handle.done() || waiting() || scheduled())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state = State::WAITING;
|
state = State::WAITING;
|
||||||
getGlobalThreadPool().enqueueWaiting(event, this);
|
waitingFor = event;
|
||||||
|
getGlobalThreadPool().enqueueWaiting(event, std::move(JobBase<MainJob>(this)));
|
||||||
}
|
}
|
||||||
void schedule()
|
bool schedule()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(promiseLock);
|
|
||||||
if(!handle || done() || !ready())
|
if(!handle || done() || !ready())
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
state = State::SCHEDULED;
|
state = State::SCHEDULED;
|
||||||
getGlobalThreadPool().scheduleJob(this);
|
getGlobalThreadPool().scheduleJob(std::move(JobBase<MainJob>(this)));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
void addRef()
|
void addRef()
|
||||||
{
|
{
|
||||||
@@ -179,25 +184,23 @@ struct JobPromiseBase
|
|||||||
}
|
}
|
||||||
void removeRef()
|
void removeRef()
|
||||||
{
|
{
|
||||||
if(--numRefs < 1)
|
numRefs--;
|
||||||
|
if(numRefs == 0)
|
||||||
{
|
{
|
||||||
if(done())
|
if(!schedule())
|
||||||
{
|
{
|
||||||
handle.destroy();
|
handle.destroy();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
schedule();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
uint64 pad0 = 0x7472617453;
|
||||||
std::mutex promiseLock;
|
|
||||||
std::coroutine_handle<JobPromiseBase> handle;
|
std::coroutine_handle<JobPromiseBase> handle;
|
||||||
|
Event* waitingFor = nullptr;
|
||||||
JobPromiseBase* continuation = nullptr;
|
JobPromiseBase* continuation = nullptr;
|
||||||
std::atomic_uint64_t numRefs = 0;
|
uint64 numRefs = 0;
|
||||||
Event finishedEvent;
|
Event finishedEvent;
|
||||||
State state = State::READY;
|
State state = State::READY;
|
||||||
|
uint64 pad1 = 0x646E45;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool MainJob = false>
|
template<bool MainJob = false>
|
||||||
@@ -213,16 +216,15 @@ public:
|
|||||||
explicit JobBase(JobPromiseBase<MainJob>* promise)
|
explicit JobBase(JobPromiseBase<MainJob>* promise)
|
||||||
: promise(promise)
|
: promise(promise)
|
||||||
{
|
{
|
||||||
|
promise->addRef();
|
||||||
}
|
}
|
||||||
JobBase(const JobBase& other)
|
JobBase(const JobBase& other)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(other.promise->promiseLock);
|
|
||||||
promise = other.promise;
|
promise = other.promise;
|
||||||
promise->addRef();
|
promise->addRef();
|
||||||
}
|
}
|
||||||
JobBase(JobBase&& other)
|
JobBase(JobBase&& other)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(other.promise->promiseLock);
|
|
||||||
promise = other.promise;
|
promise = other.promise;
|
||||||
other.promise = nullptr;
|
other.promise = nullptr;
|
||||||
}
|
}
|
||||||
@@ -238,7 +240,10 @@ public:
|
|||||||
{
|
{
|
||||||
if(this != &other)
|
if(this != &other)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(other.promise->promiseLock);
|
if(promise != nullptr)
|
||||||
|
{
|
||||||
|
promise->removeRef();
|
||||||
|
}
|
||||||
promise = other.promise;
|
promise = other.promise;
|
||||||
promise->addRef();
|
promise->addRef();
|
||||||
}
|
}
|
||||||
@@ -248,7 +253,10 @@ public:
|
|||||||
{
|
{
|
||||||
if(this != &other)
|
if(this != &other)
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(other.promise->promiseLock);
|
if(promise != nullptr)
|
||||||
|
{
|
||||||
|
promise->removeRef();
|
||||||
|
}
|
||||||
promise = other.promise;
|
promise = other.promise;
|
||||||
other.promise = nullptr;
|
other.promise = nullptr;
|
||||||
}
|
}
|
||||||
@@ -273,7 +281,7 @@ public:
|
|||||||
{
|
{
|
||||||
return promise->done();
|
return promise->done();
|
||||||
}
|
}
|
||||||
Event operator co_await() const
|
Event& operator co_await()
|
||||||
{
|
{
|
||||||
// the co_await operator keeps a reference to this, it won't
|
// the co_await operator keeps a reference to this, it won't
|
||||||
// be scheduled from the destructor
|
// be scheduled from the destructor
|
||||||
@@ -311,8 +319,7 @@ public:
|
|||||||
Array<JobBase> jobs;
|
Array<JobBase> jobs;
|
||||||
for(auto&& param : params)
|
for(auto&& param : params)
|
||||||
{
|
{
|
||||||
JobBase base = func(param);
|
jobs.add(func(param));
|
||||||
jobs.add(base);
|
|
||||||
}
|
}
|
||||||
getGlobalThreadPool().scheduleBatch(jobs);
|
getGlobalThreadPool().scheduleBatch(jobs);
|
||||||
for(auto job : jobs)
|
for(auto job : jobs)
|
||||||
@@ -333,15 +340,11 @@ using Promise = JobPromiseBase<false>;
|
|||||||
class ThreadPool
|
class ThreadPool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
|
ThreadPool(uint32 threadCount = 1);//std::thread::hardware_concurrency());
|
||||||
virtual ~ThreadPool();
|
virtual ~ThreadPool();
|
||||||
void waitIdle();
|
void waitIdle();
|
||||||
// Adds a job to the waiting queue for event
|
void scheduleJob(Job job);
|
||||||
void enqueueWaiting(Event& event, Promise* job);
|
void scheduleJob(MainJob job);
|
||||||
// Adds a job to the waiting queue for event
|
|
||||||
void enqueueWaiting(Event& event, MainPromise* job);
|
|
||||||
void scheduleJob(Promise* job);
|
|
||||||
void scheduleJob(MainPromise* job);
|
|
||||||
template<std::ranges::range Iterable>
|
template<std::ranges::range Iterable>
|
||||||
requires std::same_as<std::ranges::range_value_t<Iterable>, MainJob>
|
requires std::same_as<std::ranges::range_value_t<Iterable>, MainJob>
|
||||||
void scheduleBatch(Iterable jobs)
|
void scheduleBatch(Iterable jobs)
|
||||||
@@ -349,9 +352,9 @@ public:
|
|||||||
std::scoped_lock lock(mainJobLock);
|
std::scoped_lock lock(mainJobLock);
|
||||||
for(auto job : jobs)
|
for(auto job : jobs)
|
||||||
{
|
{
|
||||||
job.promise->addRef();
|
//job.promise->addRef();
|
||||||
job.promise->state = JobPromiseBase<true>::State::SCHEDULED;
|
job.promise->state = JobPromiseBase<true>::State::SCHEDULED;
|
||||||
mainJobs.add(job.promise);
|
mainJobs.add(job);
|
||||||
}
|
}
|
||||||
mainJobCV.notify_one();
|
mainJobCV.notify_one();
|
||||||
}
|
}
|
||||||
@@ -362,13 +365,13 @@ public:
|
|||||||
std::scoped_lock lock(jobQueueLock);
|
std::scoped_lock lock(jobQueueLock);
|
||||||
for(auto job : jobs)
|
for(auto job : jobs)
|
||||||
{
|
{
|
||||||
job.promise->addRef();
|
//job.promise->addRef();
|
||||||
job.promise->state = JobPromiseBase<false>::State::SCHEDULED;
|
job.promise->state = JobPromiseBase<false>::State::SCHEDULED;
|
||||||
jobQueue.add(job.promise);
|
jobQueue.add(job);
|
||||||
}
|
}
|
||||||
jobQueueCV.notify_all();
|
jobQueueCV.notify_all();
|
||||||
}
|
}
|
||||||
void notify(Event& event);
|
void notify(Event* event);
|
||||||
void mainLoop();
|
void mainLoop();
|
||||||
void threadLoop();
|
void threadLoop();
|
||||||
private:
|
private:
|
||||||
@@ -378,27 +381,20 @@ private:
|
|||||||
uint32 numIdling;
|
uint32 numIdling;
|
||||||
Array<std::thread> workers;
|
Array<std::thread> workers;
|
||||||
|
|
||||||
List<MainPromise*> mainJobs;
|
List<MainJob> mainJobs;
|
||||||
std::mutex mainJobLock;
|
std::mutex mainJobLock;
|
||||||
std::condition_variable mainJobCV;
|
std::condition_variable mainJobCV;
|
||||||
|
|
||||||
List<Promise*> jobQueue;
|
List<Job> jobQueue;
|
||||||
std::mutex jobQueueLock;
|
std::mutex jobQueueLock;
|
||||||
std::condition_variable jobQueueCV;
|
std::condition_variable jobQueueCV;
|
||||||
|
|
||||||
Map<Event, List<MainPromise*>> waitingMainJobs;
|
|
||||||
std::mutex waitingMainLock;
|
|
||||||
|
|
||||||
Map<Event, List<Promise*>> waitingJobs;
|
uint32 localQueueSize = 50;
|
||||||
std::mutex waitingLock;
|
|
||||||
|
|
||||||
uint32 maxLocalQueueSize = 50;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool MainJob>
|
template<bool MainJob>
|
||||||
inline JobBase<MainJob> JobPromiseBase<MainJob>::get_return_object() noexcept
|
inline JobBase<MainJob> JobPromiseBase<MainJob>::get_return_object() noexcept
|
||||||
{
|
{
|
||||||
numRefs++;
|
|
||||||
return JobBase<MainJob>(this);
|
return JobBase<MainJob>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,11 +411,4 @@ inline auto JobPromiseBase<MainJob>::final_suspend() noexcept
|
|||||||
return std::suspend_always{};
|
return std::suspend_always{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool MainJob>
|
|
||||||
inline constexpr void Event::await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h)
|
|
||||||
{
|
|
||||||
h.promise().enqueue(*this);
|
|
||||||
flag->lock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
|
|||||||
@@ -25,3 +25,8 @@ void View::setFocused()
|
|||||||
{
|
{
|
||||||
owner->setFocused(this);
|
owner->setFocused(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& View::getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public:
|
|||||||
void applyArea(URect area);
|
void applyArea(URect area);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
|
|
||||||
|
const std::string& getName();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
Gfx::PViewport viewport;
|
Gfx::PViewport viewport;
|
||||||
|
|||||||
@@ -16,9 +16,7 @@ Window::~Window()
|
|||||||
|
|
||||||
void Window::addView(PView view)
|
void Window::addView(PView view)
|
||||||
{
|
{
|
||||||
WindowView* windowView = new WindowView();
|
WindowView* windowView = new WindowView(view);
|
||||||
windowView->view = view;
|
|
||||||
windowView->updateFinished = Event(view->name);
|
|
||||||
//windowView->worker = std::thread(&Window::viewWorker, this, windowView);
|
//windowView->worker = std::thread(&Window::viewWorker, this, windowView);
|
||||||
views.add(windowView);
|
views.add(windowView);
|
||||||
viewWorker(views.size() - 1);
|
viewWorker(views.size() - 1);
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ struct WindowView
|
|||||||
PView view;
|
PView view;
|
||||||
Event updateFinished;
|
Event updateFinished;
|
||||||
std::mutex workerMutex;
|
std::mutex workerMutex;
|
||||||
|
WindowView(PView view)
|
||||||
|
: view(view)
|
||||||
|
, updateFinished(view->getName())
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
DEFINE_REF(WindowView)
|
DEFINE_REF(WindowView)
|
||||||
DECLARE_REF(WindowManager)
|
DECLARE_REF(WindowManager)
|
||||||
|
|||||||
+78
-70
@@ -1,112 +1,120 @@
|
|||||||
#include "EngineTest.h"
|
#include "EngineTest.h"
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
|
#include "ThreadPool.h"
|
||||||
#define BOOST_TEST_MODULE SeeleEngine
|
#define BOOST_TEST_MODULE SeeleEngine
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
//#include <vld.h>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
|
Seele::GlobalFixture::~GlobalFixture()
|
||||||
|
{
|
||||||
|
getGlobalThreadPool().waitIdle();
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_TEST_GLOBAL_FIXTURE(GlobalFixture);
|
BOOST_TEST_GLOBAL_FIXTURE(GlobalFixture);
|
||||||
BOOST_AUTO_TEST_SUITE(RefPtr)
|
BOOST_AUTO_TEST_SUITE(RefPtr)
|
||||||
|
|
||||||
struct TestStruct
|
struct TestStruct
|
||||||
{
|
{
|
||||||
TestStruct()
|
TestStruct()
|
||||||
: data(10)
|
: data(10)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~TestStruct()
|
virtual ~TestStruct()
|
||||||
{
|
{
|
||||||
data = 15;
|
data = 15;
|
||||||
}
|
}
|
||||||
uint32 data;
|
uint32 data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeclStruct;
|
struct DeclStruct;
|
||||||
BOOST_AUTO_TEST_CASE(basic_refcount)
|
BOOST_AUTO_TEST_CASE(basic_refcount)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Seele::RefPtr<TestStruct> ptr = new TestStruct();
|
Seele::RefPtr<TestStruct> ptr = new TestStruct();
|
||||||
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
||||||
{
|
{
|
||||||
Seele::RefPtr<TestStruct> secondPtr = ptr;
|
Seele::RefPtr<TestStruct> secondPtr = ptr;
|
||||||
BOOST_REQUIRE_EQUAL(secondPtr->data, 10);
|
BOOST_REQUIRE_EQUAL(secondPtr->data, 10);
|
||||||
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
||||||
}
|
}
|
||||||
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
BOOST_REQUIRE_EQUAL(ptr->data, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct DeclStruct
|
struct DeclStruct
|
||||||
{
|
{
|
||||||
~DeclStruct()
|
~DeclStruct()
|
||||||
{
|
{
|
||||||
data = 10;
|
data = 10;
|
||||||
}
|
}
|
||||||
uint32 data = 20;
|
uint32 data = 20;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DerivedStruct : public TestStruct
|
struct DerivedStruct : public TestStruct
|
||||||
{
|
{
|
||||||
DerivedStruct()
|
DerivedStruct()
|
||||||
:data2(20)
|
:data2(20)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
~DerivedStruct()
|
~DerivedStruct()
|
||||||
{
|
{
|
||||||
data2 = 30;
|
data2 = 30;
|
||||||
}
|
}
|
||||||
uint32 data2;
|
uint32 data2;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inheritance_cast)
|
BOOST_AUTO_TEST_CASE(inheritance_cast)
|
||||||
{
|
{
|
||||||
Seele::RefPtr<DerivedStruct> backCast;
|
Seele::RefPtr<DerivedStruct> backCast;
|
||||||
{
|
{
|
||||||
Seele::RefPtr<DerivedStruct> derived = new DerivedStruct();
|
Seele::RefPtr<DerivedStruct> derived = new DerivedStruct();
|
||||||
Seele::RefPtr<TestStruct> base = derived;
|
Seele::RefPtr<TestStruct> base = derived;
|
||||||
BOOST_REQUIRE_EQUAL(base->data, 10);
|
BOOST_REQUIRE_EQUAL(base->data, 10);
|
||||||
backCast = base.cast<DerivedStruct>();
|
backCast = base.cast<DerivedStruct>();
|
||||||
BOOST_REQUIRE_EQUAL(backCast->data, 10);
|
BOOST_REQUIRE_EQUAL(backCast->data, 10);
|
||||||
BOOST_REQUIRE_EQUAL(backCast->data2, 20);
|
BOOST_REQUIRE_EQUAL(backCast->data2, 20);
|
||||||
}
|
}
|
||||||
BOOST_REQUIRE_EQUAL(backCast->data, 10);
|
BOOST_REQUIRE_EQUAL(backCast->data, 10);
|
||||||
BOOST_REQUIRE_EQUAL(backCast->data2, 20);
|
BOOST_REQUIRE_EQUAL(backCast->data2, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(unique_ptr)
|
BOOST_AUTO_TEST_CASE(unique_ptr)
|
||||||
{
|
{
|
||||||
Seele::UniquePtr<TestStruct> uptr = new TestStruct();
|
Seele::UniquePtr<TestStruct> uptr = new TestStruct();
|
||||||
Seele::UniquePtr<TestStruct> uptr2 = std::move(uptr);
|
Seele::UniquePtr<TestStruct> uptr2 = std::move(uptr);
|
||||||
BOOST_REQUIRE_EQUAL(uptr2->data, 10);
|
BOOST_REQUIRE_EQUAL(uptr2->data, 10);
|
||||||
BOOST_REQUIRE_EQUAL(uptr.isValid(), false);
|
BOOST_REQUIRE_EQUAL(uptr.isValid(), false);
|
||||||
}
|
}
|
||||||
struct ThisReference
|
struct ThisReference
|
||||||
{
|
{
|
||||||
ThisReference()
|
ThisReference()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~ThisReference()
|
~ThisReference()
|
||||||
{
|
{
|
||||||
data = 12;
|
data = 12;
|
||||||
}
|
}
|
||||||
Seele::RefPtr<ThisReference> getRef()
|
Seele::RefPtr<ThisReference> getRef()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
uint32 data = 1;
|
uint32 data = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(this_reference)
|
BOOST_AUTO_TEST_CASE(this_reference)
|
||||||
{
|
{
|
||||||
Seele::RefPtr<ThisReference> ptr2;
|
Seele::RefPtr<ThisReference> ptr2;
|
||||||
{
|
{
|
||||||
Seele::RefPtr<ThisReference> ptr = new ThisReference();
|
Seele::RefPtr<ThisReference> ptr = new ThisReference();
|
||||||
BOOST_REQUIRE_EQUAL(ptr->data, 1);
|
BOOST_REQUIRE_EQUAL(ptr->data, 1);
|
||||||
ptr2 = ptr->getRef();
|
ptr2 = ptr->getRef();
|
||||||
BOOST_REQUIRE_EQUAL(ptr2->data, 1);
|
BOOST_REQUIRE_EQUAL(ptr2->data, 1);
|
||||||
ptr2->data = 5;
|
ptr2->data = 5;
|
||||||
BOOST_REQUIRE_EQUAL(ptr->data, 5);
|
BOOST_REQUIRE_EQUAL(ptr->data, 5);
|
||||||
}
|
}
|
||||||
BOOST_REQUIRE_EQUAL(ptr2->data, 5);
|
BOOST_REQUIRE_EQUAL(ptr2->data, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vld.h>
|
#include <vld.h>
|
||||||
#include "ThreadPool.h"
|
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
@@ -10,10 +9,7 @@ namespace Seele
|
|||||||
{
|
{
|
||||||
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||||
}
|
}
|
||||||
~GlobalFixture()
|
~GlobalFixture();
|
||||||
{
|
|
||||||
getGlobalThreadPool().waitIdle();
|
|
||||||
}
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
//Fibers::JobQueue::initJobQueues();
|
//Fibers::JobQueue::initJobQueues();
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ Job basicAwaitBase()
|
|||||||
basicAwaitState = 25;
|
basicAwaitState = 25;
|
||||||
co_await basicAwaitThird();
|
co_await basicAwaitThird();
|
||||||
BOOST_REQUIRE_EQUAL(basicAwaitState, 30);
|
BOOST_REQUIRE_EQUAL(basicAwaitState, 30);
|
||||||
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(basic_coawait)
|
BOOST_AUTO_TEST_CASE(basic_coawait)
|
||||||
@@ -211,7 +212,7 @@ Job launchStressTest()
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(stress_test)
|
BOOST_AUTO_TEST_CASE(stress_test)
|
||||||
{
|
{
|
||||||
//launchStressTest();
|
launchStressTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
Reference in New Issue
Block a user