日期:2014-05-16  浏览次数:20720 次

拥有线程安全和阻塞功能的vector类SemVector(LINUX平台)

这是我自己写的一个拥有线程安全和阻塞功能的vector类SemVector(LINUX平台),欢迎大家使用

//semvector.h
#ifndef SEMVECTOR_H_
#define SEMVECTOR_H_

#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>

template<class T>
class SemVector
{
private:
	T *m_Array;						//存储数据的向量
	int m_Size;						//向量的最大长度,-1时则没限制	
	int m_MaxSize;
	pthread_mutex_t m_Mutex;		//互斥锁	
	sem_t m_Empty;
	sem_t m_Stored;

public:
	SemVector(int size);
	~SemVector();
	//向vector尾部加入数据,若向量满了,则用条件变量等待
	void PushBack(const T &elem);
	//向vector尾部删除数据,若向量为空,则用条件变量等待
	T PopBack();

	//返回元素
	T At(int i);
	//返回数组的长度
	int Size() { return m_Size; }
	//返回数组是否为空
	bool Empty() { return ( 0 == m_Size ); }
	//返回数组的最大长度
	int GetMaxSize() { return m_MaxSize; }
};


template<class T>
SemVector<T>::SemVector(int size)
{
	m_MaxSize = size;
	m_Size = 0;
	m_Array = new T[size];

	pthread_mutex_init(&m_Mutex, NULL);
	sem_init(&m_Empty, 0, size);
	sem_init(&m_Stored, 0, 0);
}

template<class T>
SemVector<T>::~SemVector()
{
	delete m_Array;
	pthread_mutex_destroy(&m_Mutex);
	sem_destroy(&m_Empty);
	sem_destroy(&m_Stored);
}

template<class T>
void SemVector<T>::PushBack(const T &elem)
{
	sem_wait(&m_Empty);
	pthread_mutex_lock(&m_Mutex);
	m_Array[m_Size++] = elem;
#ifdef PRINT_DEBUG
	printf("push: %d, size: %d, thread: %lu\n", elem, m_Size-1, 
		(unsigned long)pthread_self());
#endif
	pthread_mutex_unlock(&m_Mutex);
	sem_post(&m_Stored);
}

template<class T>
T SemVector<T>::PopBack()
{
	T res;
	sem_wait(&m_Stored);
	pthread_mutex_lock(&m_Mutex);
	res = m_Array[--m_Size];
#ifdef PRINT_DEBUG
	printf("pop : %d, size: %d, thread: %lu\n", res, m_Size, 
		(unsigned long)pthread_self());
#endif
	pthread_mutex_unlock(&m_Mutex);
	sem_post(&m_Empty);
	return res;
}

template<class T>
T SemVector<T>::At(int i)
{
	T res;
	pthread_mutex_unlock(&m_Mutex);
	if( i < m_Size )
		res = m_Array[i];
	pthread_mutex_unlock(&m_Mutex);
	return res;
}

#endif

以下是测试例子:
//测试例子
#define PRINT_DEBUG

#include "semvector.h"

SemVector<int> g_tvec(10);
int g_value = 1;
const int TCOUNT = 100;

//生产者线程
void *Producer(void *arg)
{
	while(1)
	{
		g_tvec.PushBack(g_value++);
	}
}

//消费者线程
void *Customer(void *arg)
{
	while(1)
	{
		g_tvec.PopBack();
	}
}

//主函数
int main()
{
	pthread_t proid[TCOUNT], cusid[TCOUNT];
	//产生10个生产者和10个消费者
	for(int i=0; i<TCOUNT; i++)
	{
		pthread_create(&proid[i], NULL, Producer, NULL);
		pthread_create(&cusid[i], NULL, Customer, NULL);
	}
	for(int i=0; i<TCOUNT; i++)
	{
		pthread_join(proid[i], NULL);
		pthread_join(cusid[i], NULL);
	}
	return 0;
}