blob: 95754b339f9ff35aa35481a8b7d286f5baeb7ff9 [file] [log] [blame]
/*
* Copyright (C) 2021 Amlogic Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Description: fifo implementation for single reader single writer
* Author: song.zhao@amlogic.com
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdatomic.h>
#include "aml_avsync.h"
#include "aml_queue.h"
struct queue {
int max_len;
int ri; //read index
int wi; //write index
atomic_intptr_t *items;
};
void* create_q(int max_len)
{
struct queue *q;
if (max_len <= 0) {
printf("%s %d invalid max_len:%d\n",
__func__, __LINE__, max_len);
return NULL;
}
q = (struct queue*)calloc(1, sizeof(*q));
if (!q) {
printf("%s %d OOM\n", __func__, __LINE__);
return NULL;
}
q->items = (atomic_intptr_t *)calloc(max_len, sizeof(void *));
if (!q->items) {
printf("%s %d OOM\n", __func__, __LINE__);
free(q);
return NULL;
}
q->max_len = max_len;
q->ri = q->wi = 0;
return q;
}
void destroy_q(void * queue)
{
struct queue *q = queue;
if (!q)
return;
free(q->items);
free(q);
}
int queue_item(void *queue, void * item)
{
struct queue *q = queue;
int fullness;
if (!q)
return -1;
fullness = q->wi - q->ri;
if (fullness < 0) fullness += q->max_len;
if (fullness >= q->max_len - 1)
return -1; // not enough space
atomic_store(&q->items[q->wi], (atomic_intptr_t)item);
if (q->wi >= q->max_len - 1)
q->wi = 0;
else
q->wi++;
return 0;
}
int peek_item(void *queue, void** p_item, uint32_t cnt)
{
struct queue *q = queue;
int32_t index;
int fullness;
if (!q)
return -1;
fullness = q->wi - q->ri;
if (fullness < 0) fullness += q->max_len;
if (fullness == 0 || fullness <= cnt)
return -1; //no enough to peek
index = q->ri;
index += cnt;
if (index >= q->max_len)
index -= q->max_len;
*p_item = (void *)atomic_load(&q->items[index]);
if (*p_item != NULL)
return 0;
else
return -1;
}
int dqueue_item(void *queue, void** p_item)
{
struct queue *q = queue;
int fullness;
if (!q)
return -1;
fullness = q->wi - q->ri;
if (fullness < 0) fullness += q->max_len;
if (fullness == 0)
return -1; //empty
*p_item = (void *)atomic_load(&q->items[q->ri]);
q->items[q->ri] = 0;
if (q->ri >= q->max_len - 1)
q->ri = 0;
else
q->ri++;
return 0;
}
int queue_size(void *queue)
{
struct queue *q = queue;
int fullness;
if (!q)
return -1;
fullness = q->wi - q->ri;
if (fullness < 0) fullness += q->max_len;
return fullness;
}