Click here to Skip to main content
15,881,938 members
Articles / Desktop Programming / MFC

Template FIFO buffer using MFC synchronization

Rate me:
Please Sign up or sign in to vote.
4.90/5 (9 votes)
9 Sep 2009CPOL2 min read 35.2K   816   29   6
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:

C++
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:

C++
CTypedFifo<int> intFifo;

... 

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

intFifo.Write(seq, 5);

Later, when you need to read 3 of them:

C++
 ...

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Smart Soft
Bulgaria Bulgaria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionIt not work Pin
Carcan10-Apr-14 21:39
Carcan10-Apr-14 21:39 
GeneralMy vote of 5 Pin
blesschang14-Oct-10 15:58
blesschang14-Oct-10 15:58 
GeneralA problem with PulseEvent Pin
Nemanja Trifunovic10-Sep-09 6:05
Nemanja Trifunovic10-Sep-09 6:05 
GeneralRe: A problem with PulseEvent Pin
EmoBemo10-Sep-09 7:10
EmoBemo10-Sep-09 7:10 
GeneralRe: A problem with PulseEvent Pin
Rich Berlint14-Sep-09 19:43
Rich Berlint14-Sep-09 19:43 
GeneralRe: A problem with PulseEvent Pin
EmoBemo14-Sep-09 23:45
EmoBemo14-Sep-09 23:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.