diff --git a/Source/Core/Common/Buffer.h b/Source/Core/Common/Buffer.h new file mode 100644 index 0000000000..216d0c5fe5 --- /dev/null +++ b/Source/Core/Common/Buffer.h @@ -0,0 +1,88 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +// UniqueBuffer and SharedBuffer are a lighter alternative to std::vector. +// The main benefit is that elements are not value-initialized like in vector. +// That can be quite a bit of unecessary overhead when allocating a large buffer. + +namespace Common +{ + +namespace detail +{ +template +class BufferBase final +{ +public: + using PtrType = decltype(MakeFunc(1)); + + using value_type = PtrType::element_type; + using size_type = std::size_t; + + BufferBase() {} + BufferBase(PtrType ptr, size_type new_size) : m_ptr{std::move(ptr)}, m_size{new_size} {} + explicit BufferBase(size_type new_size) : BufferBase{MakeFunc(new_size), new_size} {} + + BufferBase(const BufferBase&) = default; + BufferBase& operator=(const BufferBase&) = default; + + BufferBase(BufferBase&& other) { swap(other); } + BufferBase& operator=(BufferBase&& other) + { + reset(); + swap(other); + return *this; + } + + void assign(PtrType ptr, size_type new_size) { BufferBase{std::move(ptr), new_size}.swap(*this); } + void reset(size_type new_size = 0) { BufferBase{new_size}.swap(*this); } + + std::pair extract() + { + std::pair result = {std::move(m_ptr), m_size}; + reset(); + return result; + } + + void swap(BufferBase& other) + { + std::swap(m_ptr, other.m_ptr); + std::swap(m_size, other.m_size); + } + + size_type size() const { return m_size; } + bool empty() const { return m_size == 0; } + + value_type* get() { return m_ptr.get(); } + const value_type* get() const { return m_ptr.get(); } + + value_type* data() { return m_ptr.get(); } + const value_type* data() const { return m_ptr.get(); } + + value_type* begin() { return m_ptr.get(); } + value_type* end() { return m_ptr.get() + m_size; } + + const value_type* begin() const { return m_ptr.get(); } + const value_type* end() const { return m_ptr.get() + m_size; } + + value_type& operator[](size_type index) { return m_ptr[index]; } + const value_type& operator[](size_type index) const { return m_ptr[index]; } + +private: + PtrType m_ptr; + size_type m_size = 0; +}; +} // namespace detail + +template +using UniqueBuffer = detail::BufferBase>; + +// TODO: std::make_shared_for_overwrite requires GCC 12.1+ +// template +// using SharedBuffer = detail::BufferBase>; + +} // namespace Common diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index c368cde1d6..ac2ef8d10f 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(common BitSet.h BitUtils.h BlockingLoop.h + Buffer.h ChunkFile.h CodeBlock.h ColorUtil.cpp diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 388367afd1..86942be03a 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -26,6 +26,7 @@ +