1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Add another stack cleanup utility to the Sqrat library.

This commit is contained in:
Sandu Liviu Catalin 2017-08-07 00:21:59 +03:00
parent fccf288b77
commit 2e8d97f071

View File

@ -1411,6 +1411,63 @@ public:
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper structure for popping elements from the stack.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct SqPopGuard
{
HSQUIRRELVM mVM; // The VM from which the elements must be popped.
SQInteger mNum; // The number of elements to be popped.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Base constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqPopGuard(HSQUIRRELVM vm, SQInteger num)
: mVM(vm), mNum(num)
{
//...
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Destructor. Pops the specified elements from the stack.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
~SqPopGuard()
{
sq_pop(mVM, mNum);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Increment the number of elements to be popped.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqPopGuard & operator ++ ()
{
++mNum;
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Decrement the number of elements to be popped.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqPopGuard & operator -- ()
{
--mNum;
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Increase the number of elements to be popped.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqPopGuard & operator += (SQInteger n)
{
mNum += n;
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Decrease the number of elements to be popped.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqPopGuard & operator -= (SQInteger n)
{
mNum -= n;
return *this;
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Implements RAII to restore the VM stack to it's initial size on function exit.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1721,6 +1778,97 @@ public:
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper structure used to make it easy to track instances of a certain type.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template < typename T > struct SqChainedInstances
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Default constructor.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SqChainedInstances()
: m_Prev(nullptr), m_Next(nullptr)
{
//...
}
protected:
SqChainedInstances * m_Prev; // Previous instance in the chain.
SqChainedInstances * m_Next; // Next instance in the chain.
static SqChainedInstances * s_Head; // The head of the instance chain.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Attach the instance to the chain.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ChainInstance()
{
// Is there an existing head?
if (s_Head == nullptr)
{
// There was no existing head
m_Prev = m_Next = nullptr;
// We're the head
s_Head = this;
}
// Is there a preceding instance before the current head?
else if (s_Head->m_Prev == nullptr)
{
// Grab the current head as the next instance in the chain
m_Next = s_Head;
// Become the new head and the preceding instance of the current head
m_Next->m_Prev = s_Head = this;
}
else
{
// Grab the current head as the next instance in the chain
m_Next = s_Head;
// Become the new head and the next instance of the preceding instance of the current head
m_Next->m_Prev->m_Next = s_Head = this;
// Become the preceding instance of the current head
m_Next->m_Prev = this;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Detach the instance from the chain.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UnchainInstance()
{
// Is there an instance after us?
if (m_Next != nullptr)
{
// Link the next instance with the one before us
m_Next->m_Prev = m_Prev;
// Are we the current head?
if (s_Head == this)
{
s_Head = m_Next; // Make the next one the head
}
}
// Is there an instance before us?
if (m_Prev != nullptr)
{
// Link the previous instance with the one after us
m_Prev->m_Next = m_Next;
// Are we the current head?
if (s_Head == nullptr || s_Head == this)
{
// If there was no instance after us then make the previous one the head
s_Head = m_Prev;
}
}
// Are we the current and the only head?
else if (s_Head == this)
{
s_Head = nullptr; // No more instances of this type
}
}
};
template < typename T > SqChainedInstances< T > * SqChainedInstances< T >::s_Head = nullptr;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @cond DEV
/// Used internally to get and manipulate the underlying type of variables - retrieved from cppreference.com