Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Template FIFO buffer using MFC synchronization

0.00/5 (No votes)
9 Sep 2009 1  
A simple template FIFO buffer. Pulses event when new data is added to the back of the FIFO.

Introduction

Sometimes when we pass data from one module to another, we face the problem with the quants. The 'receiver' object needs portions of X bytes of data but the 'sender' can only provide Y byte portions. So the 'sender' can't pass data directly to the 'receiver'.

There is another case. The 'receiver' needs data at an exact time (like CD/DVD burning device) but the 'sender' doesn't care.

So here, we need a FIFO buffer. FIFO stands for First-In - First-Out. The first data written to the buffer is the first data to be read and then removed. Then, the 'receiver' reads as much data as it likes (of course, if there is enough in the FIFO) and reads it whenever it likes after it has been written.

CTypedFifo is a simple template class providing the functionality of a FIFO buffer and it's intended for storing any kind of object. It also has the ability to synchronize with other objects. This class pretends to be thread-safe.

Using the code

Here is the CTypedFifo class declaration:

template <typename T>
class CTypedFifo
{
private:
    T * m_pW; // write pointer
    T * m_pR; // read pointer
    T * m_pBuf; // start address of the buffer
    T * m_pEnd; // end address of the buffer
    CCriticalSection m_cs; // sinchronicity
    CEvent m_eNewData; // pulsed when a write operation was performed
public:
    CTypedFifo();
    CTypedFifo(const UINT nCnt);
    ~CTypedFifo();

    BOOL Init(const UINT nCnt);
    BOOL Realloc(const UINT nCnt);
    void Free();

    // returns the count of the elements in the fifo
    int GetCount(); 

    // returns the maximum number of elements that can fit into the buffer
    int GetCapacity();

    int Read(T * pBuf, UINT nCnt);    
    void Write(const T * pBuf, UINT nCnt);
    void Drain(const UINT nCnt);
    DWORD WaitForNewData(DWORD dwMilliseconds = INFINITE);
    HANDLE GetNewDataEventHandle() const {return m_eNewData.m_hObject;}
private:
    int _Read(T * pBuf, UINT nCnt);
    int _GetCount() const;
    void _Drain(const UINT nCnt);
};

First, when you construct a CTypedFifo object, you need to specify its capacity. This is the maximum amount of objects which can be stored in the buffer (not the size in bytes). If you use the default constructor, then you must call Init(const UINT nCnt) before any Read or Write calls.

You can change the capacity of the buffer at anytime by calling Realloc(const UINT nCnt). The data stored in the buffer won't be lost.

You can retrieve the count of elements stored by calling GetCount(), and if you have 'forgotten' the capacity of the buffer, you can get it using GetCapacity().

For example, if you want to write a sequence of 5 ints to the buffer, the following code will do the job:

CTypedFifo<int> intFifo;

... 

int seq[] = { 1, 3, 5, 7, 9 };

intFifo.Write(seq, 5);

Later, when you need to read 3 of them:

 ...

int read_seq[3];
int read_one;

intFifo.Read(read_seq, 3);
intFifo.Read(&read_one, 1);

So now, in read_seq, we have the numbers { 1, 3, 5 }, and in read_one, 7. Only one element is left in the FIFO buffer: 9.

If you don't need some of the data in the buffer anymore, you can simply call Drain() and it will vanish. In order to prevent memory leaks, be sure if you store pointers in the FIFO to delete the objects they point to.

If there is no data in the FIFO, you can wait for new data using the WaitForNewData(DWORD dwMilliseconds = INFINITE) method. It will lock the calling thread until the time interval in dwMilliseconds elapses or another thread has written new data to the buffer.

When you need to wait for multiple objects, you can get a handle of an event object by calling GetNewDataEventHandle() and using it in the WaitForSingleObject or WaitForMultipleObjects APIs.

That's all. I hope you enjoy it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here