Click here to Skip to main content
15,898,134 members
Articles / Programming Languages / C++

Heap Manager for Allocating Memory from a Shared Memory Segment

Rate me:
Please Sign up or sign in to vote.
4.73/5 (13 votes)
20 Jun 2006CPOL9 min read 87.9K   1.8K   48  
A heap manager for allocating memory from a shared memory segment.
/**
 * Common template classes
 *
 * This source code is free and anyone can copy, pirate or distribute
 * the code without prior written or vocal permission.
 *
 * This software is provided "AS IS" and without any express or implied
 * warranties, including, but not limited to, the implied warranties of
 * merchantability and fitness for a particular purpose are disclaimed.
 *
 * Written By: Pradeep Chulliyan
 * Dated: June 07 2006
 */
#ifndef __STDTMPL_H__
#define __STDTMPL_H__

// Pointer wrapper class
//
template <typename T> class CPtr
{
    // Constructors and destructor
    //
public:
    CPtr() : m_len (0), m_ptr (0) {}
    virtual ~CPtr() {}

    // Public methods
    //
public:
    // Return the internal pointer
    //
    operator T*()       {return m_ptr;}
    operator const T*() {return m_ptr;}

    // Return the current size
    //
    int GetSize() const {return m_len;}

    // Return the pointer
    //
    T* GetPtr() {return m_ptr;}

    // Shared attributes
    //
protected:
    int m_len;
    T*  m_ptr;
};

// Automatic pointer
//
template <typename T> class CAutoPtr : public CPtr<T>
{
    // Constructors and destructor
    //
public:
    CAutoPtr (int l) : CPtr<T>() {GetPtr (l);}
    virtual ~CAutoPtr() {if (this->m_ptr) ::free (this->m_ptr);}

    // Public methods
    //
public:
    // Return a pointer to the item in the array
    //
    T* operator[] (int d) {return (d < 0 ? 0 : &this->m_ptr[d]);}

    // Return a buffer of at least 'len' size. Re-allocate the pointer 
    // if the previous size is less than 'len'.
    //
    T* GetPtr (int len)
    {
        if (len > this->m_len)
        {
            // Allocate a new buffer
            //
            T* ptr = (T*)::malloc (len * sizeof (T));

            // Copy the old buffer to the new one
            //
            if (this->m_ptr)
            {
                if (ptr)
                    memcpy (ptr, this->m_ptr, this->m_len * sizeof (T));
                ::free (this->m_ptr);
            }

            this->m_ptr = ptr;
            this->m_len = len;
        }
        return this->m_ptr;
    }
};

// Sorted list that supports binary search. This list cannot hold duplicate
// entries.
//
template <typename T> class CSortedList : public CAutoPtr<T>
{
    // Constructors and destructor
    //
public:
    CSortedList (int l) : CAutoPtr<T> (l), m_cnt (0), m_off (0), m_grn (32) {}
    virtual ~CSortedList() {}

    // Public methods
    //
public:
    // Set the number of items in the list
    //
    void SetCount (int cnt) {m_cnt = cnt;}

    // Set an offset for the list
    //
    void SetOffset (int off) {m_off = off;}

    // Set growth granularity
    //
    void SetGrowBy (int val) {m_grn = val;}

    // Return the number of items in the list
    //
    int GetCount() {return m_cnt;}

    // Clear the list
    //
    void Clear() {m_cnt = 0;}

    // Locate a value in the list
    //
    int Locate (const T* v)
    {
        int idx = 0;
        return Locate (v, true, idx);
    }
    
    // Locate an item in the list. If the value of 'exact' is true, then 
    // return value will be -1 if an exact match is not found.
    //
    int Locate (const T* v, bool exact, int& idx)
    {
        int tst = -1;

        if (m_cnt > 0)
        {
            int fst = m_off;
            int lst = m_off + m_cnt;
                
            idx = (fst + lst) / 2;
            tst = Compare (v, &this->m_ptr[idx]);

            do
            {
                if (tst < 0)
                    lst = idx;
                else if (tst > 0)
                    fst = idx;
                else
                    break;

                idx = (fst + lst) / 2;
                tst = Compare (v, &this->m_ptr[idx]);
            }
            while (tst && idx > fst);
        }
        else
            idx = m_off;
     
        // Return the index
        //
        return ((tst && exact) ? -1 : idx);
    }

    // Insert a value into the sorted list. If the 'idx' has a valid value,
    // then the item will be inserted at that index
    //
    void Insert (const T* v, int idx = -1)
    {
        if (idx < 0)
            Locate (v, false, idx);

        if (idx < (m_off + m_cnt))
        {
            int tst = Compare (v, &this->m_ptr[idx]);
            if (tst == 0)
                return;

            if (tst > 0)
                idx++;

            // Expand array
            //
            if ((m_off + m_cnt) == this->m_len)
            {
                Expand();
            }

            // Move data
            //
            tst = m_off + m_cnt;
            while (idx < tst)
            {
                memcpy (&this->m_ptr[tst], &this->m_ptr[tst-1], sizeof (T));
                tst--;
            }
        }
        if (idx >= this->m_len)
            Expand();

        memcpy (&this->m_ptr[idx], v, sizeof (T));
        m_cnt++;
    }

    // Remove an element from the list. If the value of 'idx' is valid,
    // this method will remove the element from the given index.
    //
    bool Remove (const T* v, int idx = -1)
    {
        if (idx < 0)
            idx = Locate (v);

        if (idx >= 0 && idx < (m_off + m_cnt))
        {
            int l = (m_cnt + m_off - idx - 1) * sizeof (T);
            if (l > 0)
                memcpy (&this->m_ptr[idx], &this->m_ptr[idx + 1], l);
            m_cnt--;
            return true;
        }
        return false;
    }

    // Shared attributes
    //
protected:
    int m_cnt;  // Number of elements
    int m_off;  // Offset of the list
    int m_grn;  // Growth granularity

protected:
    // Comparison function
    //
    virtual int Compare (const T* v1, const T* v2) = 0;

private:
    // Expand array
    //
    void Expand()
    {
        int g = m_grn - 1;
        
        g = (max (m_grn, (this->m_len / 8)) + g) & ~g;
        GetPtr (this->m_len + g);
    }
};

// Handle encapsulation class
//
class CHandle
{
public:
    CHandle (HANDLE h = INVALID_HANDLE_VALUE) : m_hdl (h) {}
    virtual ~CHandle() {Close();}

    // Close handle
    //
    void Close()
    {
        if (IsValid())
        {
            ::CloseHandle (m_hdl);
            m_hdl = 0;
        }
    }

    // Cast operator
    //
    operator HANDLE() const {return m_hdl;}

    // Assign a handle
    //
    void operator = (HANDLE h) {m_hdl = h;}

    // Check if the handle is a valid handle or not
    //
    bool IsValid() {return (m_hdl && m_hdl != INVALID_HANDLE_VALUE);}

protected:
    HANDLE m_hdl;
};

// This class encapsulates a contiguous block of memory
//
class CMemory : public CPtr<BYTE>
{
public:
    // Convert OFFSET to pointer
    //
    inline void* ToPtr (DWORD off) const
    {
        if (off < (DWORD)this->m_len)
            return &this->m_ptr[off];
        return 0;
    }

    // Convert a pointer to offset
    //
    inline DWORD ToOffset (const void* ptr) const
    {
        if (IsPtr (ptr))
            return (DWORD)(((BYTE*)ptr) - this->m_ptr);
        return (DWORD)-1;
    }

    // Check if the pointer is a valid pointer within the memory block
    //
    inline bool IsPtr (const void* ptr) const
    {
        return (this->m_ptr <= ptr && 
                ptr < &this->m_ptr[this->m_len]);
    }

    // Commit a block of memory
    //
    virtual bool Commit (void* ptr, int len) {return true;}
};

#endif // __STDTMPL_H__

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
I have been writing code for a living for last three hundred years! I have written code in almost all the languages- C/C++, JAVA, C#, VB, Pascal, Delphi, JScript and so on.

Comments and Discussions