Click to See Complete Forum and Search --> : making buffer cyclic


Kohinoor24
June 26th, 2002, 09:14 AM
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 CycleBuffer:public 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

cup
June 26th, 2002, 12:22 PM
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).


/* 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.




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++];
}
};