idPool.cpp

00001  
00002 /* Copyright (c) 2005-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "idPool.h"
00019 
00020 #include "debug.h"
00021 #include "scopedMutex.h"
00022 
00023 #include <sstream>
00024 
00025 using namespace std;
00026 
00027 #define COMPRESS_INTERVAL 10000
00028 
00029 namespace eq
00030 {
00031 namespace base
00032 {
00033 IDPool::IDPool( const uint32_t initialCapacity )
00034         : _compressCounter(0)
00035 {
00036     if( initialCapacity )
00037     {
00038         Block* block = new Block();
00039         block->start = 1;
00040         block->range = initialCapacity;
00041         
00042         _freeIDs.push_front( block );
00043     }
00044 }
00045 
00046 IDPool::~IDPool()
00047 {
00048     while( !_freeIDs.empty( ))
00049     {
00050         Block* block = _freeIDs.front();
00051         _freeIDs.pop_front();
00052         delete block;
00053     }
00054     while( !_blockCache.empty( ))
00055     {
00056         Block* block = _blockCache.front();
00057         _blockCache.pop_front();
00058         delete block;
00059     }
00060 }
00061 
00062 uint32_t IDPool::genIDs( const uint32_t range )
00063 {
00064     ScopedMutex mutex( _lock );
00065 
00066     const uint32_t id = _genIDs( range );
00067     if( id )
00068         return id;
00069 
00070     _compressIDs();
00071     return _genIDs( range );
00072 }
00073 
00074 uint32_t IDPool::_genIDs( const uint32_t range )
00075 {
00076     for( list<Block*>::iterator i = _freeIDs.begin(); i != _freeIDs.end(); ++i )
00077     {
00078         Block* block = *i;
00079 
00080         if( range <= block->range )
00081         {
00082             uint32_t start = block->start;
00083 
00084             block->range -= range;
00085             block->start += range;
00086 
00087             if( block->range == 0 )
00088             {
00089                 _freeIDs.erase( i );
00090                 _blockCache.push_front( block );
00091             }
00092 
00093             return start;
00094         }
00095     }
00096     return EQ_ID_INVALID;
00097 }
00098 
00099 void IDPool::freeIDs( const uint32_t start, const uint32_t range )
00100 {
00101     ScopedMutex mutex( _lock );
00102 
00103     Block* block;
00104 
00105     if( _blockCache.empty( ))
00106         block = new Block;
00107     else
00108     {
00109         block = _blockCache.front();
00110         _blockCache.pop_front();
00111     }
00112 
00113     block->start = start;
00114     block->range = range;
00115     _freeIDs.push_front( block );
00116 
00117     _compressCounter++;
00118     if( ( _compressCounter % COMPRESS_INTERVAL) == 0 )
00119         _compressIDs();
00120 }
00121 
00122 void IDPool::_compressIDs()
00123 {
00124     list<Block*> blocks;
00125     bool         compress = true;
00126     
00127     while( compress )
00128     {
00129         blocks.clear();
00130         compress = false;
00131 
00132         while( !_freeIDs.empty( ))
00133         {
00134             Block* block = _freeIDs.front();
00135             _freeIDs.pop_front();
00136 
00137             for( list<Block*>::iterator i = _freeIDs.begin();  
00138                  i != _freeIDs.end(); /*nop*/ )
00139             {
00140                 Block* block2 = *i;
00141                 list<Block*>::iterator currentIter = i;
00142                 ++i;
00143                 
00144                 if(( block->start + block->range ) == block2->start )
00145                 {
00146                     block->range += block2->range;
00147                     _freeIDs.erase( currentIter );
00148 
00149                     _blockCache.push_front( block2 );
00150                     compress = true;
00151                 }
00152                 else if( block->start == ( block2->start + block2->range ))
00153                 {
00154                     block->start  = block2->start;
00155                     block->range += block2->range;
00156                     _freeIDs.erase( currentIter );
00157 
00158                     _blockCache.push_front( block2 );
00159                     compress = true;
00160                 }
00161              }
00162             
00163             blocks.push_front( block );
00164         }
00165 
00166         _freeIDs.swap( blocks );
00167     }
00168 }
00169 }
00170 }
00171 
Generated on Mon Aug 10 18:58:39 2009 for Equalizer 0.9 by  doxygen 1.5.8