From 683b09144d45a0af9b1f6495d609cae8528d8298 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 14 Oct 2017 18:04:16 +0200 Subject: [PATCH] Core: Replace StackAllocation by StackArray This will cleanup alloca usage a little bit --- include/Nazara/Core/MemoryHelper.hpp | 70 +++++++-- include/Nazara/Core/MemoryHelper.inl | 182 +++++++++++++++++++++--- src/Nazara/Network/Posix/SocketImpl.cpp | 10 +- src/Nazara/Network/Win32/SocketImpl.cpp | 10 +- src/Nazara/Physics2D/PhysWorld2D.cpp | 7 +- src/Nazara/Renderer/Renderer.cpp | 8 +- 6 files changed, 236 insertions(+), 51 deletions(-) diff --git a/include/Nazara/Core/MemoryHelper.hpp b/include/Nazara/Core/MemoryHelper.hpp index dc1bcc475..7450f95f5 100644 --- a/include/Nazara/Core/MemoryHelper.hpp +++ b/include/Nazara/Core/MemoryHelper.hpp @@ -23,12 +23,15 @@ #endif #ifdef NAZARA_ALLOCA_SUPPORT - #define NazaraStackAllocation(size) Nz::StackAllocation(NAZARA_ALLOCA(size)) + #define NazaraStackAllocation(T, size) Nz::StackArray(static_cast(NAZARA_ALLOCA((size) * sizeof(T))), size) + #define NazaraStackAllocationNoInit(T, size) Nz::StackArray(static_cast(NAZARA_ALLOCA((size) * sizeof(T))), size, Nz::NoInitTag()) #else - #define NazaraStackAllocation(size) Nz::StackAllocation(Nz::OperatorNew(size)) + #define NazaraStackAllocation(T, size) Nz::StackArray(static_cast(Nz::OperatorNew((size) * sizeof(T))), size) + #define NazaraStackAllocationNoInit(T, size) Nz::StackArray(static_cast(Nz::OperatorNew((size) * sizeof(T))), size, Nz::NoInitTag()) #endif #include +#include namespace Nz { @@ -41,19 +44,70 @@ namespace Nz template void PlacementDestroy(T* ptr); - class StackAllocation + struct NoInitTag {}; + + template + class StackArray { public: - explicit StackAllocation(void* stackMemory); - ~StackAllocation(); + using value_type = T; + using const_iterator = const value_type*; + using const_pointer = const value_type*; + using const_reference = const value_type&; + using const_reverse_iterator = std::reverse_iterator; + using difference_type = std::ptrdiff_t; + using iterator = value_type*; + using pointer = value_type*; + using reference = value_type&; + using reverse_iterator = std::reverse_iterator; + using size_type = std::size_t; - void* GetPtr(); + StackArray(T* stackMemory, std::size_t size); + StackArray(T* stackMemory, std::size_t size, NoInitTag); + ~StackArray(); - operator void*(); + reference back(); + const_reference back() const; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + const_iterator crbegin() const noexcept; + const_iterator crend() const noexcept; + + T* data() noexcept; + const T* data() const noexcept; + + bool empty() const noexcept; + + iterator end() noexcept; + const_iterator end() const noexcept; + + void fill(const T& value); + + reference front() noexcept; + const_reference front() const noexcept; + + size_type max_size() const noexcept; + + reverse_iterator rbegin() noexcept; + const_reverse_iterator rbegin() const noexcept; + + reverse_iterator rend() noexcept; + const_reverse_iterator rend() const noexcept; + + size_type size() const noexcept; + + reference operator[](size_type pos); + const_reference operator[](size_type pos) const; private: - void* m_ptr; + std::size_t m_size; + T* m_ptr; }; + } #include diff --git a/include/Nazara/Core/MemoryHelper.inl b/include/Nazara/Core/MemoryHelper.inl index dcee8ca4e..748bf5af2 100644 --- a/include/Nazara/Core/MemoryHelper.inl +++ b/include/Nazara/Core/MemoryHelper.inl @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include #include @@ -77,48 +79,184 @@ namespace Nz /*! * \ingroup core - * \class Nz::StackAllocation - * \brief Core class that represents a stack allocation + * \class Nz::StackArray + * \brief Core class that represents a stack-allocated (if alloca is present) array */ + template + StackArray::StackArray(T* stackMemory, std::size_t size) : + m_size(size), + m_ptr(stackMemory) + { + for (std::size_t i = 0; i < m_size; ++i) + PlacementNew(&m_ptr[i]); + } - /*! - * \brief Constructs a StackAllocation object with a pointer to a memory allocated with NAZARA_ALLOCA or OperatorNew is alloca is not supported - * - * \param ptr Pointer to raw memory - */ - inline StackAllocation::StackAllocation(void* stackMemory) : + template + StackArray::StackArray(T* stackMemory, std::size_t size, NoInitTag) : + m_size(size), m_ptr(stackMemory) { } - /*! - * \brief Destructs the object and release memory if necessary - */ - inline StackAllocation::~StackAllocation() + template + StackArray::~StackArray() { + for (std::size_t i = 0; i < m_size; ++i) + m_ptr[i].~T(); + #ifndef NAZARA_ALLOCA_SUPPORT OperatorDelete(m_ptr); #endif } - /*! - * \brief Access the internal pointer - * \return internal memory pointer - */ - inline void* StackAllocation::GetPtr() + template + typename StackArray::reference StackArray::back() + { + assert(m_size != 0); + return m_ptr[m_size - 1]; + } + + template + typename StackArray::const_reference StackArray::back() const + { + assert(m_size != 0); + return m_ptr[m_size - 1]; + } + + template + typename StackArray::iterator StackArray::begin() noexcept + { + return &m_ptr[0]; + } + + template + typename StackArray::const_iterator StackArray::begin() const noexcept + { + return &m_ptr[0]; + } + + template + typename StackArray::const_iterator StackArray::cbegin() const noexcept + { + return &m_ptr[0]; + } + + template + typename StackArray::const_iterator StackArray::cend() const noexcept + { + return &m_ptr[m_size]; + } + + template + typename StackArray::const_iterator StackArray::crbegin() const noexcept + { + return &m_ptr[m_size]; + } + + template + typename StackArray::const_iterator StackArray::crend() const noexcept + { + return &m_ptr[0]; + } + + template + T* StackArray::data() noexcept { return m_ptr; } - /*! - * \brief Access the internal pointer - * \return internal memory pointer - */ - inline StackAllocation::operator void*() + template + const T* StackArray::data() const noexcept { return m_ptr; } + + template + bool StackArray::empty() const noexcept + { + return m_size == 0; + } + + template + typename StackArray::iterator StackArray::end() noexcept + { + return &m_ptr[m_size]; + } + + template + typename StackArray::const_iterator StackArray::end() const noexcept + { + return &m_ptr[m_size]; + } + + template + void StackArray::fill(const T& value) + { + std::fill(begin(), end(), value); + } + + template + typename StackArray::reference StackArray::front() noexcept + { + return m_ptr[0]; + } + + template + typename StackArray::const_reference StackArray::front() const noexcept + { + return m_ptr[0]; + } + + template + typename StackArray::size_type StackArray::max_size() const noexcept + { + return size(); + } + + template + typename StackArray::reverse_iterator StackArray::rbegin() noexcept + { + return m_ptr[m_size]; + } + + template + typename StackArray::const_reverse_iterator StackArray::rbegin() const noexcept + { + return m_ptr[m_size]; + } + + template + typename StackArray::reverse_iterator StackArray::rend() noexcept + { + return m_ptr[0]; + } + + template + typename StackArray::const_reverse_iterator StackArray::rend() const noexcept + { + return m_ptr[0]; + } + + template + typename StackArray::size_type StackArray::size() const noexcept + { + return m_size; + } + + template + typename StackArray::reference StackArray::operator[](size_type pos) + { + assert(pos < m_size); + return m_ptr[pos]; + } + + template + typename StackArray::const_reference StackArray::operator[](size_type pos) const + { + assert(pos < m_size); + return m_ptr[pos]; + } } #include diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index 3a2c8e81f..9d1f7bd0c 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -566,8 +566,7 @@ namespace Nz NazaraAssert(handle != InvalidHandle, "Invalid handle"); NazaraAssert(buffers && bufferCount > 0, "Invalid buffers"); - StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(iovec)); - struct iovec* sysBuffers = static_cast(memory.GetPtr()); + StackArray sysBuffers = NazaraStackAllocation(iovec, bufferCount); for (std::size_t i = 0; i < bufferCount; ++i) { sysBuffers[i].iov_base = buffers[i].data; @@ -577,7 +576,7 @@ namespace Nz struct msghdr msgHdr; std::memset(&msgHdr, 0, sizeof(msgHdr)); - msgHdr.msg_iov = sysBuffers; + msgHdr.msg_iov = sysBuffers.data(); msgHdr.msg_iovlen = static_cast(bufferCount); IpAddressImpl::SockAddrBuffer nameBuffer; @@ -689,8 +688,7 @@ namespace Nz NazaraAssert(handle != InvalidHandle, "Invalid handle"); NazaraAssert(buffers && bufferCount > 0, "Invalid buffers"); - StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(iovec)); - struct iovec* sysBuffers = static_cast(memory.GetPtr()); + StackArray sysBuffers = NazaraStackAllocation(iovec, bufferCount); for (std::size_t i = 0; i < bufferCount; ++i) { sysBuffers[i].iov_base = buffers[i].data; @@ -703,7 +701,7 @@ namespace Nz IpAddressImpl::SockAddrBuffer nameBuffer; msgHdr.msg_namelen = IpAddressImpl::ToSockAddr(to, nameBuffer.data()); msgHdr.msg_name = nameBuffer.data(); - msgHdr.msg_iov = sysBuffers; + msgHdr.msg_iov = sysBuffers.data(); msgHdr.msg_iovlen = static_cast(bufferCount); int byteSent = sendmsg(handle, &msgHdr, MSG_NOSIGNAL); diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index 6c82f0505..fbc8beec3 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -596,8 +596,7 @@ namespace Nz IpAddress senderIp; - StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(WSABUF)); - WSABUF* winBuffers = static_cast(memory.GetPtr()); + StackArray winBuffers = NazaraStackAllocation(WSABUF, bufferCount); for (std::size_t i = 0; i < bufferCount; ++i) { winBuffers[i].buf = static_cast(buffers[i].data); @@ -606,7 +605,7 @@ namespace Nz DWORD flags = 0; DWORD byteRead; - if (WSARecvFrom(handle, winBuffers, static_cast(bufferCount), &byteRead, &flags, reinterpret_cast(nameBuffer.data()), &bufferLength, nullptr, nullptr) == SOCKET_ERROR) + if (WSARecvFrom(handle, winBuffers.data(), static_cast(bufferCount), &byteRead, &flags, reinterpret_cast(nameBuffer.data()), &bufferLength, nullptr, nullptr) == SOCKET_ERROR) { int errorCode = WSAGetLastError(); switch (errorCode) @@ -696,8 +695,7 @@ namespace Nz IpAddressImpl::SockAddrBuffer nameBuffer; int bufferLength = IpAddressImpl::ToSockAddr(to, nameBuffer.data()); - StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(WSABUF)); - WSABUF* winBuffers = static_cast(memory.GetPtr()); + StackArray winBuffers = NazaraStackAllocation(WSABUF, bufferCount); for (std::size_t i = 0; i < bufferCount; ++i) { winBuffers[i].buf = static_cast(buffers[i].data); @@ -705,7 +703,7 @@ namespace Nz } DWORD byteSent; - if (WSASendTo(handle, winBuffers, static_cast(bufferCount), &byteSent, 0, reinterpret_cast(nameBuffer.data()), bufferLength, nullptr, nullptr) == SOCKET_ERROR) + if (WSASendTo(handle, winBuffers.data(), static_cast(bufferCount), &byteSent, 0, reinterpret_cast(nameBuffer.data()), bufferLength, nullptr, nullptr) == SOCKET_ERROR) { int errorCode = WSAGetLastError(); switch (errorCode) diff --git a/src/Nazara/Physics2D/PhysWorld2D.cpp b/src/Nazara/Physics2D/PhysWorld2D.cpp index a1ab49f71..b880de113 100644 --- a/src/Nazara/Physics2D/PhysWorld2D.cpp +++ b/src/Nazara/Physics2D/PhysWorld2D.cpp @@ -44,12 +44,11 @@ namespace Nz { //TODO: constexpr if to prevent copy/cast if sizeof(cpVect) == sizeof(Vector2f) - StackAllocation stackAlloc = NazaraStackAllocation(vertexCount * sizeof(Vector2f)); - Vector2f* vec = static_cast(stackAlloc.GetPtr()); + StackArray vertices = NazaraStackAllocation(Vector2f, vertexCount); for (int i = 0; i < vertexCount; ++i) - vec[i].Set(float(vertices[i].x), float(vertices[i].y)); + vertices[i].Set(float(vertices[i].x), float(vertices[i].y)); - drawOptions->polygonCallback(vec, vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); + drawOptions->polygonCallback(vertices.data(), vertexCount, float(radius), CpDebugColorToColor(outlineColor), CpDebugColorToColor(fillColor), drawOptions->userdata); } }; diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 5461ad510..0acede6d4 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -1762,9 +1762,7 @@ namespace Nz glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); maxLength++; - StackAllocation stackAlloc = NazaraStackAllocation((maxLength + 1) * sizeof(GLchar)); - GLchar* nameBuffer = static_cast(stackAlloc.GetPtr()); - + StackAllocation nameBuffer = NazaraStackAllocation(GLchar, maxLength + 1); for (GLint i = 0; i < count; i++) { GLint size; @@ -1772,9 +1770,9 @@ namespace Nz glGetActiveUniform(program, i, maxLength, nullptr, &size, &type, nameBuffer); - dump << "Uniform #" << i << ": " << nameBuffer << "(Type: 0x" << String::Number(type, 16); + dump << "Uniform #" << i << ": " << nameBuffer.data() << "(Type: 0x" << String::Number(type, 16); - GLint location = glGetUniformLocation(program, nameBuffer); + GLint location = glGetUniformLocation(program, nameBuffer.data()); switch (type) { case GL_FLOAT: