缓冲区同步读写

程序设计中经常用到缓冲队列,多个写入线程,多个读取线程,同时操作一个缓冲队列,需要信号量和互斥量等进行同步。

#pragma once

#define TVUP_API

#ifdef _WIN32
#include <windows.h>
typedef HANDLE ThreadHandle;
typedef HANDLE MutexHandle;
typedef HANDLE Semaphore;
typedef struct
{
	HANDLE      handle;
} Event;
#else  /* not _WIN32 */
#include <pthread.h>
#include <semaphore.h>
typedef pthread_t       ThreadHandle;
typedef pthread_mutex_t MutexHandle;
typedef pthread_cond_t  CondHandle;
typedef sem_t           Semaphore;
typedef struct
{
	MutexHandle     mutex;
	CondHandle      cond;
	int             state;
} Event;
#endif  /* not _WIN32 */

typedef void *          (* ThreadFunction) (void *);

TVUP_API
int dfsThreadCreate( ThreadHandle *pThread, ThreadFunction func, void *pArg );

TVUP_API
int dfsThreadJoin( ThreadHandle thread );

TVUP_API
int dfsThreadMutexInit( MutexHandle *pMutex );

TVUP_API
int dfsThreadMutexDestroy( MutexHandle *pMutex );

TVUP_API
int dfsThreadMutexLock( MutexHandle *pMutex );

TVUP_API
int dfsThreadMutexUnlock( MutexHandle *pMutex );

TVUP_API
int dfsEventInit( Event *pEvent, int state );

TVUP_API
int dfsEventSet( Event *pEvent );

TVUP_API
int dfsEventWait( Event *pEvent, int timeoutUSecs );

TVUP_API
void dfsEventDestroy( Event *pEvent );

TVUP_API
int dfsSemInit( Semaphore * pSem, int initVal);

TVUP_API
int dfsSemSet( Semaphore * pSem );

TVUP_API
int dfsSemWait( Semaphore * pSem, int timeoutMills);

TVUP_API
int dfsSemDestroy( Semaphore * pSem );

#include <list>

typedef void * DataT;

class CRWBuffer
{
public:
	enum {MaxBufferLength = 100000,};
public:
	CRWBuffer(int nMaxBufLen);
	virtual ~CRWBuffer(void);

	int ReadBuf( DataT * pBuf);
	int WriteBuf(const DataT * pBuf);

	int WaitForReadable(int timeoutMSec);
	int WaitForWritable(int timeoutMSec);
public:
	std::list<DataT> m_Buflist;

	Semaphore m_semReadable;
	Semaphore m_semWritable;
	MutexHandle m_Mutex;
};




#include "RWBuffer.h"

CRWBuffer::CRWBuffer(int nMaxBufLen)
{
	dfsThreadMutexInit(&m_Mutex);
	dfsSemInit(&m_semReadable, 0);
	dfsSemInit(&m_semWritable, nMaxBufLen);
}

CRWBuffer::~CRWBuffer(void)
{
	dfsSemDestroy(&m_semWritable);
	dfsSemDestroy(&m_semReadable);
	dfsThreadMutexDestroy(&m_Mutex);
}

int CRWBuffer::WaitForReadable(int timeoutMSec)
{
	return dfsSemWait(&m_semReadable, timeoutMSec);
}

int CRWBuffer::WaitForWritable(int timeoutMSec)
{
	return dfsSemWait(&m_semWritable, timeoutMSec);
}

int CRWBuffer::ReadBuf(DataT * pBuf)
{
	dfsThreadMutexLock(&m_Mutex);
	*pBuf = m_Buflist.front();
	m_Buflist.pop_front();
	dfsThreadMutexUnlock(&m_Mutex);
	dfsSemSet(&m_semWritable);
	return 0;
}

int CRWBuffer::WriteBuf(const DataT * pBuf)
{
	dfsThreadMutexLock(&m_Mutex);
	m_Buflist.push_back(*pBuf);
	dfsThreadMutexUnlock(&m_Mutex);
	dfsSemSet(&m_semReadable);
	return 0;
}

#ifdef WIN32
int dfsThreadCreate( ThreadHandle *pThread, ThreadFunction func, void *pArg )
{
	*pThread = CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)func, pArg, 0, 0 );
	if ( *pThread == 0 )
		return 1;
	return 0;
}

int dfsThreadJoin( ThreadHandle thread )
{
	WaitForSingleObject( thread, INFINITE );
	CloseHandle(thread);
	return 0;
}

int dfsThreadMutexInit( MutexHandle *pMutex )
{
	BOOL        bInitialOwner = FALSE;
	LPCTSTR     lpName = 0;
	*pMutex = CreateMutex( 0, bInitialOwner, lpName );
	if ( *pMutex == 0 )
		return 1;
	return 0;
}

int dfsThreadMutexDestroy( MutexHandle *pMutex )
{
	CloseHandle( pMutex );
	return 0;
}

int dfsThreadMutexLock( MutexHandle *pMutex )
{
	if ( WaitForSingleObject( *pMutex, INFINITE ) )
		return 1;
	return 0;
}

int dfsThreadMutexUnlock( MutexHandle *pMutex )
{
	if ( !ReleaseMutex( *pMutex ) )
		return 1;
	return 0;
}


int dfsEventInit( Event *pEvent, int state )
{
	pEvent->handle = CreateEvent( NULL, FALSE, state ? TRUE : FALSE, NULL );
	if ( pEvent->handle == 0 )
		return 1;
	return 0;
}

int dfsEventSet( Event *pEvent )
{
	BOOL    retVal;
	retVal = SetEvent( pEvent->handle );
	if ( !retVal )
		return 1;
	return 0;
}

int dfsEventWait( Event *pEvent, int timeoutMSecs )
{
	DWORD   retVal = WaitForSingleObject( pEvent->handle, timeoutMSecs );
	if ( retVal != WAIT_OBJECT_0 )
		return 0;
	return 1;
}

void dfsEventDestroy( Event *pEvent )
{
	CloseHandle( pEvent->handle );
}

int dfsSemInit( Semaphore * pSem , int initVal)
{
	*pSem = CreateSemaphoreA(NULL, initVal, 100000, NULL);
	return 0;
}

int dfsSemSet( Semaphore * pSem )
{
	if (!ReleaseSemaphore(*pSem, 1, NULL))
		return 1;
	return 0;
}

int dfsSemWait( Semaphore * pSem, int timeoutMills)
{
	int rc = WaitForSingleObject(*pSem, timeoutMills);
	if (rc != WAIT_OBJECT_0)
		return 1;
	return 0;
}

int dfsSemDestroy( Semaphore * pSem )
{
	if (!CloseHandle(*pSem))
		return 1;
	return 0;
}

#else

int dfsThreadCreate( ThreadHandle *pThread, ThreadFunction func, void *pArg )
{
	return pthread_create( pThread, 0, func, pArg ); 
}

int dfsThreadJoin( ThreadHandle thread )
{
	return pthread_join( thread, NULL );
}


int dfsThreadMutexInit( MutexHandle *pMutex )
{
	return pthread_mutex_init( pMutex, NULL );
}

int dfsThreadMutexDestroy( MutexHandle *pMutex )
{
	return pthread_mutex_destroy( pMutex );
}

int dfsThreadMutexLock( MutexHandle *pMutex )
{
	return pthread_mutex_lock( pMutex );
}

int dfsThreadMutexUnlock( MutexHandle *pMutex )
{
	return pthread_mutex_unlock( pMutex );
}


int dfsEventInit( Event *pEvent, int state )
{
	pthread_mutex_init( &(pEvent->mutex), NULL );
	pthread_cond_init( &(pEvent->cond), NULL );
	pEvent->state = state;

	return 0;
}

int dfsEventSet( Event *pEvent )
{
	pthread_mutex_lock( &(pEvent->mutex) );

	if ( !(pEvent->state) )
	{
		pEvent->state = 1;
		pthread_cond_signal( &(pEvent->cond) );
	}

	pthread_mutex_unlock( &(pEvent->mutex) );

	return 0;
}

int dfsEventWait( Event *pEvent, int timeoutMSecs )
{
	int             retVal = 0;       /* (if the event's already set, we'll return without making any calls) */
	struct timeval  curTime;
	struct timespec absTimeout;

	pthread_mutex_lock( &(pEvent->mutex) );

	if ( timeoutMSecs <= 0 )
	{
		retVal = 0;
		while ( !(pEvent->state) && (retVal == 0) )
			retVal = pthread_cond_wait( &(pEvent->cond), &(pEvent->mutex) );

		pEvent->state = 0; /* auto-reset */
	}
	else
	{
		gettimeofday( &curTime, NULL );
		curTime.tv_sec  += timeoutMSecs / 1000;
		curTime.tv_usec += (timeoutMSecs % 1000) * 1000;
		if ( curTime.tv_usec >= 1000000 )
		{
			curTime.tv_usec -= 1000000;
			curTime.tv_sec  += 1;
		}

		absTimeout.tv_sec = curTime.tv_sec;
		absTimeout.tv_nsec = curTime.tv_usec * 1000;

		retVal = 0;
		while ( !(pEvent->state) && (retVal == 0) )
			retVal = pthread_cond_timedwait( &(pEvent->cond), &(pEvent->mutex), &absTimeout );

		pEvent->state = 0; /* auto-reset */
	}

	pthread_mutex_unlock(&(pEvent->mutex) );

	/* Coerce the expeted DFPort "error" into a DFStream "error".
	*/
	if ( retVal == ETIMEDOUT )
		retVal = 1;

	return retVal;
}

void dfsEventDestroy( Event *pEvent )
{
	pthread_mutex_destroy( &(pEvent->mutex) );
	pthread_cond_destroy( &(pEvent->cond) );
}

int dfsSemInit( Semaphore * pSem , int initVal)
{
	sem_init(pSem, 0, initVal);
	return 0;
}

int dfsSemSet( Semaphore * pSem )
{
	sem_post(pSem);
	return 0;
}

int dfsSemWait( Semaphore * pSem, int timeoutMills)
{
	struct timespec interval = {time(NULL), timeoutMills * 1000000};
	int rc = sem_timedwait(pSem, &interval);
	if (rc == 0)
		return 0;
	if (rc == -1 && errno == ETIMEDOUT)
		return 1;
	return errno;
}

int dfsSemDestroy( Semaphore * pSem )
{
	sem_destroy(pSem);
	return 0;
}

#endif


#include "RWBuffer.h"

void * ReadFunction(void * args)
{
	CRWBuffer * pBuffer = (CRWBuffer *)args;
	while (1)
	{
		if (WAIT_OBJECT_0 == pBuffer->WaitForReadable(1000))
		{
			DataT data;
			pBuffer->ReadBuf(&data);
			Sleep(2000);
		}
		else
		{
			printf("Wait for readable\n");
		}
	}
}

void * WriteFunction(void * args)
{
	CRWBuffer * pBuffer = (CRWBuffer *)args;
	while(1)
	{
		if (WAIT_OBJECT_0 == pBuffer->WaitForWritable(1000))
		{
			DataT data;
			pBuffer->WriteBuf(&data);
			Sleep(10);
		}
		else
		{
			printf("Wait for writable\n");
		}
	}
}

int main(int argc, char * argv [])
{

	CRWBuffer * pBuffer = new CRWBuffer(1000);

	ThreadHandle t1, t2, t3;

	dfsThreadCreate(&t1, ReadFunction, pBuffer);
	dfsThreadCreate(&t2, ReadFunction, pBuffer);

	dfsThreadCreate(&t3, WriteFunction, pBuffer);

	getchar();
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值