| #ifndef UIMA_LOWLEVEL_HEAP_HPP |
| #define UIMA_LOWLEVEL_HEAP_HPP |
| /** \file lowlevel_heap.hpp . |
| ----------------------------------------------------------------------------- |
| |
| |
| |
| |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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: Base Heap design. 32-bit heaps used for interop |
| |
| ----------------------------------------------------------------------------- |
| |
| |
| -------------------------------------------------------------------------- */ |
| |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Include dependencies */ |
| /* ----------------------------------------------------------------------- */ |
| #include "uima/pragmas.hpp" |
| |
| #include "uima/lowlevel_typedefs.hpp" |
| |
| #include "uima/macros.h" |
| |
| #include <vector> |
| |
| #if defined( _MSC_VER ) |
| #pragma warning( push ) |
| #pragma warning( disable : 4311 ) |
| #pragma warning( disable : 4312 ) |
| #endif |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Constants */ |
| /* ----------------------------------------------------------------------- */ |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Forward declarations */ |
| /* ----------------------------------------------------------------------- */ |
| namespace uima { |
| namespace internal { |
| class CASSerializer; |
| class CASDeserializer; |
| } |
| } |
| /* ----------------------------------------------------------------------- */ |
| /* Types / Classes */ |
| /* ----------------------------------------------------------------------- */ |
| |
| namespace uima { |
| namespace lowlevel { |
| namespace internal { |
| |
| /** |
| * Generic implementation of a possibly segmented heap of cells of type T. |
| * Used in uima::lowlevel::FSHeap for the FS heap, the StringRef Heap, |
| * and the String heap. T must be an integral type. |
| */ |
| template <class T> |
| class UIMA_LINK_IMPORTSPEC Heap { |
| friend class uima::internal::CASSerializer; |
| friend class uima::internal::CASDeserializer; |
| #if defined(__GNUC__) && (__GNUC__ < 3) |
| //Older GNU compiler can't handle friend properly so we make public |
| public: |
| #else |
| private: |
| #endif |
| // start of the current heap segment |
| T* iv_pTHeap; |
| // current top of heap |
| T* iv_pTTopOfHeap; |
| // end of current allocated heap segment |
| T* iv_pTLastHeapCell; |
| // all starts of all used segments so far (most recently allocated first) |
| std::vector<T*> iv_vecUsedSegments; |
| // all ends of all used segments so far (most recently allocated first) |
| std::vector<T*> iv_vecUsedSegmentEnds; |
| // all tops of all used segments so far (most recently allocated first) |
| std::vector<T*> iv_vecUsedSegmentTops; |
| |
| // next available cell on heap |
| WORD32 iv_topOfHeap; |
| // segment size |
| WORD32 iv_uiCellNumber; |
| // default value of the heap cells |
| int iv_iDefaultValue; |
| |
| #ifdef BYEBYEPTRS |
| /** |
| * returns -1 if t lies in the current heap, an index >=0 into |
| * usedSegments, if t resides there, or -2 if t could not be found at all. |
| */ |
| int searchIndex(T* t) const { |
| if ( (t >= iv_pTHeap) && (t < iv_pTTopOfHeap) ) { |
| return -1; |
| } |
| WORD32 i; |
| for (i=0; i<iv_vecUsedSegments.size(); ++i) { |
| if ( (t>=iv_vecUsedSegments[i]) && (t< iv_vecUsedSegmentEnds[i] ) ) { |
| return(int) i; |
| } |
| } |
| return -2; |
| } |
| #endif |
| |
| public: |
| Heap(WORD32 cells, int value) |
| : iv_pTHeap(NULL), |
| iv_pTTopOfHeap(NULL), |
| iv_pTLastHeapCell(NULL), |
| iv_uiCellNumber(cells), |
| iv_iDefaultValue(value) { |
| iv_pTHeap = new T[iv_uiCellNumber]; |
| iv_topOfHeap = 1; // leave 0th cell empty |
| memset(iv_pTHeap, iv_iDefaultValue, (iv_uiCellNumber * sizeof(T)) ); |
| } |
| |
| |
| ~Heap() { |
| if (iv_pTHeap != NULL) { |
| assert( EXISTS(iv_pTHeap) ); |
| delete[] iv_pTHeap; |
| } |
| iv_pTHeap = NULL; |
| } |
| |
| |
| bool debugIsValidHeapCell(TyFS cell) const { |
| if ( cell < 1 || cell >= iv_topOfHeap ) { |
| return false; |
| } |
| return true; |
| } |
| |
| T* getHeapStart() const { |
| return iv_pTHeap; |
| } |
| WORD32 getTopOfHeap() const { |
| return iv_topOfHeap; |
| } |
| WORD32 getLastHeapCell() const { |
| return iv_uiCellNumber; |
| } |
| |
| T getHeapValue(TyFS tyFS) const { |
| return iv_pTHeap[tyFS]; |
| } |
| |
| void setHeapValue(TyFS tyFS, T t) { |
| iv_pTHeap[tyFS] = t; |
| } |
| |
| |
| /** |
| * reserve n more heap cells; if necessary, increase heap size |
| */ |
| int increaseHeap(WORD32 n) { |
| //assert( n > 0 ); |
| int result = iv_topOfHeap; |
| iv_topOfHeap += n; |
| |
| // usual case, just return |
| if ( iv_topOfHeap < iv_uiCellNumber ) { |
| return result; |
| } |
| |
| // calculate new heap size to be at least double current size |
| if ( n > iv_uiCellNumber ) { |
| iv_uiCellNumber += n; |
| } else { |
| iv_uiCellNumber *= 2; |
| } |
| T* iv_pTHeapNew = new T[iv_uiCellNumber]; |
| assert( iv_pTHeapNew != NULL ); |
| memcpy(iv_pTHeapNew, iv_pTHeap, result*sizeof(T)); |
| memset(iv_pTHeapNew + result, iv_iDefaultValue, (iv_uiCellNumber - result)*sizeof(T)); |
| delete[] iv_pTHeap; |
| iv_pTHeap = iv_pTHeapNew; |
| return result; |
| } |
| |
| /** |
| * reset this heap. Paint over used cells. |
| */ |
| void reset() { |
| UIMA_TPRINT("resetting heap"); |
| if ( iv_topOfHeap == 1 ) { |
| // nothing to be done |
| return; |
| } |
| // !TODO don't need to fill all heaps with default value????? |
| memset(iv_pTHeap, iv_iDefaultValue, iv_topOfHeap * sizeof(T) ); |
| iv_topOfHeap = 1; |
| UIMA_TPRINT(" heap reset'd"); |
| } |
| |
| bool resides(TyFS t) const { |
| return debugIsValidHeapCell(t); |
| } |
| |
| #ifdef BYEBYEPTRS |
| WORD32 getPageSize() const { |
| return iv_uiCellNumber; |
| } |
| |
| WORD32 getSegmentNumber() const { |
| assert( iv_vecUsedSegments.size() == iv_vecUsedSegmentEnds.size() ); |
| return iv_vecUsedSegmentEnds.size() + 1; |
| } |
| |
| /** |
| * method used during serialization. |
| * sets the output parameter to a vector of pairs of pointers to |
| * the start and end, respectively, of the used heap segments |
| * in the order they were allocated. |
| */ |
| void getHeapSegments( vector<pair<T*, T*> >& rvecResult ) const { |
| assert( iv_vecUsedSegments.size() == iv_vecUsedSegmentEnds.size() ); |
| WORD32 uiSegmentNum = iv_vecUsedSegmentEnds.size() + 1; |
| rvecResult.resize(uiSegmentNum); |
| if (uiSegmentNum == 1) { |
| rvecResult[0] = pair<T*, T*>(iv_pTHeap, iv_pTTopOfHeap); |
| return; |
| } |
| // fill result from back to front |
| rvecResult[uiSegmentNum-1] = pair<T*, T*>(iv_pTHeap, iv_pTTopOfHeap); |
| int i; |
| for (i=uiSegmentNum-2; i>=1; --i) { |
| rvecResult[i] = pair<T*, T*>(iv_vecUsedSegments[i], iv_vecUsedSegmentEnds[i]); |
| } |
| assert( i == 0 ); |
| rvecResult[0] = pair<T*, T*>(iv_vecUsedSegments[0], iv_vecUsedSegmentEnds[0]); |
| } |
| |
| /** |
| * method used during DEserialization. |
| * sets the output parameter to a vector of pairs of pointers to |
| * the start and TOP, respectively, of the used heap segments |
| * in the order they were allocated. |
| */ |
| void getHeapSegmentBounds( vector<pair<T*, T*> >& rvecResult ) const { |
| assert( iv_vecUsedSegments.size() == iv_vecUsedSegmentEnds.size() ); |
| WORD32 uiSegmentNum = iv_vecUsedSegmentEnds.size() + 1; |
| rvecResult.resize(uiSegmentNum); |
| if (uiSegmentNum == 1) { |
| rvecResult[0] = pair<T*, T*>(iv_pTHeap, iv_pTLastHeapCell); |
| return; |
| } |
| // fill result from back to front |
| rvecResult[uiSegmentNum-1] = pair<T*, T*>(iv_pTHeap, iv_pTLastHeapCell); |
| int i; |
| for (i=uiSegmentNum-2; i>=1; --i) { |
| rvecResult[i] = pair<T*, T*>(iv_vecUsedSegments[i], iv_vecUsedSegmentTops[i]); |
| } |
| assert( i == 0 ); |
| rvecResult[0] = pair<T*, T*>(iv_vecUsedSegments[0], iv_vecUsedSegmentTops[0]); |
| } |
| |
| /** |
| * get a unique ID for a pointer into the heap. |
| */ |
| ptrdiff_t getUniqueID(T const * t) const { |
| if (iv_vecUsedSegmentEnds.size() == 0) { |
| if ( (t > iv_pTHeap) && (t < iv_pTTopOfHeap) ) { |
| return(t - iv_pTHeap); |
| } |
| } else { |
| // if in the first allocated segment |
| if ( (t>iv_vecUsedSegments[0]) && (t< iv_vecUsedSegmentEnds[0] ) ) { |
| return(t - iv_vecUsedSegments[0]); |
| } |
| // keep absolute number of heap cells |
| WORD32 uiAbsoluteHeapCellNum = iv_vecUsedSegmentEnds[0] - iv_vecUsedSegments[0]; |
| WORD32 i; |
| WORD32 len = iv_vecUsedSegments.size(); |
| // for each allocated heap segment |
| for (i=1; i<len; ++i) { |
| T* segmentStart = iv_vecUsedSegments[i]; |
| T* segmentEnd = iv_vecUsedSegmentEnds[i]; |
| if ( (t>segmentStart) && (t< segmentEnd ) ) { |
| return uiAbsoluteHeapCellNum - 1 + (t - segmentStart); |
| } |
| uiAbsoluteHeapCellNum += (segmentEnd - segmentStart) - 1; |
| } |
| // if in the current (most recently allocated) heap segment |
| if ( (t > iv_pTHeap) && (t < iv_pTTopOfHeap) ) { |
| return uiAbsoluteHeapCellNum + (t - iv_pTHeap) - 1; |
| } |
| } |
| // if we arrived here, something went wrong |
| assert(false); |
| return -1; |
| } |
| #endif |
| }; |
| |
| } |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- */ |
| /* Implementation */ |
| /* ----------------------------------------------------------------------- */ |
| |
| |
| /* ----------------------------------------------------------------------- */ |
| |
| #if defined( _MSC_VER ) |
| #pragma warning( pop ) |
| #endif |
| |
| #endif |
| |