SmartAudio/package/allwinner/liballwinner_tina/liballwinner/LIBRARY/DEMUX/BASE/CdxQueue.c

182 lines
4.1 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
* All rights reserved.
*
* File : CdxQueue.c
* Description : Queue
* History :
*
*/
#include <CdxTypes.h>
#include <CdxAtomic.h>
#include <CdxMemory.h>
//#include <CdxBaseErrno.h>
#include <CdxLog.h>
#include <CdxQueue.h>
#define CdxAtomicBoolCAS(ptr, oldVal, newVal) \
__sync_bool_compare_and_swap(ptr, oldVal, newVal)
struct CdxQueueImplS
{
struct CdxQueueS base;
struct CdxQueueNodeEntityS *front;
struct CdxQueueNodeEntityS *rear;
cdx_bool enablePop;
cdx_bool enablePush;
AwPoolT *pool;
};
struct CdxQueueNodeEntityS
{
struct CdxQueueNodeEntityS *next;
cdx_atomic_t ref;
CdxQueueDataT data;
};
static inline struct CdxQueueNodeEntityS *
QueueNodeEntityIncRef(struct CdxQueueNodeEntityS *entity)
{
CdxAtomicInc(&entity->ref);
return entity;
}
static inline cdx_void QueueNodeEntityDecRef(AwPoolT *pool, struct CdxQueueNodeEntityS *entity)
{
if (CdxAtomicDec(&entity->ref) == 0)
{
Pfree(pool, entity);
}
}
static CdxQueueDataT __CdxQueuePop(CdxQueueT *queue)
{
struct CdxQueueImplS *impl;
struct CdxQueueNodeEntityS *entity = NULL;
CdxQueueDataT data;
CDX_CHECK(queue);
impl = CdxContainerOf(queue, struct CdxQueueImplS, base);
if (!impl->enablePop)
{
return NULL;
}
do
{
if (entity)
{
QueueNodeEntityDecRef(impl->pool, entity);
}
entity = QueueNodeEntityIncRef(impl->front);
if (entity->next == NULL) /* it's only a dummy node */
{
QueueNodeEntityDecRef(impl->pool, entity);
return NULL;
}
data = entity->next->data;
/*
*先把数据保存下来,
*避免取到entity之后它的next被释放了
*/
}
while (!CdxAtomicBoolCAS(&impl->front, entity, entity->next));
QueueNodeEntityDecRef(impl->pool, entity); /*对应上面取entity的时候+1*/
QueueNodeEntityDecRef(impl->pool, entity); /*再-1 才能释放内存*/
return data;
}
static cdx_err __CdxQueuePush(CdxQueueT *queue, CdxQueueDataT data)
{
struct CdxQueueImplS *impl;
struct CdxQueueNodeEntityS *entity, *tmpEntity;
cdx_bool ret;
CDX_CHECK(queue);
impl = CdxContainerOf(queue, struct CdxQueueImplS, base);
if (!impl->enablePush)
{
return -1;
}
entity = Palloc(impl->pool, sizeof(*entity));
CDX_FORCE_CHECK(entity);
CDX_CHECK(data);/*不希望有为0的data*/
entity->data = data;
entity->next = NULL;
CdxAtomicSet(&entity->ref, 1);
do
{
tmpEntity = impl->rear;
}
while (!CdxAtomicBoolCAS(&tmpEntity->next, NULL, entity));
ret = CdxAtomicBoolCAS(&impl->rear, tmpEntity, entity);
CDX_CHECK(CDX_TRUE == ret);
return CDX_SUCCESS;
}
static cdx_bool __CdxQueueEmpty(CdxQueueT *queue)
{
struct CdxQueueImplS *impl;
CDX_CHECK(queue);
impl = CdxContainerOf(queue, struct CdxQueueImplS, base);
return impl->front == impl->rear;
}
static struct CdxQueueOpsS gQueueOps =
{
.pop = __CdxQueuePop,
.push = __CdxQueuePush,
.empty = __CdxQueueEmpty
};
CdxQueueT *CdxQueueCreate(AwPoolT *pool)
{
struct CdxQueueImplS *impl;
struct CdxQueueNodeEntityS *dummy;
impl = Palloc(pool, sizeof(struct CdxQueueImplS));
CDX_FORCE_CHECK(impl);
memset(impl, 0x00, sizeof(struct CdxQueueImplS));
impl->pool = pool;
dummy = Palloc(impl->pool, sizeof(struct CdxQueueNodeEntityS));
CDX_FORCE_CHECK(dummy);
dummy->next = NULL;
dummy->data = NULL;
CdxAtomicSet(&dummy->ref, 1);
impl->front = dummy;
impl->rear = dummy;
impl->base.ops = &gQueueOps;
impl->enablePop = CDX_TRUE;
impl->enablePush = CDX_TRUE;
return &impl->base;
}
cdx_void CdxQueueDestroy(CdxQueueT *queue)
{
struct CdxQueueImplS *impl;
// struct CdxQueueNodeEntityS *dummy;
CDX_CHECK(queue);
impl = CdxContainerOf(queue, struct CdxQueueImplS, base);
impl->enablePush = CDX_FALSE;
impl->enablePop = CDX_FALSE;
CDX_LOG_CHECK(impl->front == impl->rear, "queue not empty");
QueueNodeEntityDecRef(impl->pool, impl->front);
Pfree(impl->pool, impl);
return ;
}