mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 17:01:51 +00:00
- started reorganizing SW's memory management.
Need to get rid of all those unmanaged allocations and present game data in an easily serializable form. This adds a managed TPointer class that replicates the useful parts of std::unique_pointer but steers clear of its properties that often render it useless.
This commit is contained in:
parent
588fa5ffe2
commit
dcb393bc44
5 changed files with 175 additions and 17 deletions
|
@ -269,6 +269,32 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value,
|
||||||
return arc;
|
return arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T, class TT>
|
||||||
|
FSerializer& Serialize(FSerializer& arc, const char* key, TPointer<T>& value, TPointer<T>* def)
|
||||||
|
{
|
||||||
|
if (arc.isWriting())
|
||||||
|
{
|
||||||
|
if (value.Data() == nullptr && key) return arc;
|
||||||
|
}
|
||||||
|
bool res = arc.BeginArray(key);
|
||||||
|
if (arc.isReading())
|
||||||
|
{
|
||||||
|
if (!res || arc.ArraySize() == 0)
|
||||||
|
{
|
||||||
|
value.Clear();
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
value.Alloc();
|
||||||
|
}
|
||||||
|
if (value.Data())
|
||||||
|
{
|
||||||
|
Serialize(arc, nullptr, *value, def ? def->Data() : nullptr);
|
||||||
|
}
|
||||||
|
arc.EndArray();
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<int size>
|
template<int size>
|
||||||
FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray<size>& value, FixedBitArray<size>* def)
|
FSerializer& Serialize(FSerializer& arc, const char* key, FixedBitArray<size>& value, FixedBitArray<size>* def)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1368,6 +1368,128 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Pointer wrapper without the unpleasant side effects of std::unique_ptr, mainly the inability to copy it.
|
||||||
|
// This class owns the object with no means to release it, and copying the pointer copies the object.
|
||||||
|
template <class T>
|
||||||
|
class TPointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
////////
|
||||||
|
TPointer()
|
||||||
|
{
|
||||||
|
Ptr = nullptr;
|
||||||
|
}
|
||||||
|
TPointer(const T& other)
|
||||||
|
{
|
||||||
|
Alloc();
|
||||||
|
*Ptr = other;
|
||||||
|
}
|
||||||
|
TPointer(T&& other)
|
||||||
|
{
|
||||||
|
Alloc();
|
||||||
|
*Ptr = other;
|
||||||
|
}
|
||||||
|
TPointer(const TPointer<T>& other)
|
||||||
|
{
|
||||||
|
DoCopy(other);
|
||||||
|
}
|
||||||
|
TPointer(TPointer<T>&& other)
|
||||||
|
{
|
||||||
|
Ptr = other.Ptr;
|
||||||
|
other.Ptr = nullptr;
|
||||||
|
}
|
||||||
|
TPointer<T>& operator= (const T& other)
|
||||||
|
{
|
||||||
|
if (&other != this)
|
||||||
|
{
|
||||||
|
Alloc();
|
||||||
|
*Ptr = other;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
TPointer<T>& operator= (const TPointer<T>& other)
|
||||||
|
{
|
||||||
|
if (&other != this)
|
||||||
|
{
|
||||||
|
DoCopy(other);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
TPointer<T>& operator= (TPointer<T>&& other)
|
||||||
|
{
|
||||||
|
if (&other != this)
|
||||||
|
{
|
||||||
|
if (Ptr) delete Ptr;
|
||||||
|
Ptr = other.Ptr;
|
||||||
|
other.Ptr = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
~TPointer()
|
||||||
|
{
|
||||||
|
if (Ptr) delete Ptr;
|
||||||
|
Ptr = nullptr;
|
||||||
|
}
|
||||||
|
// Check equality of two pointers
|
||||||
|
bool operator==(const TPointer<T>& other) const
|
||||||
|
{
|
||||||
|
return *Ptr == *other.Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator* () const
|
||||||
|
{
|
||||||
|
assert(Ptr);
|
||||||
|
return *Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() { return Ptr; }
|
||||||
|
|
||||||
|
// returns raw pointer
|
||||||
|
T* Data() const
|
||||||
|
{
|
||||||
|
return Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T* () const
|
||||||
|
{
|
||||||
|
return Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Alloc()
|
||||||
|
{
|
||||||
|
if (!Ptr) Ptr = new T;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
if (Ptr) delete Ptr;
|
||||||
|
Ptr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Swap(TPointer<T>& other)
|
||||||
|
{
|
||||||
|
std::swap(Ptr, other.Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* Ptr;
|
||||||
|
|
||||||
|
void DoCopy(const TPointer<T>& other)
|
||||||
|
{
|
||||||
|
if (other.Ptr == nullptr)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Alloc();
|
||||||
|
*Ptr = *other.Ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -1115,12 +1115,22 @@ typedef struct
|
||||||
// User Extension record
|
// User Extension record
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef struct
|
struct USER
|
||||||
{
|
{
|
||||||
|
// These are for easy zero-init of USERs without having to be on the lookout for non-trivial members.
|
||||||
|
void* operator new(size_t alloc)
|
||||||
|
{
|
||||||
|
return M_Calloc(alloc, 1);
|
||||||
|
}
|
||||||
|
void operator delete (void* mem)
|
||||||
|
{
|
||||||
|
M_Free(mem);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Variables that can be used by actors and Player
|
// Variables that can be used by actors and Player
|
||||||
//
|
//
|
||||||
ROTATORp rotator;
|
TPointer<ROTATOR> rotator;
|
||||||
|
|
||||||
// wall vars for lighting
|
// wall vars for lighting
|
||||||
int WallCount;
|
int WallCount;
|
||||||
|
@ -1269,7 +1279,9 @@ typedef struct
|
||||||
int16_t oangdiff; // Used for interpolating sprite angles
|
int16_t oangdiff; // Used for interpolating sprite angles
|
||||||
|
|
||||||
uint8_t filler;
|
uint8_t filler;
|
||||||
} USER,*USERp;
|
};
|
||||||
|
|
||||||
|
using USERp = USER*;
|
||||||
|
|
||||||
struct USERSAVE
|
struct USERSAVE
|
||||||
{
|
{
|
||||||
|
@ -1440,21 +1452,15 @@ typedef struct
|
||||||
} RANGE,*RANGEp;
|
} RANGE,*RANGEp;
|
||||||
|
|
||||||
|
|
||||||
inline void ClearUser(USER* user)
|
#pragma message ("Remove NewUser/FreeUser!")
|
||||||
{
|
|
||||||
*user = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline USER* NewUser()
|
inline USER* NewUser()
|
||||||
{
|
{
|
||||||
auto u = (USER*)M_Calloc(sizeof(USER), 1);// new USER;
|
return new USER;
|
||||||
ClearUser(u);
|
|
||||||
return u;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void FreeUser(int num)
|
inline void FreeUser(int num)
|
||||||
{
|
{
|
||||||
if (User[num]) M_Free(User[num]);// delete User[num];
|
if (User[num]) delete User[num];
|
||||||
User[num] = nullptr;
|
User[num] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -747,7 +747,11 @@ bool GameInterface::LoadGame()
|
||||||
while (SpriteNum != -1)
|
while (SpriteNum != -1)
|
||||||
{
|
{
|
||||||
User[SpriteNum] = u = NewUser();
|
User[SpriteNum] = u = NewUser();
|
||||||
|
// We need to be careful with allocated content in User when loading a binary save state.
|
||||||
|
// This needs to be refactored out ASAP.
|
||||||
|
u->rotator.Clear();
|
||||||
MREAD(u,sizeof(USER),1,fil);
|
MREAD(u,sizeof(USER),1,fil);
|
||||||
|
memset((void*)&u->rotator, 0, sizeof(u->rotator));
|
||||||
|
|
||||||
if (u->WallShade)
|
if (u->WallShade)
|
||||||
{
|
{
|
||||||
|
@ -757,7 +761,7 @@ bool GameInterface::LoadGame()
|
||||||
|
|
||||||
if (u->rotator)
|
if (u->rotator)
|
||||||
{
|
{
|
||||||
u->rotator = (ROTATORp)CallocMem(sizeof(*u->rotator), 1);
|
u->rotator.Alloc();
|
||||||
MREAD(u->rotator,sizeof(*u->rotator),1,fil);
|
MREAD(u->rotator,sizeof(*u->rotator),1,fil);
|
||||||
|
|
||||||
if (u->rotator->origx)
|
if (u->rotator->origx)
|
||||||
|
|
|
@ -790,7 +790,8 @@ KillSprite(int16_t SpriteNum)
|
||||||
FreeMem(u->rotator->origx);
|
FreeMem(u->rotator->origx);
|
||||||
if (u->rotator->origy)
|
if (u->rotator->origy)
|
||||||
FreeMem(u->rotator->origy);
|
FreeMem(u->rotator->origy);
|
||||||
FreeMem(u->rotator);
|
|
||||||
|
u->rotator.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeUser(SpriteNum);
|
FreeUser(SpriteNum);
|
||||||
|
@ -909,7 +910,6 @@ SpawnUser(short SpriteNum, short id, STATEp state)
|
||||||
u->WaitTics = 0;
|
u->WaitTics = 0;
|
||||||
u->OverlapZ = Z(4);
|
u->OverlapZ = Z(4);
|
||||||
u->WallShade = NULL;
|
u->WallShade = NULL;
|
||||||
u->rotator = NULL;
|
|
||||||
u->bounce = 0;
|
u->bounce = 0;
|
||||||
|
|
||||||
u->motion_blur_num = 0;
|
u->motion_blur_num = 0;
|
||||||
|
@ -2404,7 +2404,7 @@ SpriteSetup(void)
|
||||||
for (w = startwall, wallcount = 0; w <= endwall; w++)
|
for (w = startwall, wallcount = 0; w <= endwall; w++)
|
||||||
wallcount++;
|
wallcount++;
|
||||||
|
|
||||||
u->rotator = (ROTATORp)CallocMem(sizeof(ROTATOR), 1);
|
u->rotator.Alloc();
|
||||||
u->rotator->num_walls = wallcount;
|
u->rotator->num_walls = wallcount;
|
||||||
u->rotator->open_dest = SP_TAG5(sp);
|
u->rotator->open_dest = SP_TAG5(sp);
|
||||||
u->rotator->speed = SP_TAG7(sp);
|
u->rotator->speed = SP_TAG7(sp);
|
||||||
|
@ -2460,7 +2460,7 @@ SpriteSetup(void)
|
||||||
u->WaitTics = time*15; // 1/8 of a sec
|
u->WaitTics = time*15; // 1/8 of a sec
|
||||||
u->Tics = 0;
|
u->Tics = 0;
|
||||||
|
|
||||||
u->rotator = (ROTATORp)CallocMem(sizeof(ROTATOR), 1);
|
u->rotator.Alloc();
|
||||||
u->rotator->open_dest = SP_TAG5(sp);
|
u->rotator->open_dest = SP_TAG5(sp);
|
||||||
u->rotator->speed = SP_TAG7(sp);
|
u->rotator->speed = SP_TAG7(sp);
|
||||||
u->rotator->vel = SP_TAG8(sp);
|
u->rotator->vel = SP_TAG8(sp);
|
||||||
|
|
Loading…
Reference in a new issue