mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-11-04 00:07:19 +01:00 
			
		
		
		
	Get rid of the memory manager from buffer.
This commit is contained in:
		@@ -5,7 +5,6 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -47,343 +46,11 @@ void ThrowMemExcept(const char * msg, ...)
 | 
			
		||||
    throw Sqrat::Exception(buffer); // NOLINT(hicpp-exception-baseclass,cert-err60-cpp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Allocate a memory buffer and return it.
 | 
			
		||||
*/
 | 
			
		||||
static Buffer::Pointer AllocMem(Buffer::SzType size)
 | 
			
		||||
{
 | 
			
		||||
    // Attempt to allocate memory directly
 | 
			
		||||
    auto ptr = reinterpret_cast< Buffer::Pointer >(std::malloc(size));
 | 
			
		||||
    // Validate the allocated memory
 | 
			
		||||
    if (!ptr)
 | 
			
		||||
    {
 | 
			
		||||
        ThrowMemExcept("Unable to allocate (%u) bytes of memory", size);
 | 
			
		||||
    }
 | 
			
		||||
    // Return the allocated memory
 | 
			
		||||
    return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * ...
 | 
			
		||||
*/
 | 
			
		||||
class MemCat
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Memory;
 | 
			
		||||
    friend class Buffer;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef Buffer::Value       Value; // The type of value used to represent a byte.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef Buffer::Reference   Reference; // A reference to the stored value type.
 | 
			
		||||
    typedef Buffer::ConstRef    ConstRef; // A const reference to the stored value type.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef Buffer::Pointer     Pointer; // A pointer to the stored value type.
 | 
			
		||||
    typedef Buffer::ConstPtr    ConstPtr; // A const pointer to the stored value type.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef Buffer::SzType      SzType; // The type used to represent size in general.
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Structure used to store a memory chunk in the linked list.
 | 
			
		||||
    */
 | 
			
		||||
    struct Node
 | 
			
		||||
    {
 | 
			
		||||
        // ----------------------------------------------------------------------------------------
 | 
			
		||||
        SzType      mCap; // The size of the memory chunk.
 | 
			
		||||
        Pointer     mPtr; // Pointer to the memory chunk.
 | 
			
		||||
        Node*       mNext; // The next node in the list.
 | 
			
		||||
 | 
			
		||||
        /* ----------------------------------------------------------------------------------------
 | 
			
		||||
         * Base constructor.
 | 
			
		||||
        */
 | 
			
		||||
        explicit Node(Node * next)
 | 
			
		||||
            : mCap(0)
 | 
			
		||||
            , mPtr(nullptr)
 | 
			
		||||
            , mNext(next)
 | 
			
		||||
        {
 | 
			
		||||
            /* ... */
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    static Node *   s_Nodes; /* List of unused node instances. */
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Node*   m_Head; /* The head memory node. */
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    MemCat()
 | 
			
		||||
        : m_Head(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~MemCat()
 | 
			
		||||
    {
 | 
			
		||||
        for (Node * node = m_Head, * next = nullptr; node; node = next)
 | 
			
		||||
        {
 | 
			
		||||
            // Free the memory (if any)
 | 
			
		||||
            if (node->mPtr)
 | 
			
		||||
            {
 | 
			
		||||
                std::free(node->mPtr);
 | 
			
		||||
            }
 | 
			
		||||
            // Save the next node
 | 
			
		||||
            next = node->mNext;
 | 
			
		||||
            // Release the node instance
 | 
			
		||||
            delete node;
 | 
			
		||||
        }
 | 
			
		||||
        // Explicitly set the head node to null
 | 
			
		||||
        m_Head = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Clear all memory buffers from the pool.
 | 
			
		||||
    */
 | 
			
		||||
    void Clear()
 | 
			
		||||
    {
 | 
			
		||||
        for (Node * node = m_Head, * next = nullptr; node; node = next)
 | 
			
		||||
        {
 | 
			
		||||
            // Free the memory (if any)
 | 
			
		||||
            if (node->mPtr)
 | 
			
		||||
            {
 | 
			
		||||
                free(node->mPtr);
 | 
			
		||||
            }
 | 
			
		||||
            // Save the next node
 | 
			
		||||
            next = node->mNext;
 | 
			
		||||
            // Release the node instance
 | 
			
		||||
            Push(node);
 | 
			
		||||
        }
 | 
			
		||||
        // Explicitly set the head node to null
 | 
			
		||||
        m_Head = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Grab a memory buffer from the pool.
 | 
			
		||||
    */
 | 
			
		||||
    void Grab(Pointer & ptr, SzType & size)
 | 
			
		||||
    {
 | 
			
		||||
        // NOTE: Function assumes (size > 0)
 | 
			
		||||
        // Find a buffer large enough to satisfy the requested size
 | 
			
		||||
        for (Node * node = m_Head, * prev = nullptr; node; prev = node, node = node->mNext)
 | 
			
		||||
        {
 | 
			
		||||
            // Is this buffer large enough?
 | 
			
		||||
            if (node->mCap >= size)
 | 
			
		||||
            {
 | 
			
		||||
                // Was there a previous node?
 | 
			
		||||
                if (prev)
 | 
			
		||||
                {
 | 
			
		||||
                    prev->mNext = node->mNext;
 | 
			
		||||
                }
 | 
			
		||||
                // Probably this was the head
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    m_Head = node->mNext;
 | 
			
		||||
                }
 | 
			
		||||
                // Assign the memory
 | 
			
		||||
                ptr = node->mPtr;
 | 
			
		||||
                // Assign the size
 | 
			
		||||
                size = node->mCap;
 | 
			
		||||
                // Release the node instance
 | 
			
		||||
                Push(node);
 | 
			
		||||
                // Exit the function
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // Round up the size to a power of two number
 | 
			
		||||
        size = (size & (size - 1)) ? NextPow2(size) : size;
 | 
			
		||||
        // Allocate the memory directly
 | 
			
		||||
        ptr = AllocMem(size);
 | 
			
		||||
        // See if the memory could be allocated
 | 
			
		||||
        // (shouldn't reach this point if allocation failed)
 | 
			
		||||
        if (!ptr)
 | 
			
		||||
        {
 | 
			
		||||
            // Revert the size
 | 
			
		||||
            size = 0;
 | 
			
		||||
            // Throw the exception
 | 
			
		||||
            ThrowMemExcept("Unable to allocate (%u) bytes of memory", size);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return a memory buffer to the pool.
 | 
			
		||||
    */
 | 
			
		||||
    void Drop(Pointer & ptr, SzType & size)
 | 
			
		||||
    {
 | 
			
		||||
        if (!ptr)
 | 
			
		||||
        {
 | 
			
		||||
            ThrowMemExcept("Cannot store invalid memory buffer");
 | 
			
		||||
        }
 | 
			
		||||
        // Request a node instance
 | 
			
		||||
        Node * node = Pull();
 | 
			
		||||
        // Assign the specified memory
 | 
			
		||||
        node->mPtr = ptr;
 | 
			
		||||
        // Assign the specified size
 | 
			
		||||
        node->mCap = size;
 | 
			
		||||
        // Demote the current head node
 | 
			
		||||
        node->mNext = m_Head;
 | 
			
		||||
        // Promote as the head node
 | 
			
		||||
        m_Head = node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Allocate a group of nodes and pool them for later use.
 | 
			
		||||
    */
 | 
			
		||||
    static void Make()
 | 
			
		||||
    {
 | 
			
		||||
        for (SzType n = 16; n; --n)
 | 
			
		||||
        {
 | 
			
		||||
            // Create a new node instance
 | 
			
		||||
            s_Nodes = new Node(s_Nodes);
 | 
			
		||||
            // Validate the head node
 | 
			
		||||
            if (!s_Nodes)
 | 
			
		||||
            {
 | 
			
		||||
                ThrowMemExcept("Unable to allocate memory nodes");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve an unused node from the free list.
 | 
			
		||||
    */
 | 
			
		||||
    static Node * Pull()
 | 
			
		||||
    {
 | 
			
		||||
        // Are there any nodes available?
 | 
			
		||||
        if (!s_Nodes)
 | 
			
		||||
        {
 | 
			
		||||
            Make(); // Make some!
 | 
			
		||||
        }
 | 
			
		||||
        // Grab the head node
 | 
			
		||||
        Node * node = s_Nodes;
 | 
			
		||||
        // Promote the next node as the head
 | 
			
		||||
        s_Nodes = node->mNext;
 | 
			
		||||
        // Return the node
 | 
			
		||||
        return node;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return a node to the free list.
 | 
			
		||||
    */
 | 
			
		||||
    static void Push(Node * node)
 | 
			
		||||
    {
 | 
			
		||||
        // See if the node is even valid
 | 
			
		||||
        if (!node)
 | 
			
		||||
        {
 | 
			
		||||
            ThrowMemExcept("Attempting to push invalid node");
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            // Demote the current head node
 | 
			
		||||
            node->mNext = s_Nodes;
 | 
			
		||||
            // Promote as the head node
 | 
			
		||||
            s_Nodes = node;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
MemCat::Node *  MemCat::s_Nodes = nullptr;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Lightweight memory allocator to reduce the overhead of small allocations.
 | 
			
		||||
*/
 | 
			
		||||
class Memory
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Buffer; // Allow the buffer type to access the memory categories.
 | 
			
		||||
    friend class MemRef; // Allow the memory manager reference to create new instances.
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Memory()
 | 
			
		||||
        : m_Small()
 | 
			
		||||
        , m_Medium()
 | 
			
		||||
        , m_Large()
 | 
			
		||||
    {
 | 
			
		||||
        // Allocate several nodes for when memory starts pooling
 | 
			
		||||
        MemCat::Make();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~Memory()
 | 
			
		||||
    {
 | 
			
		||||
        for (MemCat::Node * node = MemCat::s_Nodes, * next = nullptr; node; node = next)
 | 
			
		||||
        {
 | 
			
		||||
            // Save the next node
 | 
			
		||||
            next = node->mNext;
 | 
			
		||||
            // Release the node instance
 | 
			
		||||
            delete node;
 | 
			
		||||
        }
 | 
			
		||||
        // Explicitly set the head node to null
 | 
			
		||||
        MemCat::s_Nodes = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    MemCat m_Small; // Small memory allocations of <= 1024 bytes.
 | 
			
		||||
    MemCat m_Medium; // Medium memory allocations of <= 4096 bytes.
 | 
			
		||||
    MemCat m_Large; // Large memory allocations of <= 4096 bytes.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
MemRef MemRef::s_Mem{nullptr};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MemRef::Grab()
 | 
			
		||||
{
 | 
			
		||||
    if (m_Ptr)
 | 
			
		||||
    {
 | 
			
		||||
        ++(*m_Ref);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void MemRef::Drop()
 | 
			
		||||
{
 | 
			
		||||
    if (m_Ptr && --(*m_Ref) == 0)
 | 
			
		||||
    {
 | 
			
		||||
        delete m_Ptr;
 | 
			
		||||
        delete m_Ref;
 | 
			
		||||
        m_Ptr = nullptr;
 | 
			
		||||
        m_Ref = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
const MemRef & MemRef::Get()
 | 
			
		||||
{
 | 
			
		||||
    if (!s_Mem.m_Ptr)
 | 
			
		||||
    {
 | 
			
		||||
        s_Mem.m_Ptr = new Memory();
 | 
			
		||||
        s_Mem.m_Ref = new Counter(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return s_Mem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Buffer::Buffer(const Buffer & o)
 | 
			
		||||
    : m_Ptr(nullptr)
 | 
			
		||||
    , m_Cap(o.m_Cap)
 | 
			
		||||
    , m_Cur(o.m_Cur)
 | 
			
		||||
    , m_Mem(o.m_Mem)
 | 
			
		||||
{
 | 
			
		||||
    if (m_Cap)
 | 
			
		||||
    {
 | 
			
		||||
@@ -445,7 +112,7 @@ Buffer & Buffer::operator = (const Buffer & o) // NOLINT(cert-oop54-cpp)
 | 
			
		||||
void Buffer::Grow(SzType n)
 | 
			
		||||
{
 | 
			
		||||
    // Backup the current memory
 | 
			
		||||
    Buffer bkp(m_Ptr, m_Cap, m_Cur, m_Mem);
 | 
			
		||||
    Buffer bkp(m_Ptr, m_Cap, m_Cur);
 | 
			
		||||
    // Acquire a bigger buffer
 | 
			
		||||
    Request(bkp.m_Cap + n);
 | 
			
		||||
    // Copy the data from the old buffer
 | 
			
		||||
@@ -458,27 +125,13 @@ void Buffer::Grow(SzType n)
 | 
			
		||||
void Buffer::Request(SzType n)
 | 
			
		||||
{
 | 
			
		||||
    // NOTE: Function assumes (n > 0)
 | 
			
		||||
    // Is there a memory manager available?
 | 
			
		||||
    if (!m_Mem)
 | 
			
		||||
    {
 | 
			
		||||
        // Round up the size to a power of two number
 | 
			
		||||
        n = (n & (n - 1)) ? NextPow2(n) : n;
 | 
			
		||||
        // Allocate the memory directly
 | 
			
		||||
        m_Ptr = AllocMem(n);
 | 
			
		||||
    }
 | 
			
		||||
    // Find out in which category does this buffer reside
 | 
			
		||||
    else if (n <= 1024)
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Small.Grab(m_Ptr, n);
 | 
			
		||||
    }
 | 
			
		||||
    else if (n <= 4096)
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Medium.Grab(m_Ptr, n);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Large.Grab(m_Ptr, n);
 | 
			
		||||
    }
 | 
			
		||||
    assert(n > 0);
 | 
			
		||||
    // Round up the size to a power of two number
 | 
			
		||||
    n = (n & (n - 1)) ? NextPow2(n) : n;
 | 
			
		||||
    // Release previous memory if any
 | 
			
		||||
    delete[] m_Ptr; // Implicitly handles null!
 | 
			
		||||
    // Attempt to allocate memory
 | 
			
		||||
    m_Ptr = new Value[n];
 | 
			
		||||
    // If no errors occurred then we can set the size
 | 
			
		||||
    m_Cap = n;
 | 
			
		||||
}
 | 
			
		||||
@@ -486,25 +139,8 @@ void Buffer::Request(SzType n)
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Buffer::Release()
 | 
			
		||||
{
 | 
			
		||||
    // TODO: Implement a limit on how much memory can actually be pooled.
 | 
			
		||||
    // Is there a memory manager available?
 | 
			
		||||
    if (!m_Mem)
 | 
			
		||||
    {
 | 
			
		||||
        std::free(m_Ptr); // Deallocate the memory directly
 | 
			
		||||
    }
 | 
			
		||||
    // Find out to which category does this buffer belong
 | 
			
		||||
    else if (m_Cap <= 1024)
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Small.Drop(m_Ptr, m_Cap);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Cap <= 4096)
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Medium.Drop(m_Ptr, m_Cap);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_Mem->m_Large.Drop(m_Ptr, m_Cap);
 | 
			
		||||
    }
 | 
			
		||||
    // Deallocate the memory
 | 
			
		||||
    delete[] m_Ptr; // Implicitly handles null!
 | 
			
		||||
    // Explicitly reset the buffer
 | 
			
		||||
    m_Ptr = nullptr;
 | 
			
		||||
    m_Cap = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,178 +11,6 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
class Memory;
 | 
			
		||||
class Buffer;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * A counted reference to a memory manager instance.
 | 
			
		||||
*/
 | 
			
		||||
class MemRef
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    static MemRef s_Mem;
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef unsigned int Counter;
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Memory*     m_Ptr; // The memory manager instance.
 | 
			
		||||
    Counter*    m_Ref; // Reference count to the managed instance.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Grab a strong reference to a memory manager.
 | 
			
		||||
    */
 | 
			
		||||
    void Grab();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Drop a strong reference to a memory manager.
 | 
			
		||||
    */
 | 
			
		||||
    void Drop();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Get a reference to the global memory manager instance.
 | 
			
		||||
    */
 | 
			
		||||
    static const MemRef & Get();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor (null).
 | 
			
		||||
    */
 | 
			
		||||
    MemRef() noexcept
 | 
			
		||||
        : m_Ptr(s_Mem.m_Ptr)
 | 
			
		||||
        , m_Ref(s_Mem.m_Ref)
 | 
			
		||||
    {
 | 
			
		||||
        Grab();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor (null).
 | 
			
		||||
    */
 | 
			
		||||
    explicit MemRef(std::nullptr_t) noexcept
 | 
			
		||||
            : m_Ptr(nullptr)
 | 
			
		||||
            , m_Ref(nullptr)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    MemRef(const MemRef & o) noexcept
 | 
			
		||||
        : m_Ptr(o.m_Ptr)
 | 
			
		||||
        , m_Ref(o.m_Ref)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        Grab();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    MemRef(MemRef && o) noexcept
 | 
			
		||||
        : m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        o.m_Ptr = nullptr;
 | 
			
		||||
        o.m_Ref = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~MemRef()
 | 
			
		||||
    {
 | 
			
		||||
        Drop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    MemRef & operator = (const MemRef & o) noexcept // NOLINT(bugprone-unhandled-self-assignment,cert-oop54-cpp)
 | 
			
		||||
    {
 | 
			
		||||
        if (m_Ptr != o.m_Ptr)
 | 
			
		||||
        {
 | 
			
		||||
            Drop();
 | 
			
		||||
            m_Ptr = o.m_Ptr;
 | 
			
		||||
            m_Ref = o.m_Ref;
 | 
			
		||||
            Grab();
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    MemRef & operator = (MemRef && o) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        if (m_Ptr != o.m_Ptr)
 | 
			
		||||
        {
 | 
			
		||||
            Drop();
 | 
			
		||||
            m_Ptr = o.m_Ptr;
 | 
			
		||||
            m_Ref = o.m_Ref;
 | 
			
		||||
            o.m_Ptr = nullptr;
 | 
			
		||||
            o.m_Ref = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an equality comparison between two memory managers.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator == (const MemRef & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Ptr == o.m_Ptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an inequality comparison between two memory managers.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator != (const MemRef & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Ptr != o.m_Ptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Implicit conversion to boolean for use in boolean operations.
 | 
			
		||||
    */
 | 
			
		||||
    operator bool () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
 | 
			
		||||
    {
 | 
			
		||||
        return static_cast<bool>(m_Ptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Member operator for dereferencing the managed pointer.
 | 
			
		||||
    */
 | 
			
		||||
    Memory * operator -> () const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_Ptr);
 | 
			
		||||
        return m_Ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Indirection operator for obtaining a reference of the managed pointer.
 | 
			
		||||
    */
 | 
			
		||||
    Memory & operator * () const
 | 
			
		||||
    {
 | 
			
		||||
        assert(m_Ptr);
 | 
			
		||||
        return *m_Ptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release the reference to the managed instance.
 | 
			
		||||
    */
 | 
			
		||||
    void Reset()
 | 
			
		||||
    {
 | 
			
		||||
        if (m_Ptr)
 | 
			
		||||
        {
 | 
			
		||||
            Drop();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void ThrowMemExcept(const char * msg, ...);
 | 
			
		||||
 | 
			
		||||
@@ -207,16 +35,18 @@ public:
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    typedef unsigned int    SzType; // The type used to represent size in general.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    static_assert(sizeof(Value) == 1, "Value type must be 1 byte");
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct and take ownership of the specified buffer.
 | 
			
		||||
    */
 | 
			
		||||
    Buffer(Pointer & ptr, SzType & cap, SzType & cur, MemRef mem)
 | 
			
		||||
    Buffer(Pointer & ptr, SzType & cap, SzType & cur)
 | 
			
		||||
        : m_Ptr(ptr)
 | 
			
		||||
        , m_Cap(cap)
 | 
			
		||||
        , m_Cur(cur)
 | 
			
		||||
        , m_Mem(std::move(mem))
 | 
			
		||||
    {
 | 
			
		||||
        ptr = nullptr;
 | 
			
		||||
        cap = 0;
 | 
			
		||||
@@ -240,7 +70,6 @@ public:
 | 
			
		||||
        : m_Ptr(nullptr)
 | 
			
		||||
        , m_Cap(0)
 | 
			
		||||
        , m_Cur(0)
 | 
			
		||||
        , m_Mem(MemRef::Get())
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
@@ -252,7 +81,6 @@ public:
 | 
			
		||||
        : m_Ptr(nullptr)
 | 
			
		||||
        , m_Cap(0)
 | 
			
		||||
        , m_Cur(0)
 | 
			
		||||
        , m_Mem(MemRef::Get())
 | 
			
		||||
    {
 | 
			
		||||
        Request(size < 8 ? 8 : size);
 | 
			
		||||
    }
 | 
			
		||||
@@ -264,7 +92,6 @@ public:
 | 
			
		||||
        : m_Ptr(nullptr)
 | 
			
		||||
        , m_Cap(0)
 | 
			
		||||
        , m_Cur(0)
 | 
			
		||||
        , m_Mem(MemRef::Get())
 | 
			
		||||
    {
 | 
			
		||||
        Request(size < 8 ? 8 : size);
 | 
			
		||||
        Move(pos);
 | 
			
		||||
@@ -277,7 +104,6 @@ public:
 | 
			
		||||
        : m_Ptr(nullptr)
 | 
			
		||||
        , m_Cap(0)
 | 
			
		||||
        , m_Cur(0)
 | 
			
		||||
        , m_Mem(MemRef::Get())
 | 
			
		||||
    {
 | 
			
		||||
        Request(size < 8 ? 8 : size);
 | 
			
		||||
        m_Cur += Write(m_Cur, data, size);
 | 
			
		||||
@@ -290,7 +116,6 @@ public:
 | 
			
		||||
        : m_Ptr(nullptr)
 | 
			
		||||
        , m_Cap(0)
 | 
			
		||||
        , m_Cur(0)
 | 
			
		||||
        , m_Mem(MemRef::Get())
 | 
			
		||||
    {
 | 
			
		||||
        Request(size < 8 ? 8 : size);
 | 
			
		||||
        Write(m_Cur, data, size);
 | 
			
		||||
@@ -309,7 +134,6 @@ public:
 | 
			
		||||
        : m_Ptr(o.m_Ptr)
 | 
			
		||||
        , m_Cap(o.m_Cap)
 | 
			
		||||
        , m_Cur(o.m_Cur)
 | 
			
		||||
        , m_Mem(std::forward< MemRef >(o.m_Mem))
 | 
			
		||||
    {
 | 
			
		||||
        o.m_Ptr = nullptr;
 | 
			
		||||
    }
 | 
			
		||||
@@ -338,7 +162,6 @@ public:
 | 
			
		||||
            m_Ptr = o.m_Ptr;
 | 
			
		||||
            m_Cap = o.m_Cap;
 | 
			
		||||
            m_Cur = o.m_Cur;
 | 
			
		||||
            m_Mem = o.m_Mem;
 | 
			
		||||
            o.m_Ptr = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        return *this;
 | 
			
		||||
@@ -882,7 +705,7 @@ public:
 | 
			
		||||
        else if (n > m_Cap)
 | 
			
		||||
        {
 | 
			
		||||
            // Backup the current memory
 | 
			
		||||
            Buffer bkp(m_Ptr, m_Cap, m_Cur, m_Mem);
 | 
			
		||||
            Buffer bkp(m_Ptr, m_Cap, m_Cur);
 | 
			
		||||
            // Request the memory
 | 
			
		||||
            Request(n * sizeof(T));
 | 
			
		||||
            // Return the backup
 | 
			
		||||
@@ -904,7 +727,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release the managed memory and manager.
 | 
			
		||||
     * Release the managed memory.
 | 
			
		||||
    */
 | 
			
		||||
    void ResetAll()
 | 
			
		||||
    {
 | 
			
		||||
@@ -912,7 +735,6 @@ public:
 | 
			
		||||
        {
 | 
			
		||||
            Release();
 | 
			
		||||
        }
 | 
			
		||||
        m_Mem.Reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
@@ -1024,9 +846,6 @@ private:
 | 
			
		||||
    Pointer     m_Ptr; /* Pointer to the memory buffer. */
 | 
			
		||||
    SzType      m_Cap; /* The total size of the buffer. */
 | 
			
		||||
    SzType      m_Cur; /* The buffer edit cursor. */
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    MemRef      m_Mem; /* Reference to the associated memory manager. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user