缓冲区同步读写

来源:互联网 发布:女生旅游攻略 知乎 编辑:程序博客网 时间:2024/04/20 10:39

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

#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_APIint dfsThreadCreate( ThreadHandle *pThread, ThreadFunction func, void *pArg );TVUP_APIint dfsThreadJoin( ThreadHandle thread );TVUP_APIint dfsThreadMutexInit( MutexHandle *pMutex );TVUP_APIint dfsThreadMutexDestroy( MutexHandle *pMutex );TVUP_APIint dfsThreadMutexLock( MutexHandle *pMutex );TVUP_APIint dfsThreadMutexUnlock( MutexHandle *pMutex );TVUP_APIint dfsEventInit( Event *pEvent, int state );TVUP_APIint dfsEventSet( Event *pEvent );TVUP_APIint dfsEventWait( Event *pEvent, int timeoutUSecs );TVUP_APIvoid dfsEventDestroy( Event *pEvent );TVUP_APIint dfsSemInit( Semaphore * pSem, int initVal);TVUP_APIint dfsSemSet( Semaphore * pSem );TVUP_APIint dfsSemWait( Semaphore * pSem, int timeoutMills);TVUP_APIint 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 WIN32int 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;}#elseint 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;}