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

182 lines
4.1 KiB
C
Raw Normal View History

2018-07-13 01:31:50 +00:00
/*
* 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;
/*
*<EFBFBD>Ȱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>entity֮<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>next<EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD><EFBFBD>
*/
}
while (!CdxAtomicBoolCAS(&impl->front, entity, entity->next));
QueueNodeEntityDecRef(impl->pool, entity); /*<2A><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>ȡentity<74><79>ʱ<EFBFBD><CAB1>+1*/
QueueNodeEntityDecRef(impl->pool, entity); /*<2A><>-1 <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>*/
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);/*<2A><>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD>Ϊ0<CEAA><30>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 ;
}