169 lines
5.7 KiB
C
169 lines
5.7 KiB
C
|
#ifndef _DEPOOLHEAP_H
|
||
|
#define _DEPOOLHEAP_H
|
||
|
/*-------------------------------------------------------------------------
|
||
|
* drawElements Memory Pool Library
|
||
|
* --------------------------------
|
||
|
*
|
||
|
* Copyright 2014 The Android Open Source Project
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
*//*!
|
||
|
* \file
|
||
|
* \brief Memory pool heap class.
|
||
|
*//*--------------------------------------------------------------------*/
|
||
|
|
||
|
#include "deDefs.h"
|
||
|
#include "deMemPool.h"
|
||
|
#include "dePoolArray.h"
|
||
|
|
||
|
DE_BEGIN_EXTERN_C
|
||
|
|
||
|
void dePoolHeap_selfTest (void);
|
||
|
|
||
|
DE_END_EXTERN_C
|
||
|
|
||
|
/*--------------------------------------------------------------------*//*!
|
||
|
* \brief Declare a template pool heap class.
|
||
|
* \param TYPENAME Type name of the declared heap.
|
||
|
* \param VALUETYPE Type of the value contained in the heap.
|
||
|
* \param CMPFUNC Comparison function of two elements returning (-1, 0, +1).
|
||
|
*
|
||
|
* This macro declares a pool heap with all the necessary functions for
|
||
|
* operating with it. All allocated memory is taken from the memory pool
|
||
|
* given to the constructor.
|
||
|
*
|
||
|
* The functions for operating the heap are:
|
||
|
*
|
||
|
* \code
|
||
|
* Heap* Heap_create (deMemPool* pool);
|
||
|
* int Heap_getNumElements (const Heap* heap);
|
||
|
* deBool Heap_reserve (Heap* heap, int size);
|
||
|
* void Heap_reset (Heap* heap);
|
||
|
* deBool Heap_push (Heap* heap, Element elem);
|
||
|
* Element Heap_popMin (Heap* heap);
|
||
|
* \endcode
|
||
|
*//*--------------------------------------------------------------------*/
|
||
|
#define DE_DECLARE_POOL_HEAP(TYPENAME, VALUETYPE, CMPFUNC) \
|
||
|
\
|
||
|
DE_DECLARE_POOL_ARRAY(TYPENAME##Array, VALUETYPE); \
|
||
|
\
|
||
|
typedef struct TYPENAME##_s \
|
||
|
{ \
|
||
|
TYPENAME##Array* array; \
|
||
|
} TYPENAME; /* NOLINT(TYPENAME) */ \
|
||
|
\
|
||
|
DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool); \
|
||
|
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* heap) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE deBool TYPENAME##_reserve (DE_PTR_TYPE(TYPENAME) heap, int capacity) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE void TYPENAME##_reset (DE_PTR_TYPE(TYPENAME) heap) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE void TYPENAME##_moveDown (DE_PTR_TYPE(TYPENAME) heap, int ndx) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE void TYPENAME##_moveUp (DE_PTR_TYPE(TYPENAME) heap, int ndx) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE deBool TYPENAME##_push (DE_PTR_TYPE(TYPENAME) heap, VALUETYPE elem) DE_UNUSED_FUNCTION; \
|
||
|
DE_INLINE VALUETYPE TYPENAME##_popMin (DE_PTR_TYPE(TYPENAME) heap) DE_UNUSED_FUNCTION; \
|
||
|
\
|
||
|
DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool) \
|
||
|
{ \
|
||
|
DE_PTR_TYPE(TYPENAME) heap = DE_POOL_NEW(pool, TYPENAME); \
|
||
|
if (!heap) \
|
||
|
return DE_NULL; \
|
||
|
heap->array = TYPENAME##Array_create(pool); \
|
||
|
if (!heap->array) \
|
||
|
return DE_NULL; \
|
||
|
return heap; \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* heap) \
|
||
|
{ \
|
||
|
return TYPENAME##Array_getNumElements(heap->array); \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE deBool TYPENAME##_reserve (DE_PTR_TYPE(TYPENAME) heap, int capacity) \
|
||
|
{ \
|
||
|
return TYPENAME##Array_reserve(heap->array, capacity); \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE void TYPENAME##_reset (DE_PTR_TYPE(TYPENAME) heap) \
|
||
|
{ \
|
||
|
TYPENAME##Array_setSize(heap->array, 0); \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE void TYPENAME##_moveDown (DE_PTR_TYPE(TYPENAME) heap, int ndx) \
|
||
|
{ \
|
||
|
TYPENAME##Array* array = heap->array; \
|
||
|
int numElements = TYPENAME##Array_getNumElements(array); \
|
||
|
for (;;) \
|
||
|
{ \
|
||
|
int childNdx0 = 2*ndx + 1; \
|
||
|
if (childNdx0 < numElements) \
|
||
|
{ \
|
||
|
int childNdx1 = deMin32(childNdx0 + 1, numElements - 1); \
|
||
|
int childCmpRes = CMPFUNC(TYPENAME##Array_get(array, childNdx0), TYPENAME##Array_get(array, childNdx1)); \
|
||
|
int minChildNdx = (childCmpRes == 1) ? childNdx1 : childNdx0; \
|
||
|
int cmpRes = CMPFUNC(TYPENAME##Array_get(array, ndx), TYPENAME##Array_get(array, minChildNdx)); \
|
||
|
if (cmpRes == 1) \
|
||
|
{ \
|
||
|
TYPENAME##Array_swap(array, ndx, minChildNdx); \
|
||
|
ndx = minChildNdx; \
|
||
|
} \
|
||
|
else \
|
||
|
break; \
|
||
|
} \
|
||
|
else \
|
||
|
break; \
|
||
|
} \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE void TYPENAME##_moveUp (DE_PTR_TYPE(TYPENAME) heap, int ndx) \
|
||
|
{ \
|
||
|
TYPENAME##Array* array = heap->array; \
|
||
|
while (ndx > 0) \
|
||
|
{ \
|
||
|
int parentNdx = (ndx-1) >> 1; \
|
||
|
int cmpRes = CMPFUNC(TYPENAME##Array_get(array, ndx), TYPENAME##Array_get(array, parentNdx)); \
|
||
|
if (cmpRes == -1) \
|
||
|
{ \
|
||
|
TYPENAME##Array_swap(array, ndx, parentNdx); \
|
||
|
ndx = parentNdx; \
|
||
|
} \
|
||
|
else \
|
||
|
break; \
|
||
|
} \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE deBool TYPENAME##_push (DE_PTR_TYPE(TYPENAME) heap, VALUETYPE elem) \
|
||
|
{ \
|
||
|
TYPENAME##Array* array = heap->array; \
|
||
|
int numElements = TYPENAME##Array_getNumElements(array); \
|
||
|
if (!TYPENAME##Array_setSize(array, numElements + 1)) \
|
||
|
return DE_FALSE; \
|
||
|
TYPENAME##Array_set(array, numElements, elem); \
|
||
|
TYPENAME##_moveUp(heap, numElements); \
|
||
|
return DE_TRUE; \
|
||
|
} \
|
||
|
\
|
||
|
DE_INLINE VALUETYPE TYPENAME##_popMin (DE_PTR_TYPE(TYPENAME) heap) \
|
||
|
{ \
|
||
|
TYPENAME##Array* array = heap->array; \
|
||
|
VALUETYPE tmp = TYPENAME##Array_get(array, 0); \
|
||
|
int numElements = TYPENAME##Array_getNumElements(array); \
|
||
|
TYPENAME##Array_set(array, 0, TYPENAME##Array_get(array, numElements-1)); \
|
||
|
TYPENAME##Array_setSize(array, numElements-1); \
|
||
|
TYPENAME##_moveDown(heap, 0); \
|
||
|
return tmp; \
|
||
|
} \
|
||
|
\
|
||
|
struct TYPENAME##Unused_s { int unused; }
|
||
|
|
||
|
#endif /* _DEPOOLHEAP_H */
|