CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Oct 2001
    Posts
    745

    making buffer cyclic

    I have a Cyclic Buffer into which I have to put objects. Iam allocating bytes for the object first & then Putting the object into this memory later. please Look at the protected: members of the class to see what each variable is doing.
    The allocateBytes () Function is used to allocate memory for the object & GetObject() Function returns me the ptr to the object.
    I have a pointer to the beginning of the object(The write ptr),whenever a new object is placed in the buffer.

    As the object is split into different parts it is not written in one call to the The allocatebytes() function.
    The allocatebytes() gets called until the whole object is written.

    Now The problem is at some point the buffer reaches its end,(As it is a cyclic buffer)then the memory allocated for the object will be split between the end & beginning of the buffer.Then I wont be able to read the ptr to an object whose memory is split.
    So What I need is I want to extract the part of the memory allocated, which is put on the end of the buffer & put it to the beginning of the buffer.

    How Can I do it?
    Could anyone show it with a code snippet?

    The Cyclic Buffer class

    class CycleBufferublic Buffer
    {
    public:
    CycleBuffer(size_type bufferSize):Buffer(bufferSize)
    {
    m_pWrite = m_pBuffer;//m_pBuffer,Decalared in base class Buffer as protected member,the ptr to buffer.
    m_pRead = m_pBuffer;
    m_Counter = 0;
    m_BytesInBuffer = 0;
    m_Size = 0;

    }
    /*Here num is only part of the object put.allocateBytes should have to be called several times to
    put an object*/

    void * allocateBytes(size_type num)

    {
    unsigned int ulLengthToEnd = m_BufSize - (m_pWrite - m_pBuffer);
    if (ulLengthToEnd>= num)
    {
    m_pWrite += BytesToWrite;
    /*Calculating size of a single object which is put into the list*/
    m_Size += BytesToWrite;
    }

    m_BytesInBuffer += BytesToWrite;
    ReleaseLock();
    }

    /*This Function Increments the read ptr and the object is read from the buffer*/
    /* */
    void GetObject()
    {
    /* Getting The size of object put in the list*/
    list<unsigned int>::iterator it = m_DocSize.begin();
    unsigned int BytesToRead = *it;
    char * m_pNgElement = m_pRead;
    if (BytesToRead)
    {
    unsigned int ulLengthToEnd = m_bufferSize - (m_pRead - m_pBuffer);


    if ( ulLengthToEnd >= BytesToRead)
    {

    m_pRead = m_pBuffer + (((m_pRead + BytesToRead) - m_pBuffer) % m_bufferSize);
    }

    }
    m_BytesInBuffer -= BytesToRead;
    m_DocSize.pop_front();
    ReleaseLock();
    return m_pNgElement;
    //returning ptr to the object
    }

    void clear()
    {
    m_pFree = m_pBuffer;
    }
    }
    void ResetDocBytes()
    {
    m_Size = 0;
    }
    void SetDocBytes()
    {
    m_DocSize.push_back(m_Size);
    //return m_Size;

    }
    inline void SetCounter(int temp){ m_Counter = temp;}
    inline int GetCounter(){ return m_Counter;}


    protected:

    char* m_pWrite; // Write Ptr.
    char* m_pRead; // Read Ptr
    unsigned int m_BytesInBuffer; // Bytes in The Buffer
    int m_Counter;// Count of objects being put into the buffer.
    unsigned int m_Size;
    // Incremented till an object is written to the buffer & then when a new object starts,assigning it to 0;
    //To calculate the size of the object. As the object is split into different parts it is not written in one call to the The allocatebytes() function.
    //The allocatebytes() gets called until the whole object is written.

    list<unsigned int> m_DocSize;// List storing the size of each object.

    };



    Thanks in advance

  2. #2
    Join Date
    Jun 2002
    Location
    Letchworth, UK
    Posts
    1,020
    Add the following routine. Whenever you've fully allocated an object, call Relocate. I am assuming you have stored the buffer size somewhere (mBufferSize in example below).

    Code:
        /* Relocate from the back to the front
    
            From
            +-------------+
            |BBB| ... |AAA|
            +-------------+
    
            To
            +-------------+
            |AAABBB...    |
            +-------------+
    
        */
        int Relocate (int iStart, int iSize)
        {
            int result;
    
            // Do we need to relocate
            if ((iStart + iSize) < mBufferSize)
                result = iStart;
            else
            {
                // BBB from start to new location
                int src = 0;
                int dst = mBufferSize - iStart;
                int size = iStart + iSize - mBufferSize;
                memcpy (&mBuffer[dst], &mBuffer[src], size);
    
                // AAA from iStart to start of buffer
                src  = iStart;
                size = dst;
                dst  = 0;
                memcpy (&mBuffer[dst], &mBuffer[src], size);
                
                result = 0;
            }
            return result;
        }
    Alternative strategy if you have very small objects. It is great for fast comms: no end of buffer comparisons.

    This uses a cyclic buffer of 256 chars. The counters are unsigned chars so they will wrap when you hit 255.

    The user adds items in using Push and takes items out using Pop but does not access mBuffer directly.



    Code:
    class TrulyCyclic
    {
    public:
        unsigned char mBuffer[256];
        unsigned char mReadPosn;        // Must be unsigned chars otherwise it will not wrap
        unsigned char mWritePosn;
        
        TrulyCyclic ()
        :   mReadPosn (0)
        ,   mWritePosn (0)
        {
        }
    
        /*
            Usage:
    
            Single item
                unsigned char* start = 0;
                Push (item, &start, itemsize);
    
            Multiple items
                unsigned char* start = 0;
                Push (itemPart1, &start, itemPart1Size);
                Push (itemPart2, &start, itemPart2Size);
                ...
                Push (itemPartn, &start, itemPartnSize);
        */
        void Push (
            unsigned char* iObject,
            unsigned char** vObjectStart,
            unsigned char iObjectSize
        )
        {
            if (*vObjectStart == 0)
            {
                // Not formed yet.  Set the start position
                *vObjectStart = &mBuffer[mWritePosn];
                mBuffer[mWritePosn++] = 0;
            }
    
            // Must use for loop otherwise it will not wrap
            for (int i = 0; i < iObjectSize; i++)
                mBuffer[mWritePosn++] = iObject[i];
    
            // Increase the size
            unsigned char* oldsize = *vObjectStart;
            (*oldsize) += iObjectSize;
        }
    
        void Pop (
            unsigned char* oObject,
            unsigned char* oObjectSize
        )
        {
            *oObjectSize = mBuffer[mReadPosn++];
    
            // Must use for loop otherwise it will not wrap
            for (int i = 0; i < *oObjectSize; i++)
                oObject[i] = mBuffer[mReadPosn++];
        }
    };
    Succinct is verbose for terse

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured