#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; \ \ DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool); \ DE_INLINE int TYPENAME##_getNumElements (const TYPENAME* heap) DE_UNUSED_FUNCTION; \ DE_INLINE deBool TYPENAME##_reserve (TYPENAME* heap, int capacity) DE_UNUSED_FUNCTION; \ DE_INLINE void TYPENAME##_reset (TYPENAME* heap) DE_UNUSED_FUNCTION; \ DE_INLINE void TYPENAME##_moveDown (TYPENAME* heap, int ndx) DE_UNUSED_FUNCTION; \ DE_INLINE void TYPENAME##_moveUp (TYPENAME* heap, int ndx) DE_UNUSED_FUNCTION; \ DE_INLINE deBool TYPENAME##_push (TYPENAME* heap, VALUETYPE elem) DE_UNUSED_FUNCTION; \ DE_INLINE VALUETYPE TYPENAME##_popMin (TYPENAME* heap) DE_UNUSED_FUNCTION; \ \ DE_INLINE TYPENAME* TYPENAME##_create (deMemPool* pool) \ { \ 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 (TYPENAME* heap, int capacity) \ { \ return TYPENAME##Array_reserve(heap->array, capacity); \ } \ \ DE_INLINE void TYPENAME##_reset (TYPENAME* heap) \ { \ TYPENAME##Array_setSize(heap->array, 0); \ } \ \ DE_INLINE void TYPENAME##_moveDown (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 (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 (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 (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##Dummy_s { int dummy; } #endif /* _DEPOOLHEAP_H */