00001 // Filename: uniqueIdAllocator.cxx 00002 // Created by: schuyler 2003-03-13 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 // 00019 00020 #include "pandabase.h" 00021 #include "notify.h" 00022 00023 #include "uniqueIdAllocator.h" 00024 00025 NotifyCategoryDecl(uniqueIdAllocator, EXPCL_PANDA, EXPTP_PANDA); 00026 NotifyCategoryDef(uniqueIdAllocator, ""); 00027 00028 #ifndef NDEBUG //[ 00029 // Non-release build: 00030 #define uniqueIdAllocator_debug(msg) \ 00031 if (uniqueIdAllocator_cat.is_debug()) { \ 00032 uniqueIdAllocator_cat->debug() << msg << endl; \ 00033 } else {} 00034 00035 #define uniqueIdAllocator_info(msg) \ 00036 uniqueIdAllocator_cat->info() << msg << endl 00037 00038 #define uniqueIdAllocator_warning(msg) \ 00039 uniqueIdAllocator_cat->warning() << msg << endl 00040 #else //][ 00041 // Release build: 00042 #define uniqueIdAllocator_debug(msg) ((void)0) 00043 #define uniqueIdAllocator_info(msg) ((void)0) 00044 #define uniqueIdAllocator_warning(msg) ((void)0) 00045 #endif //] 00046 00047 #define audio_error(msg) \ 00048 audio_cat->error() << msg << endl 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: 00052 // Access: 00053 // Description: Create a free id pool in the range [min:max]. 00054 //////////////////////////////////////////////////////////////////// 00055 UniqueIdAllocator:: 00056 UniqueIdAllocator(U32 min, U32 max) 00057 : _min(min), _max(max) { 00058 uniqueIdAllocator_debug("UniqueIdAllocator("<<min<<", "<<max<<")"); 00059 _size=_max-_min+1; // +1 because min and max are inclusive. 00060 nassertv(_size); // size must be > 0. 00061 _table=new U32[_size]; 00062 nassertv(_table); // This should be redundant if new throws an exception. 00063 for (U32 i=0; i<_size; ++i) { 00064 _table[i]=i+1; 00065 } 00066 _table[_size-1]=IndexEnd; 00067 _next_free=0; 00068 _last_free=_size-1; 00069 _free=_size; 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: 00074 // Access: 00075 // Description: 00076 //////////////////////////////////////////////////////////////////// 00077 UniqueIdAllocator:: 00078 ~UniqueIdAllocator() { 00079 uniqueIdAllocator_debug("~UniqueIdAllocator()"); 00080 delete [] _table; 00081 } 00082 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: 00086 // Access: 00087 // Description: Receive an id between _min and _max (that were passed 00088 // to the constructor). 00089 // IndexEnd is returned if no ids are available. 00090 //////////////////////////////////////////////////////////////////// 00091 U32 UniqueIdAllocator:: 00092 allocate() { 00093 if (_next_free==IndexEnd) { 00094 // ...all ids allocated. 00095 uniqueIdAllocator_warning("allocate Error: no more free ids."); 00096 return IndexEnd; 00097 } 00098 U32 id=_min+_next_free; 00099 _next_free=_table[_next_free]; 00100 #ifndef NDEBUG //[ 00101 _table[id-_min]=IndexAllocated; 00102 #endif //] 00103 --_free; 00104 uniqueIdAllocator_debug("allocate() returning "<<id); 00105 return id; 00106 } 00107 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: 00111 // Access: 00112 // Description: Free an allocated index (index must be between _min 00113 // and _max that were passed to the constructor). 00114 //////////////////////////////////////////////////////////////////// 00115 void UniqueIdAllocator:: 00116 free(U32 index) { 00117 uniqueIdAllocator_debug("free("<<index<<")"); 00118 nassertv(index>=_min); // Attempt to free out-of-range id. 00119 nassertv(index<=_max); // Attempt to free out-of-range id. 00120 index=index-_min; // Convert to _table index. 00121 nassertv(_table[index]==IndexAllocated); // Attempt to free non-allocated id. 00122 _table[index]=IndexEnd; // Mark this element as the end of the list. 00123 _table[_last_free]=index; 00124 if (_next_free==IndexEnd) { 00125 // ...the free list was empty. 00126 _next_free=index; 00127 } 00128 _last_free=index; 00129 ++_free; 00130 } 00131 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: 00135 // Access: 00136 // Description: return what percentage of the pool is used. The 00137 // range is 0 to 1.0, so 75% would be 0.75, for example. 00138 //////////////////////////////////////////////////////////////////// 00139 float UniqueIdAllocator:: 00140 percent_used() const { 00141 return float(_size-_free)/_size; 00142 } 00143 00144 00145 //////////////////////////////////////////////////////////////////// 00146 // Function: 00147 // Access: 00148 // Description: ...intended for debugging only. 00149 //////////////////////////////////////////////////////////////////// 00150 void UniqueIdAllocator:: 00151 output(ostream& os, bool verbose) const { 00152 os <<"[_next_free: "<<long(_next_free) 00153 <<"; _last_free: "<<long(_last_free) 00154 <<"; _size: "<<_size 00155 <<"; _free: "<<_free 00156 <<"; used: "<<_size-_free 00157 <<"; %used: "<<float(_size-_free)/_size; 00158 if (verbose) { 00159 os <<";\n "; 00160 for (U32 i=0; i<_size; ++i) { 00161 os<<long(_table[i])<<", "; 00162 } 00163 } 00164 os<<"]"<<endl; 00165 } 00166