Common: Remove SafeArray

And replace with std::vector.
This commit is contained in:
Stenzek 2023-06-29 22:43:42 +10:00 committed by Connor McLaughlin
parent 732aa96656
commit adca796d94
18 changed files with 81 additions and 355 deletions

View File

@ -11,7 +11,6 @@ add_library(common)
target_sources(common PRIVATE
AlignedMalloc.cpp
Assertions.cpp
SafeArray.inl
Console.cpp
CrashHandler.cpp
DynamicLibrary.cpp
@ -90,7 +89,6 @@ target_sources(common PRIVATE
ReadbackSpinManager.h
RedtapeWilCom.h
RedtapeWindows.h
SafeArray.h
ScopedGuard.h
SettingsInterface.h
SettingsWrapper.h

View File

@ -1,99 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/Pcsx2Defs.h"
// Microsoft Windows only macro, useful for freeing out COM objects:
#define safe_release(ptr) \
((void)((((ptr) != NULL) && ((ptr)->Release(), !!0)), (ptr) = NULL))
// --------------------------------------------------------------------------------------
// SafeArray
// --------------------------------------------------------------------------------------
// Handy little class for allocating a resizable memory block, complete with exception
// error handling and automatic cleanup. A lightweight alternative to std::vector.
//
template <typename T>
class SafeArray
{
DeclareNoncopyableObject(SafeArray);
public:
static const int DefaultChunkSize = 0x1000 * sizeof(T);
public:
std::string Name; // user-assigned block name
int ChunkSize;
protected:
T* m_ptr;
int m_size; // size of the allocation of memory
protected:
SafeArray(std::string name, T* allocated_mem, int initSize);
virtual T* _virtual_realloc(int newsize);
// A safe array index fetcher. Asserts if the index is out of bounds (dev and debug
// builds only -- no bounds checking is done in release builds).
T* _getPtr(uint i) const;
public:
virtual ~SafeArray();
explicit SafeArray(std::string name = "Unnamed");
explicit SafeArray(int initialSize, std::string name = "Unnamed");
void Dispose();
void ExactAlloc(int newsize);
void MakeRoomFor(int newsize)
{
if (newsize > m_size)
ExactAlloc(newsize);
}
bool IsDisposed() const { return (m_ptr == NULL); }
// Returns the size of the memory allocation, as according to the array type.
int GetLength() const { return m_size; }
// Returns the size of the memory allocation in bytes.
int GetSizeInBytes() const { return m_size * sizeof(T); }
// Extends the containment area of the array. Extensions are performed
// in chunks.
void GrowBy(int items)
{
MakeRoomFor(m_size + ChunkSize + items + 1);
}
// Gets a pointer to the requested allocation index.
// DevBuilds : Generates assertion if the index is invalid.
T* GetPtr(uint idx = 0) { return _getPtr(idx); }
const T* GetPtr(uint idx = 0) const { return _getPtr(idx); }
// Gets a pointer to the element directly after the last element in the array.
// This is equivalent to doing GetPtr(GetLength()), except that this call *avoids*
// the out-of-bounds assertion check that typically occurs when you do that. :)
T* GetPtrEnd() { return &m_ptr[m_size]; }
const T* GetPtrEnd() const { return &m_ptr[m_size]; }
// Gets an element of this memory allocation much as if it were an array.
// DevBuilds : Generates assertion if the index is invalid.
T& operator[](int idx) { return *_getPtr((uint)idx); }
const T& operator[](int idx) const { return *_getPtr((uint)idx); }
virtual SafeArray<T>* Clone() const;
};

View File

@ -1,121 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/Assertions.h"
#include "common/SafeArray.h"
// Internal constructor for use by derived classes. This allows a derived class to
// use its own memory allocation (with an aligned memory, for example).
// Throws:
// Exception::OutOfMemory if the allocated_mem pointer is NULL.
template <typename T>
SafeArray<T>::SafeArray(std::string name, T* allocated_mem, int initSize)
: Name(std::move(name))
{
ChunkSize = DefaultChunkSize;
m_ptr = allocated_mem;
m_size = initSize;
if (m_ptr == NULL)
pxFailRel("SafeArray memory assignment failed");
}
template <typename T>
T* SafeArray<T>::_virtual_realloc(int newsize)
{
T* retval = (T*)((m_ptr == NULL) ?
malloc(newsize * sizeof(T)) :
realloc(m_ptr, newsize * sizeof(T)));
if (IsDebugBuild && (retval != NULL))
{
// Zero everything out to 0xbaadf00d, so that its obviously uncleared
// to a debuggee
u32* fill = (u32*)&retval[m_size];
const u32* end = (u32*)((((uptr)&retval[newsize - 1]) - 3) & ~0x3);
for (; fill < end; ++fill)
*fill = 0xbaadf00d;
}
return retval;
}
template <typename T>
SafeArray<T>::~SafeArray()
{
safe_free(m_ptr);
}
template <typename T>
SafeArray<T>::SafeArray(std::string name)
: Name(std::move(name))
{
ChunkSize = DefaultChunkSize;
m_ptr = NULL;
m_size = 0;
}
template <typename T>
SafeArray<T>::SafeArray(int initialSize, std::string name)
: Name(std::move(name))
{
ChunkSize = DefaultChunkSize;
m_ptr = (initialSize == 0) ? NULL : (T*)malloc(initialSize * sizeof(T));
m_size = initialSize;
if ((initialSize != 0) && (m_ptr == NULL))
pxFailRel("SafeArray memory allocation failed");
}
// Clears the contents of the array to zero, and frees all memory allocations.
template <typename T>
void SafeArray<T>::Dispose()
{
m_size = 0;
safe_free(m_ptr);
}
template <typename T>
T* SafeArray<T>::_getPtr(uint i) const
{
pxAssumeDev(i < static_cast<uint>(m_size), "Array index in bounds");
return &m_ptr[i];
}
// reallocates the array to the explicit size. Can be used to shrink or grow an
// array, and bypasses the internal threshold growth indicators.
template <typename T>
void SafeArray<T>::ExactAlloc(int newsize)
{
if (newsize == m_size)
return;
m_ptr = _virtual_realloc(newsize);
if (m_ptr == NULL)
pxFailRel("SafeArray exact alloc failed");
m_size = newsize;
}
template <typename T>
SafeArray<T>* SafeArray<T>::Clone() const
{
SafeArray<T>* retval = new SafeArray<T>(m_size);
memcpy(retval->GetPtr(), m_ptr, sizeof(T) * m_size);
return retval;
}

View File

@ -42,6 +42,7 @@
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/SysForwardDefs.h"
#include "pcsx2/VMManager.h"
#include "common/Assertions.h"

View File

@ -30,6 +30,7 @@
#include "MTGS.h"
#include "VMManager.h"
#include "svnrev.h"
#include "SysForwardDefs.h"
#include "vtlb.h"
#include "common/Assertions.h"

View File

@ -22,6 +22,8 @@
#include "IopHw.h"
#include "IopDma.h"
#include "common/Threading.h"
//THIS ALL IS FOR THE CDROM REGISTERS HANDLING
enum cdrom_registers

View File

@ -34,6 +34,7 @@
#include "common/FileSystem.h"
#include "common/StringUtil.h"
#include "common/Threading.h"
#include "common/Timer.h"
#include <atomic>

View File

@ -38,6 +38,7 @@
#include "ps2/BiosTools.h"
#include "Patch.h"
#include "svnrev.h"
#include "SysForwardDefs.h"
#include "common/FileSystem.h"
#include "common/Console.h"
@ -46,6 +47,7 @@
#include "common/SettingsInterface.h"
#include "common/SettingsWrapper.h"
#include "common/StringUtil.h"
#include "common/Threading.h"
#include "common/Timer.h"
#include "imgui.h"

View File

@ -17,6 +17,8 @@
#include "GS.h"
#include "common/Threading.h"
#include <functional>
/////////////////////////////////////////////////////////////////////////////

View File

@ -15,7 +15,6 @@
#include "PrecompiledHeader.h"
#include "common/FileSystem.h"
#include "common/SafeArray.inl"
#include "common/Path.h"
#include "common/StringUtil.h"
@ -171,7 +170,7 @@ class FileMemoryCard
protected:
std::FILE* m_file[8] = {};
std::string m_filenames[8] = {};
SafeArray<u8> m_currentdata;
std::vector<u8> m_currentdata;
u64 m_chksum[8] = {};
bool m_ispsx[8] = {};
u32 m_chkaddr = 0;
@ -490,7 +489,8 @@ s32 FileMemoryCard::Save(uint slot, const u8* src, u32 adr, int size)
if (m_ispsx[slot])
{
m_currentdata.MakeRoomFor(size);
if (static_cast<int>(m_currentdata.size()) < size)
m_currentdata.resize(size);
for (int i = 0; i < size; i++)
m_currentdata[i] = src[i];
}
@ -498,9 +498,10 @@ s32 FileMemoryCard::Save(uint slot, const u8* src, u32 adr, int size)
{
if (!Seek(mcfp, adr))
return 0;
m_currentdata.MakeRoomFor(size);
if (static_cast<int>(m_currentdata.size()) < size)
m_currentdata.resize(size);
const size_t read_result = std::fread(m_currentdata.GetPtr(), size, 1, mcfp);
const size_t read_result = std::fread(m_currentdata.data(), size, 1, mcfp);
if (read_result == 0)
Host::ReportFormattedErrorAsync("Memory Card", "Error reading memcard.\n");
@ -527,7 +528,7 @@ s32 FileMemoryCard::Save(uint slot, const u8* src, u32 adr, int size)
if (!Seek(mcfp, adr))
return 0;
if (std::fwrite(m_currentdata.GetPtr(), size, 1, mcfp) == 1)
if (std::fwrite(m_currentdata.data(), size, 1, mcfp) == 1)
{
static auto last = std::chrono::time_point<std::chrono::system_clock>();

View File

@ -14,7 +14,6 @@
*/
#include "PrecompiledHeader.h"
#include "common/SafeArray.inl"
#include "common/Path.h"
#include "MemoryCardFile.h"

View File

@ -39,6 +39,7 @@
#include "Elfheader.h"
#include "pcsx2/VMManager.h"
#include "svnrev.h"
#include "SysForwardDefs.h"
#include "PINE.h"
PINEServer::PINEServer() {}

View File

@ -22,6 +22,7 @@
#include "common/FileSystem.h"
#include "DebugTools/Debug.h"
#include "MemoryTypes.h"
#include "SysForwardDefs.h"
#include <fmt/format.h>

View File

@ -42,7 +42,6 @@
#include "common/Error.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "common/SafeArray.inl"
#include "common/ScopedGuard.h"
#include "common/StringUtil.h"
#include "common/ZipHelpers.h"
@ -95,40 +94,28 @@ static void PostLoadPrep()
// --------------------------------------------------------------------------------------
// SaveStateBase (implementations)
// --------------------------------------------------------------------------------------
SaveStateBase::SaveStateBase( SafeArray<u8>& memblock )
SaveStateBase::SaveStateBase(VmStateBuffer& memblock)
: m_memory(memblock)
, m_version(g_SaveVersion)
{
Init( &memblock );
}
SaveStateBase::SaveStateBase( SafeArray<u8>* memblock )
void SaveStateBase::PrepBlock(int size)
{
Init( memblock );
}
void SaveStateBase::Init( SafeArray<u8>* memblock )
{
m_memory = memblock;
m_version = g_SaveVersion;
m_idx = 0;
m_error = false;
}
void SaveStateBase::PrepBlock( int size )
{
pxAssertDev( m_memory, "Savestate memory/buffer pointer is null!" );
if (m_error)
return;
const int end = m_idx+size;
const int end = m_idx + size;
if (IsSaving())
{
m_memory->MakeRoomFor(end);
if (static_cast<u32>(end) >= m_memory.size())
m_memory.resize(static_cast<u32>(end));
}
else
{
if (m_memory->GetSizeInBytes() < end)
if (m_memory.size() < static_cast<u32>(end))
{
Console.Error("(SaveStateBase) Buffer overflow in PrepBlock(), expected %d got %d", end, m_memory->GetSizeInBytes());
Console.Error("(SaveStateBase) Buffer overflow in PrepBlock(), expected %d got %zu", end, m_memory.size());
m_error = true;
}
}
@ -270,44 +257,29 @@ bool SaveStateBase::FreezeInternals()
// --------------------------------------------------------------------------------------
// uncompressed to/from memory state saves implementation
memSavingState::memSavingState( SafeArray<u8>& save_to )
: SaveStateBase( save_to )
{
}
memSavingState::memSavingState( SafeArray<u8>* save_to )
: SaveStateBase( save_to )
memSavingState::memSavingState(VmStateBuffer& save_to)
: SaveStateBase(save_to)
{
}
// Saving of state data
void memSavingState::FreezeMem( void* data, int size )
void memSavingState::FreezeMem(void* data, int size)
{
if (!size) return;
m_memory->MakeRoomFor( m_idx + size );
memcpy( m_memory->GetPtr(m_idx), data, size );
const int new_size = m_idx + size;
if (static_cast<u32>(new_size) > m_memory.size())
m_memory.resize(static_cast<u32>(new_size));
std::memcpy(&m_memory[m_idx], data, size);
m_idx += size;
}
void memSavingState::MakeRoomForData()
{
pxAssertDev( m_memory, "Savestate memory/buffer pointer is null!" );
m_memory->ChunkSize = ReallocThreshold;
m_memory->MakeRoomFor( m_idx + MemoryBaseAllocSize );
}
// --------------------------------------------------------------------------------------
// memLoadingState (implementations)
// --------------------------------------------------------------------------------------
memLoadingState::memLoadingState( const SafeArray<u8>& load_from )
: SaveStateBase( const_cast<SafeArray<u8>&>(load_from) )
{
}
memLoadingState::memLoadingState( const SafeArray<u8>* load_from )
: SaveStateBase( const_cast<SafeArray<u8>*>(load_from) )
memLoadingState::memLoadingState(const VmStateBuffer& load_from)
: SaveStateBase(const_cast<VmStateBuffer&>(load_from))
{
}
@ -320,14 +292,11 @@ void memLoadingState::FreezeMem( void* data, int size )
return;
}
const u8* const src = m_memory->GetPtr(m_idx);
const u8* const src = &m_memory[m_idx];
m_idx += size;
memcpy( data, src, size );
std::memcpy(data, src, size);
}
// Used to hold the current state backup (fullcopy of PS2 memory and subcomponents states).
//static VmStateBuffer state_buffer( L"Public Savestate Buffer" );
static const char* EntryFilename_StateVersion = "PCSX2 Savestate Version.id";
static const char* EntryFilename_Screenshot = "Screenshot.png";
static const char* EntryFilename_InternalStructures = "PCSX2 Internal Structures.dat";
@ -716,7 +685,8 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
std::unique_ptr<ArchiveEntryList> SaveState_DownloadState(Error* error)
{
std::unique_ptr<ArchiveEntryList> destlist = std::make_unique<ArchiveEntryList>(new VmStateBuffer("Zippable Savestate"));
std::unique_ptr<ArchiveEntryList> destlist = std::make_unique<ArchiveEntryList>();
destlist->GetBuffer().resize(1024 * 1024 * 64);
memSavingState saveme(destlist->GetBuffer());
ArchiveEntry internals(EntryFilename_InternalStructures);
@ -1073,8 +1043,8 @@ static bool LoadInternalStructuresState(zip_t* zf, s64 index)
if (!zff)
return false;
VmStateBuffer buffer(static_cast<int>(zst.size), "StateBuffer_UnzipFromDisk"); // start with an 8 meg buffer to avoid frequent reallocation.
if (zip_fread(zff.get(), buffer.GetPtr(), buffer.GetSizeInBytes()) != buffer.GetSizeInBytes())
std::vector<u8> buffer(zst.size);
if (zip_fread(zff.get(), buffer.data(), buffer.size()) != buffer.size())
return false;
memLoadingState state(buffer);

View File

@ -77,19 +77,21 @@ extern bool SaveState_UnzipFromDisk(const std::string& filename, Error* error);
// states), and memLoadingState, memSavingState (uncompressed memory states).
class SaveStateBase
{
public:
using VmStateBuffer = std::vector<u8>;
protected:
VmStateBuffer* m_memory;
VmStateBuffer& m_memory;
u32 m_version; // version of the savestate being loaded.
u32 m_version = 0; // version of the savestate being loaded.
int m_idx; // current read/write index of the allocation
int m_idx = 0; // current read/write index of the allocation
bool m_error; // error occurred while reading/writing
bool m_error = false; // error occurred while reading/writing
public:
SaveStateBase( VmStateBuffer& memblock );
SaveStateBase( VmStateBuffer* memblock );
virtual ~SaveStateBase() { }
SaveStateBase(VmStateBuffer& memblock);
virtual ~SaveStateBase() = default;
__fi bool HasError() const { return m_error; }
__fi bool IsOkay() const { return !m_error; }
@ -171,12 +173,7 @@ public:
u8* GetBlockPtr()
{
return m_memory->GetPtr(m_idx);
}
u8* GetPtrEnd() const
{
return m_memory->GetPtrEnd();
return &m_memory[m_idx];
}
void CommitBlock( int size )
@ -204,8 +201,6 @@ public:
bool gsFreeze();
protected:
void Init( VmStateBuffer* memblock );
bool vmFreeze();
bool mtvuFreeze();
bool rcntFreeze();
@ -241,7 +236,7 @@ protected:
// --------------------------------------------------------------------------------------
// ArchiveEntry
// --------------------------------------------------------------------------------------
class ArchiveEntry
class ArchiveEntry final
{
protected:
std::string m_filename;
@ -256,7 +251,7 @@ public:
m_datasize = 0;
}
virtual ~ArchiveEntry() = default;
~ArchiveEntry() = default;
ArchiveEntry& SetDataIndex(uptr idx)
{
@ -286,52 +281,41 @@ public:
}
};
typedef SafeArray< u8 > ArchiveDataBuffer;
// --------------------------------------------------------------------------------------
// ArchiveEntryList
// --------------------------------------------------------------------------------------
class ArchiveEntryList
class ArchiveEntryList final
{
public:
using VmStateBuffer = std::vector<u8>;
DeclareNoncopyableObject(ArchiveEntryList);
protected:
std::vector<ArchiveEntry> m_list;
std::unique_ptr<ArchiveDataBuffer> m_data;
VmStateBuffer m_data;
public:
virtual ~ArchiveEntryList() = default;
ArchiveEntryList() = default;
~ArchiveEntryList() = default;
ArchiveEntryList() {}
ArchiveEntryList(ArchiveDataBuffer* data)
: m_data(data)
const VmStateBuffer& GetBuffer() const
{
return m_data;
}
ArchiveEntryList(ArchiveDataBuffer& data)
: m_data(&data)
VmStateBuffer& GetBuffer()
{
}
const VmStateBuffer* GetBuffer() const
{
return m_data.get();
}
VmStateBuffer* GetBuffer()
{
return m_data.get();
return m_data;
}
u8* GetPtr(uint idx)
{
return &(*m_data)[idx];
return &m_data[idx];
}
const u8* GetPtr(uint idx) const
{
return &(*m_data)[idx];
return &m_data[idx];
}
ArchiveEntryList& Add(const ArchiveEntry& src)
@ -360,36 +344,24 @@ public:
// Saving and Loading Specialized Implementations...
// --------------------------------------------------------------------------------------
class memSavingState : public SaveStateBase
class memSavingState final : public SaveStateBase
{
typedef SaveStateBase _parent;
protected:
static const int ReallocThreshold = _1mb / 4; // 256k reallocation block size.
static const int MemoryBaseAllocSize = _8mb; // 8 meg base alloc when PS2 main memory is excluded
public:
virtual ~memSavingState() = default;
memSavingState( VmStateBuffer& save_to );
memSavingState( VmStateBuffer* save_to );
memSavingState(VmStateBuffer& save_to);
~memSavingState() override = default;
void MakeRoomForData();
void FreezeMem( void* data, int size );
bool IsSaving() const { return true; }
void FreezeMem(void* data, int size) override;
bool IsSaving() const override { return true; }
};
class memLoadingState : public SaveStateBase
class memLoadingState final : public SaveStateBase
{
public:
virtual ~memLoadingState() = default;
memLoadingState(const VmStateBuffer& load_from);
~memLoadingState() override = default;
memLoadingState( const VmStateBuffer& load_from );
memLoadingState( const VmStateBuffer* load_from );
void FreezeMem( void* data, int size );
bool IsSaving() const { return false; }
bool IsFinished() const { return m_idx >= m_memory->GetSizeInBytes(); }
void FreezeMem(void* data, int size) override;
bool IsSaving() const override { return false; }
};

View File

@ -25,6 +25,7 @@
#include "VUmicro.h"
#include "ps2/BiosTools.h"
#include "svnrev.h"
#include "SysForwardDefs.h"
#include "x86/newVif.h"
#include "common/Align.h"

View File

@ -15,19 +15,10 @@
#pragma once
#include "SysForwardDefs.h"
#include "common/SafeArray.h"
#include "common/Threading.h"
#include "Config.h"
#include "VirtualMemory.h"
#include "vtlb.h"
typedef SafeArray<u8> VmStateBuffer;
class BaseVUmicroCPU;
// This is a table of default virtual map addresses for ps2vm components. These locations
// are provided and used to assist in debugging and possibly hacking; as it makes it possible
// for a programmer to know exactly where to look (consistently!) for the base address of

View File

@ -29,6 +29,9 @@
#pragma clang diagnostic ignored "-Wmicrosoft-goto"
#endif
#define safe_release(ptr) \
((void)((((ptr) != NULL) && ((ptr)->Release(), !!0)), (ptr) = NULL))
namespace usb_eyetoy
{
namespace windows_api