条件锁和队列的使用

1 描述

  队列的基本操作包括队列的创建、取队列、放回队列,但是取队列还需加上等待时间、还有放入等待时间。队列的操作是一个典型的生产消费模型,相关的说明可以参考博客:(https://blog.csdn.net/Pro__rookie/article/details/87358814)。
  # 2 代码主要实现
	typedef struct statck_create_tag
	{
		int len;
		char name[128];
	}statck_create_t;
	
	typedef struct statck_create_obj_tag
	{
		int len;
		int cur_wr_site;
		int cur_re_site;
		int count;
		char name[128];
		void **statck_que;
		pthread_mutex_t lock;
		pthread_cond_t condPush;
		pthread_cond_t condPop;			
	}statck_create_obj_t;

	int Statck_Create(void **hd,statck_create_t param)
	{
		int ret = 0;
		statck_create_obj_t *pobj = NULL;
		pobj = (statck_create_obj_t *)malloc(sizeof(statck_create_obj_t ));
		if(!pobj)
			return -1;
		memset(pobj,0,sizeof(statck_create_obj_t ));
		pobj->len = param.len;
		assert(strlen(param.name) <= 128);
		snprintf(pobj->name,strlen(param.name)-1,"%s",param.name);
		
		pobj->statck_que = (void**)malloc(pobj->len*sizeof(void*));
		if(!pobj->statck_que)
			return -1;
		memset((void*)pobj->statck_que,0,pobj->len*sizeof(void*));

		ret = pthread_mutex_init(&pobj->lock,NULL);
		assert(0 == ret);

		ret = pthread_cond_init(&pobj->condPush,NULL);
		assert(0 == ret);

		ret = pthread_cond_init(&pobj->condPop,NULL);
		assert(0 == ret);
	
		*hd = pobj;
		return 0;
	}

	int Statck_push(void *hd,void *value,int time_out)
	{
		int ret = -1;
		struct timeval tv;
		struct timespec waitTime;
		statck_create_obj_t *pobj = (statck_create_obj_t *)hd;
		assert(NULL != pobj);

		pthread_mutex_lock(&pobj->lock);
		while(1)
		{
			if(pobj->count < pobj->len)
			{
				pobj->statck_que[pobj->cur_wr_site] = value;
				//pobj->cur_wr_site记录当前的位置,依次0 1 2 .... pobj->len-1 0 1 ....
				pobj->cur_wr_site = (pobj->cur_wr_site+1)%pobj->len;
				pobj->count++;
				//生产者,给pop发信号,已经存了数据,可以来取数据了
				pthread_cond_signal(&pobj->condPop);
				ret = 0;
				break;
			}else
			{
				if(TIME_OUT_NONE == time_out)
				{
					printf("push %s value %p fail\n",pobj->name,value);
					ret = -1;
					break;
				}else
				{
					if(TIME_OUT_FOREVER == time_out)
					{
						ret = pthread_cond_wait(&pobj->condPush,&pobj->lock);
						if(0 != ret)
						{
							printf("pthread_cond_wait failed,ret:%d\n",ret);
							break;
						}
					}else
					{
						memset(&tv,0,sizeof(sruct timeval));
						ret = gettimeofday(&tv,NULL);
						if(0 == ret)
						{
							memset(&waitTime,0,sizeof(struct timespec));
							waitTime.tv_sec = (long)time_out/1000;
							waitTime.tv_nsec = ((long)time_out%1000)*1000000;
							waitTime.tv_sec += tv.tv_sec;
							waitTime.tv_nsec += tv.tv_usec*1000;
							if(waitTime.tv_nsec >= 1000000000)
							{
								waitTime.tv_sec += 1;
								waitTime.tv_nsec %= 1000000000;
							}
							/*tv_nsec 此值有范围限制的,就是不能超过1秒即1000000000纳秒。如果超出1秒,就要在tv_sec 此值增加一秒;tv_nsec 减去一秒。如果tv_nsec 此值溢出,调用pthread_cond_timedwait函数,会立马返回。*/
							//pthread_cond_timedwait中的waitTime需要绝对时间,所以要先取到当前时间
							ret = pthread_cond_timedwait(&pobj->condPush,&pobj->lock,&waitTime);
							if(ETIMEDOUT == ret)
							{
								ret = ETIMEDOUT;
								break;
							}else
							{
								printf("pthread_cond_timedwait failed %d\n",ret);
								break;
							}
						}
					}
				}
			}
		}
		pthread_mutex_unlock(&pobj->lock);
		return ret;
	}

int Statck_pop(void *hd,void **value,int time_out)
{
	int ret = -1;
	struct timeval tv;
	struct timespec waitTime;
	statck_create_obj_t *pobj = (statck_create_obj_t *)hd;
	assert(NULL != pobj);

	pthread_mutex_lock(&pobj->lock);
	while(1)
	{
		if(pobj->count > 0)
		{
			*value = (void*)pobj->statck_que[pobj->cur_re_site];
			pobj->cur_re_site = (pobj->cur_re_site+1)%pobj->len;
			pobj->count--;
			pthread_cond_signal(&pobj->condPush);
			ret = 0;
			break;
		}else
		{
			if(TIME_OUT_FOREVER == time_out)
			{
				ret = pthread_cond_wait(&pobj->condPop,&pobj->lock);
				if(0 != ret)
				{
					printf("pthread_cond_wait failed,ret:%d\n",ret);
					break;
				}
		     }else
			{
				memset(&tv,0,sizeof(sruct timeval));
				ret = gettimeofday(&tv,NULL);
				if(0 == ret)
				{
					memset(&waitTime,0,sizeof(struct timespec));
					waitTime.tv_sec = (long)time_out/1000;
					waitTime.tv_nsec = ((long)time_out%1000)*1000000;
					waitTime.tv_sec += tv.tv_sec;
					waitTime.tv_nsec += tv.tv_usec*1000;
					if(waitTime.tv_nsec >= 1000000000)
					{
						waitTime.tv_sec += 1;
						waitTime.tv_nsec %= 1000000000;
					}
					ret = pthread_cond_timedwait(&pobj->condPop,&pobj->lock,&waitTime);
					if(ETIMEDOUT == ret)
					{
						ret = ETIMEDOUT;
						break;
					}else
					{
						printf("pthread_cond_timedwait failed %d\n",ret);
						break;
					}
				}
			}			
		}
	}
		pthread_mutex_unlock(&pobj->lock);
		return ret;
}

int main(int argv,char **argc)
{
	int ret = 0 , i = 0  , que_size = 10;
	void *hd = NULL;
	statck_create_t param;
	
	param.len = que_size;
	snprintf(param.name,128,"que_test");
	ret = Statck_Create(&hd,param);
	assert(0 == ret);
	
	for(i = 0 ; i < que_size ; i++)
	{
		int *value = (int*)malloc(sizeof(int));
		*value = i;
		ret = Statck_push(hd,value,TIME_OUT_NONE);
	}
	for(i = 0 ; i < que_size ; i++)
	{
		int *pop_value = NULL;
		ret = Statck_pop(hd,(void**)pop_value,TIME_OUT_NONE);
		if(pop_value)
			printf("pop_value = %d\n",*pop_value);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值