00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef FLYWEIGHT_POOL
00032 #define FLYWEIGHT_POOL
00033
00034 #include <list>
00035 #include <assert.h>
00036 #ifdef HAVE_VPR
00037 #include <vpr/Sync/Mutex.h>
00038 #endif
00039
00040 namespace syn
00041 {
00042
00059 template <class type>
00060 class FlyWeightPool
00061 {
00062 public:
00063 FlyWeightPool() : mAutoGrow( false ), mNumCheckedOut( 0 ), mSize( 0 )
00064 {
00065 this->acquire();
00066 mPool.resize( mSize );
00067 this->release();
00068 }
00069 ~FlyWeightPool()
00070 {
00071 assert( this != NULL && "this would be bad indeed" );
00072 this->acquire();
00073 assert( mNumCheckedOut == 0 && "not everyone has checked their items back into the pool" );
00074 assert( mPool.size() == mSize && "not everyone has checked their items back into the pool" );
00075 while (mPool.size() > 0)
00076 {
00077 delete mPool.front();
00078 mPool.pop_front();
00079 }
00080 this->release();
00081 }
00082
00083 void setAutoGrow( bool grow ) { mAutoGrow = grow; }
00084 bool autoGrow() const { return mAutoGrow; }
00085
00086 #ifdef HAVE_VPR
00087 void acquire() const { mMutex.acquire(); }
00088 bool tryAcquire() const { return mMutex.tryAcquire(); }
00089 void release() const { mMutex.release(); }
00090 #else
00091 void acquire() const { }
00092 bool tryAcquire() const { return false; }
00093 void release() const { }
00094 #endif
00095
00096 void resize( unsigned int s )
00097 {
00098 this->acquire();
00099 {
00100 this->resize_nonthreadsafe( s );
00101 }
00102 this->release();
00103 }
00104
00106 unsigned int size() const { return mSize; }
00107
00109 int available() const { return mPool.size(); }
00110
00112 bool empty() const { return mPool.size() == 0; }
00113
00118 void take( type* &t )
00119 {
00120 this->acquire();
00121 if (mAutoGrow && this->empty())
00122 {
00123 this->resize_nonthreadsafe( (this->size() + 1) * 2 );
00124 }
00125 assert( this->empty() == false && "need to check empty() before take()ing" );
00126 t = mPool.front();
00127 mPool.pop_front();
00128 ++mNumCheckedOut;
00129 this->release();
00130 }
00131
00135 void putback( type* t )
00136 {
00137 this->acquire();
00138 {
00139 if (mPool.size() < mSize)
00140 mPool.push_front( t );
00141
00142
00143
00144 else
00145 delete t;
00146
00147 --mNumCheckedOut;
00148 }
00149 this->release();
00150 }
00151
00152 private:
00153 void resize_nonthreadsafe( unsigned int s )
00154 {
00155
00156 int size_to_grow = (int)s - (int)mSize;
00157 int size_to_shrink = -size_to_grow;
00158 int x;
00159
00160
00161 for (x = 0; x < size_to_grow; ++x)
00162 {
00163 mPool.push_front( new type );
00164 }
00165
00166
00167 for (x = 0; x < size_to_shrink && mPool.size() > 0; ++x)
00168 {
00169 delete mPool.back();
00170 mPool.pop_back();
00171 }
00172
00173
00174 mSize = s;
00175 }
00176
00177 #ifdef HAVE_VPR
00178 mutable vpr::Mutex mMutex;
00179 #endif
00180 bool mAutoGrow;
00181 int mNumCheckedOut;
00182 unsigned int mSize;
00183 std::list<type*> mPool;
00184
00185
00186 };
00187
00188 }
00189 #endif