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 = (pobj->cur_wr_site+1)%pobj->len;
pobj->count++;
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;
}
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;
}