c语言中没有队列,所以利用双向链表来实现FIFO,删除头部节点,在尾部插入。由于是链表,所以节点需要我们自己分配,但是为了避免重复的分配,我们分配好队列长度的内存池,在栈里或堆里,连续的node数组,当出队列时我们就将将其释放回内存池,需要时从内存池分配一个节点。
需求:
用来计算最近1次,5次,30次等的平均速率,我们用队列,来实现,当计算平均速率时只需从尾部遍历,计算各时刻的平均速率。
看代码:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
#define MAX_SPEED_SENCOND 60
int write_len = 0;
void* write_thread(void* arg);
struct list_node{
int use;
int value;
struct list_node *next;
struct list_node *prev;
};
struct list_node list_buf[MAX_SPEED_SENCOND];
struct list_node *tail;
struct list_node *head;
int list_len = 0;
struct list_node* get_pool_node(struct list_node* list_buf)
{
if (list_buf == NULL)
{
printf("get_pool_node: NULL Pointert!!!\n");
return NULL;
}
for (int i = 0; i < MAX_SPEED_SENCOND; i++)
{
if (list_buf[i].use == 0)
{
return &list_buf[i];
}
}
printf("not find node in pool");
return NULL;
};
void enqueue(int speed_1s)
{
if (list_len >= MAX_SPEED_SENCOND)
{
head->use = 0;
head = head->next;
head->prev = NULL;
list_len -=1;
}
struct list_node* list_tmp = get_pool_node((struct list_node*)list_buf);
if (list_tmp == NULL)
{
printf("NULL list_tmp.....\n");
return ;
}
list_tmp->value = speed_1s;
if (list_len == 0)
{
tail = head = list_tmp;
list_tmp->next = NULL;
list_tmp->prev = NULL;
list_tmp->use = 1;
}
else
{
tail->next = list_tmp;
list_tmp->prev = tail;
list_tmp->next = NULL;
list_tmp->use = 1;
tail = list_tmp;
}
list_len++;
}
int main()
{
int ret = 0;
pthread_t wr_tid = 0;
int times = 0;
int wr_len_last = 0;
int wr_speed = 0;
memset(list_buf, 0, sizeof(list_buf));
ret = pthread_create(&wr_tid, NULL, write_thread, NULL);
if (ret != 0)
{
printf("create thread failed!\n");
goto exit;
}
int idx = 0;
int tmp_sum = 0;
struct list_node* tmp_itr = NULL;
while(1)
{
sleep(1);
wr_speed = write_len - wr_len_last;
wr_len_last = write_len;
enqueue(wr_speed);
printf("\n################times %d##################\n", times);
tmp_sum = 0;
tmp_itr = tail;
idx=0;
while (tmp_itr != NULL)
{
tmp_sum += tmp_itr->value;
switch (++idx)
{
case 1:
case 5:
case 10:
case 30:
case 60:
printf("%dS: %d KB/s\n", idx, tmp_sum/idx/1024);
break;
default:
break;
}
tmp_itr=tmp_itr->prev;
}
fflush(stdout);
times++;
}
pthread_join(wr_tid, NULL);
exit:
close(fd);
return ret;
}
void* write_thread(void* arg)
{
int ret = 0;
int len = 0;
srand((unsigned) (time(NULL)));
while(1)
{
len = rand() % TEST_BUF_SIZE;
usleep(100000); /*simulate write*/
write_len += len;
}
return NULL;
}