今天笔试的时候遇到一个唤醒缓冲区问题,然后当时很多函数名都不记得了,所以写的不好,回来后写了下。
环形缓冲区实现的时候可以用数组实现,一个读和写的index,实现的时候要如何判断空间已满?空?
方法1:废弃一个缓冲空间不用,当写指针+1等于读指针的时候(意思是写指针多跑一圈快要赶上读指针),此时表明空间已满。
方法2:维护一个变量记录缓冲区使用大小,当大小等于缓冲区大小,则为满;当大小为0时为空。
环形缓冲区多用于多线程缓冲。相对于队列,它的优点是不必新增与释放空间,所有空间重复利用,只需维护两个指针。
多线程环境,在多线程的环境下,要使用环形缓冲区,要互斥的访问,基本上和生产者、消费者模型相似,下面给出一个简单的实现。
#include <iostream>
#include <Windows.h>
#include <process.h>
using namespace std;
class CRingBuffer
{
public:
CRingBuffer();
~CRingBuffer();
int read();
bool write(int data);
private:
static const int MAX_SIZE = 100;
int buffer[MAX_SIZE];
HANDLE sem_empty;
HANDLE sem_full;
HANDLE mutex;
//int size;
int wIndex;
int rIndex;
inline int addRing(int index)
{
return (index + 1 ) == MAX_SIZE ? 0 : (index + 1);
}
};
CRingBuffer::CRingBuffer()
{
sem_empty = CreateSemaphore( NULL, MAX_SIZE, MAX_SIZE, NULL );
sem_full = CreateSemaphore( NULL, 0, MAX_SIZE, NULL );
mutex = CreateMutex( NULL, false, NULL );
wIndex = rIndex = 0;
}
CRingBuffer::~CRingBuffer()
{
CloseHandle(sem_empty);
CloseHandle(sem_full);
CloseHandle(mutex);
}
int CRingBuffer::read()
{
WaitForSingleObject( sem_full, INFINITE );
WaitForSingleObject( mutex, INFINITE );
int data = buffer[rIndex];
rIndex = addRing(rIndex);
ReleaseMutex( mutex );
ReleaseSemaphore( sem_empty, 1, NULL);
return data;
}
bool CRingBuffer::write( int data )
{
WaitForSingleObject( sem_empty, INFINITE );
WaitForSingleObject( mutex, INFINITE );
buffer[wIndex] = data;
wIndex = addRing(wIndex);
ReleaseMutex( mutex );
ReleaseSemaphore( sem_full, 1, NULL);
return true;
}
CRingBuffer ringBuff;
CRITICAL_SECTION g_hthread;
unsigned int __stdcall consumer(void *pPM)
{
for ( int i=0; i<2000; ++i )
{
int data = ringBuff.read();
EnterCriticalSection(&g_hthread);
cout<<"===consumer read "<<data<<endl;
LeaveCriticalSection(&g_hthread);
}
return 0;
}
unsigned int __stdcall producer(void *pPM)
{
for ( int i=0; i<1000; ++i )
{
ringBuff.write(i);
EnterCriticalSection(&g_hthread);
cout<<"producer write "<<i<<endl;
LeaveCriticalSection(&g_hthread);
}
return 0;
}
int main()
{
#define THREADNUM 3
HANDLE handle[THREADNUM];
InitializeCriticalSection(&g_hthread);
handle[0] = (HANDLE)_beginthreadex(NULL, 0, consumer, NULL, 0, NULL);
handle[1] = (HANDLE)_beginthreadex(NULL, 0, producer, NULL, 0, NULL);
handle[2] = (HANDLE)_beginthreadex(NULL, 0, producer, NULL, 0, NULL);
WaitForMultipleObjects(THREADNUM, handle, TRUE, INFINITE);
for ( int i=0; i<THREADNUM; ++i )
CloseHandle(handle[i]);
DeleteCriticalSection(&g_hthread);
}
环形缓冲区
最新推荐文章于 2024-01-07 00:12:18 发布