Main Page   Class Hierarchy   Compound List   File List   Compound Members  

sparingStack.h

00001 /****************************************************
00002  *  Bachelor Project:                               *
00003  *  External Memory Minimum Spanning Trees          *
00004  *  by Dominik Schultes <mail@dominik-schultes.de>  *
00005  *                                                  *
00006  *                sparingStack.h                    *
00007  *                                                  *
00008  *  May 15, 2003                                    *
00009  ****************************************************/
00010 
00011 
00012 #ifndef SPARINGSTACK_H
00013 #define SPARINGSTACK_H
00014 
00020 template <typename value_type, int elementsPerBlock, int noOfBlocks>
00021 class CommonPoolOfBlocks
00022 {
00023  public:
00027     class Block
00028     {
00029      public:
00031         Block()
00032             : _size( 0 ), _prev( 0 )
00033             {}
00034 
00039         void push(const value_type &element) {
00040             _elements[_size++] = element;
00041         }
00042 
00047         const value_type & top() const {return _elements[_size-1];}
00048 
00053         void pop() {_size--;}
00054 
00058         void clear() {_size = 0;}
00059 
00061         bool empty() const {return (_size==0);}
00062 
00064         bool full() const {return (_size==elementsPerBlock);}
00065 
00067         int size() const {return _size;}
00068 
00070         const value_type & operator[](int index) const {return _elements[index];}
00071 
00073         void setPrevBlock(Block *const prev) {_prev = prev;}
00074 
00076         Block * prevBlock() const {return _prev;}
00077         
00078      private:
00080         int _size;
00081 
00083         Block *_prev;
00084 
00086         value_type _elements[elementsPerBlock];
00087     };
00088     
00089 
00091     CommonPoolOfBlocks()
00092         : _free( &_blocks[noOfBlocks-1] ), _reserveMemory( 0 ),
00093           _totalNoOfBlocks( noOfBlocks ), _noOfFreeBlocks( noOfBlocks )
00094         {
00095             // initialize the linked list of free blocks
00096             for (int i=noOfBlocks-1; i>0; i--)
00097                 _blocks[i].setPrevBlock(&_blocks[i-1]);
00098         }
00099 
00104     ~CommonPoolOfBlocks() {
00105         for (int i=0; i<_additionalBlocks.size(); i++) {
00106             delete[] _additionalBlocks[i];
00107             DS_VERBOSE1( std::cout << std::endl
00108                          << "CommonPoolOfBlocks::~CommonPoolOfBlocks(): "
00109                          << "additionally created blocks deleted." << std::endl );
00110         }
00111     }
00112 
00114     Block * request() {
00115         
00116         if ( ! _free ) { // If there are no more free blocks...
00117             // check if reserve memory is available
00118             int noOfNewBlocks = _reserveMemory / sizeof( Block );
00119             if (noOfNewBlocks == 0) {
00120                 // If there is not enough reserve memory, the program is aborted !
00121                 std::cerr << "CommonPoolOfBlocks: request(): No free blocks available !"
00122                           << std::endl;
00123                 abort();
00124             }
00125 
00126             DS_VERBOSE1( std::cout << std::endl << "CommonPoolOfBlocks::request(): "
00127                          << noOfNewBlocks << " new blocks created." << std::endl );
00128 
00129             // allocate new blocks according to the available reserve memory
00130             _reserveMemory -= noOfNewBlocks * sizeof( Block );
00131             
00132             DS_LOGGING2( _totalNoOfBlocks += noOfNewBlocks;
00133                          _noOfFreeBlocks += noOfNewBlocks );
00134 
00135             Block *newBlocks = new Block[noOfNewBlocks];
00136             _additionalBlocks.push_back( newBlocks );
00137             for (int i=0; i<noOfNewBlocks; i++) {
00138                 newBlocks[i].setPrevBlock( _free );
00139                 _free = &newBlocks[i];
00140             }
00141         }
00142         
00143         DS_LOGGING2( _noOfFreeBlocks-- );
00144 
00145         // return a free block
00146         Block *block = _free;
00147         _free = _free->prevBlock();
00148         return block;
00149     }
00150 
00152     void release(Block *block) {
00153         block->setPrevBlock(_free);
00154         _free = block;
00155 
00156         DS_LOGGING2( _noOfFreeBlocks++ );
00157     }
00158 
00164     void increaseReserveMemory(int newMemory) {
00165         _reserveMemory += newMemory;
00166     }
00167 
00168     
00169     DS_LOGGING2(
00171         int noOfBlocksUsed() const {return _totalNoOfBlocks - _noOfFreeBlocks;}
00172         
00174         int noOfBlocksFree() const {return _noOfFreeBlocks;}
00175     )
00176         
00177  private:
00179     Block _blocks[noOfBlocks];
00180 
00182     Block *_free;
00183 
00188     int _reserveMemory;
00189 
00190     std::vector<Block*> _additionalBlocks;
00191     
00197     int _totalNoOfBlocks;
00198     
00200     int _noOfFreeBlocks;
00201     
00202 };
00203 
00204 
00209 template <typename value_type, int elementsPerBlock, int noOfBlocks>
00210 class SparingStack
00211 {
00212  protected:
00214     typedef CommonPoolOfBlocks<value_type, elementsPerBlock, noOfBlocks> Pool;
00216     typedef Pool::Block Block;
00217     
00218  public:
00220     SparingStack() : _top( &_bottom ) {}
00221 
00223     ~SparingStack() {
00224         while (_top != &_bottom) {
00225             Block *oldBlock = _top;
00226             _top = _top->prevBlock();
00227             oldBlock->clear();
00228             _pool->release(oldBlock);
00229         }
00230     }
00231 
00237     void setPool(Pool *pool) {_pool = pool;}
00238 
00240     bool empty() const {return _top->empty();}
00241 
00243     void push(const value_type &element) {
00244         if ( _top->full() ) {
00245             // If the current block is full, request a new one.
00246             Block *newBlock = _pool->request();
00247             newBlock->setPrevBlock(_top);
00248             _top = newBlock;
00249         }
00250         _top->push(element);
00251     }
00252 
00254     const value_type & top() const {return _top->top();}
00255 
00257     void pop() {
00258         _top->pop();
00259         if ( (_top->empty()) && (_top != &_bottom) ) {
00260             // If the current block is now empty, release it.
00261             // (The 'bottom' block belongs to the stack and is never released.)
00262             Block *oldBlock = _top;
00263             _top = _top->prevBlock();
00264             _pool->release(oldBlock);
00265         }
00266     }
00267 
00269     int size() const {
00270         Block *current = _top;
00271         int blockCounter = 0;
00272         while (current != &_bottom) {
00273             blockCounter++;
00274             current = current->prevBlock();
00275         }
00276         return _top->size() + (blockCounter * DS_INT_EDGES_PER_BLOCK);
00277     }
00278     
00279  protected:
00281     Pool *_pool;
00282 
00284     Block *_top;
00285 
00287     Block _bottom;  
00288 };
00289 
00290 
00294 template <int elementsPerBlock, int noOfBlocks>
00295 class REWS_SparingStack : public SparingStack<RelabeledEdgeWithoutSource,
00296                                               elementsPerBlock,
00297                                               noOfBlocks>
00298 {
00299  public:
00307     NodeID determineMinEdge(MST &result) const {
00308         // determine the edge with minimum weight
00309         RelabeledEdgeWithoutSource minEdge = top();
00310         Block *current = _top;
00311         while (true) {
00312             for (int index=current->size()-1; index >= 0; index--) {
00313                 if ( (*current)[index] < minEdge ) minEdge = (*current)[index]; 
00314             }
00315             if (current == &_bottom) break;
00316             current = current->prevBlock();
00317         }
00318 
00319         // Add the edge with minimum weight incident to the
00320         // current node to the resulting minimum spanning tree.
00321         result.add( minEdge );
00322                 
00323         DS_VERBOSE2( std::cout << "( !!! MST::add = "
00324                      << minEdge << " )" );
00325 
00326         return minEdge.target();
00327     }
00328 };
00329 
00330 
00331 #endif // SPARINGSTACK_H

Generated on Thu Aug 14 15:13:27 2003 for External Memory Minimum Spanning Trees by doxygen1.2.17