113 lines
2.3 KiB
C++
113 lines
2.3 KiB
C++
|
|
#include <pthread.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
|
||
|
|
#include "packet_io.h"
|
||
|
|
#include "packet_utils.h"
|
||
|
|
#include "packet_queue.h"
|
||
|
|
|
||
|
|
struct packet_queue
|
||
|
|
{
|
||
|
|
pthread_mutex_t lock;
|
||
|
|
struct packet **queue;
|
||
|
|
uint32_t size;
|
||
|
|
uint32_t head;
|
||
|
|
uint32_t tail;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct packet_queue *packet_queue_create(uint32_t size)
|
||
|
|
{
|
||
|
|
struct packet_queue *queue = (struct packet_queue *)calloc(1, sizeof(struct packet_queue));
|
||
|
|
if (queue == NULL)
|
||
|
|
{
|
||
|
|
PACKET_IO_LOG_ERROR("unable to alloc packet queue");
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
queue->queue = (struct packet **)calloc(size, sizeof(struct packet *));
|
||
|
|
if (queue->queue == NULL)
|
||
|
|
{
|
||
|
|
PACKET_IO_LOG_ERROR("unable to alloc packet queue buffer");
|
||
|
|
free(queue);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
queue->size = size;
|
||
|
|
queue->head = 0;
|
||
|
|
queue->tail = 0;
|
||
|
|
pthread_mutex_init(&queue->lock, NULL);
|
||
|
|
|
||
|
|
return queue;
|
||
|
|
}
|
||
|
|
|
||
|
|
void packet_queue_destory(struct packet_queue *queue)
|
||
|
|
{
|
||
|
|
if (queue == NULL)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
struct packet *pkt = NULL;
|
||
|
|
while (1)
|
||
|
|
{
|
||
|
|
packet_queue_pop(queue, &pkt);
|
||
|
|
if (pkt == NULL)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
packet_free(pkt);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (queue->queue)
|
||
|
|
{
|
||
|
|
free(queue->queue);
|
||
|
|
queue->queue = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
pthread_mutex_destroy(&queue->lock);
|
||
|
|
|
||
|
|
free(queue);
|
||
|
|
}
|
||
|
|
|
||
|
|
int packet_queue_is_full(struct packet_queue *queue)
|
||
|
|
{
|
||
|
|
return (queue->tail + 1) % queue->size == queue->head;
|
||
|
|
}
|
||
|
|
|
||
|
|
int packet_queue_is_empty(struct packet_queue *queue)
|
||
|
|
{
|
||
|
|
return queue->head == queue->tail;
|
||
|
|
}
|
||
|
|
|
||
|
|
void packet_queue_push(struct packet_queue *queue, struct packet *pkt)
|
||
|
|
{
|
||
|
|
retry:
|
||
|
|
pthread_mutex_lock(&queue->lock);
|
||
|
|
if (packet_queue_is_full(queue))
|
||
|
|
{
|
||
|
|
PACKET_IO_LOG_ERROR("packet queue is full, retry later");
|
||
|
|
pthread_mutex_unlock(&queue->lock);
|
||
|
|
sleep(1);
|
||
|
|
goto retry;
|
||
|
|
}
|
||
|
|
|
||
|
|
queue->queue[queue->tail] = pkt;
|
||
|
|
queue->tail = (queue->tail + 1) % queue->size;
|
||
|
|
pthread_mutex_unlock(&queue->lock);
|
||
|
|
}
|
||
|
|
|
||
|
|
void packet_queue_pop(struct packet_queue *queue, struct packet **pkt)
|
||
|
|
{
|
||
|
|
pthread_mutex_lock(&queue->lock);
|
||
|
|
if (packet_queue_is_empty(queue))
|
||
|
|
{
|
||
|
|
pthread_mutex_unlock(&queue->lock);
|
||
|
|
*pkt = NULL;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
*pkt = queue->queue[queue->head];
|
||
|
|
queue->head = (queue->head + 1) % queue->size;
|
||
|
|
pthread_mutex_unlock(&queue->lock);
|
||
|
|
}
|