idPool.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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(); )
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