00001
00002
00003 #ifdef I_REALLY_WANT_TO_USE_IMAGECACHE
00004 #define MediaTable_ImageCache_h
00005
00006 #include "OglGui/OglImageCache.h"
00007
00008 #include "TableDataSource.h"
00009 #include "Visualization/RgbOglImage.h"
00010
00011 #ifdef USE_BOOST_THREADPOOL
00012
00013
00014
00015
00016 #include "threadpool25/threadpool.hpp"
00017
00018 #endif
00019
00020
00021 namespace Impala {
00022 namespace Application {
00023 namespace MediaTable {
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 class ImageCache
00070 {
00071 public:
00072 typedef Impala::Core::Array::Array2dVec3UInt8 Array2dVec3UInt8;
00073 typedef std::pair<int, OGLIMAGE*> ImageWithID;
00074
00075 static void InitializeCache(TableDataSource *source, int size)
00076 {
00077 if (sInstance)
00078 {
00079 ILOG_WARN("ImageCache already initialized. Skipping.");
00080 return;
00081 }
00082 sInstance = new ImageCache(source, size);
00083 }
00084
00085 static ImageCache* GetInstance()
00086 {
00087 if (!sInstance)
00088 {
00089 ILOG_ERROR("You forgot to initialize ImageCache with a source.");
00090 return 0;
00091 }
00092 return sInstance;
00093 }
00094
00095
00096 OGLIMAGE* GetImage(int id, String column)
00097 {
00098 OGLIMAGE *i = GetImageFromCache(id, column);
00099 if (!i)
00100 i = LoadImage(id, column);
00101 return i;
00102 }
00103
00104 OGLIMAGE* GetImageFromCache(int id, String column)
00105 {
00106
00107
00108
00109
00110 for (int i=0; i<mImages.size(); i++)
00111 {
00112 if (id == mImages[i]->first) {
00113
00114 UpdateLRU(i);
00115 return mImages[i]->second;
00116 }
00117 }
00118 return 0;
00119 }
00120
00121 #ifndef USE_BOOST_THREADPOOL
00122 OGLIMAGE* LoadImage(int id, String column)
00123 {
00124
00125
00126 Array2dVec3UInt8* ar = mSource->GetImageDataByID(column, id);
00127 if (ar == 0)
00128 return 0;
00129
00130 ImageWithID *p = GetLeastUsedImageFromCache();
00131 if (p->second)
00132 {
00133 ReleaseOglImage(p->second);
00134 ILOG_DEBUG("Refcount for least used image now " <<
00135 p->second->refCount);
00136 }
00137 else
00138 ILOG_DEBUG("Cache not yet grown to max size, growing...");
00139
00140 p->second = Visualization::RgbOglImage::OglImage(ar);
00141 p->first = id;
00142 return p->second;
00143 }
00144 #else
00145 OGLIMAGE* LoadImage(int id, String column)
00146 {
00147
00148
00149
00150
00151
00152
00153
00154 ImageWithID *p = GetLeastUsedImageFromCache();
00155 if (p->second)
00156 {
00157 ReleaseOglImage(p->second);
00158 ILOG_DEBUG("Refcount for least used image now " <<
00159 p->second->refCount);
00160 }
00161 else
00162 ILOG_DEBUG("Cache not yet grown to max size, growing...");
00163
00164 p->second = Visualization::RgbOglImage::OglImage(mEmptyArray);
00165 p->first = id;
00166
00167
00168
00169
00170 OglImageLoader loader(mSource, column, id, p->second);
00171
00172 mThreadPool->schedule(loader);
00173
00174 mActiveTasks = true;
00175
00176 return p->second;
00177 }
00178 #endif
00179
00180 #ifndef USE_BOOST_THREADPOOL
00181 bool
00182 IsLoadingImages()
00183 {
00184 return false;
00185 }
00186 #else
00187 bool
00188 IsLoadingImages()
00189 {
00190 if (!mActiveTasks)
00191 return false;
00192
00193 ILOG_DEBUG("TP check: Size " << mThreadPool->size() << " Active tasks " << mThreadPool->active() << " Pending tasks " << mThreadPool->pending());
00194
00195 if (mThreadPool->active() == 0)
00196 mActiveTasks = false;
00197
00198 return true;
00199 }
00200 #endif
00201
00202
00203 int GetImageCacheMaxSize()
00204 {
00205 return mCacheSize;
00206 }
00207
00208
00209 void PreloadCache()
00210 {
00211
00212 int preload = mCacheSize;
00213 if (mSource->GetTotalRows() < mCacheSize)
00214 preload = mSource->GetTotalRows();
00215 ILOG_INFO("Preloading " << preload << " images...");
00216 for (int i=0; i<preload; i++)
00217 {
00218 if (i%100==0)
00219 ILOG_DEBUG("Preloading image " << i << " of " << preload);
00220 LoadImage(i, "");
00221 }
00222 }
00223
00224 private:
00225 ImageCache(TableDataSource* source, int size)
00226 {
00227 Init(source, size);
00228 }
00229
00230 ImageCache(ImageCache const&){};
00231 ImageCache& operator=(ImageCache const&){};
00232
00233 ImageWithID* GetLeastUsedImageFromCache()
00234 {
00235 int item = mLRU.front();
00236 UpdateLRU(item);
00237 return mImages[item];
00238 }
00239
00240 void UpdateLRU(int index)
00241 {
00242 mLRU.remove(index);
00243 mLRU.push_back(index);
00244 }
00245
00246 void Init(TableDataSource* source, int size)
00247 {
00248 mCacheSize = size;
00249 ILOG_DEBUG("Initializing image cache for "<< mCacheSize <<" OGLIMAGEs");
00250
00251 #ifdef USE_BOOST_THREADPOOL
00252 mEmptyArray = Core::Array::ArrayCreate<Core::Array::Array2dVec3UInt8>(0, 0, 0, 0);
00253
00254 mThreadPool = new boost::threadpool::pool(1);
00255 if(source->MultiThreadImageCacheSupported)
00256 mThreadPool->size_controller().resize(8);
00257 mActiveTasks = false;
00258 #endif
00259
00260 mSource = source;
00261
00262 for (int i=0; i<mCacheSize; i++)
00263 {
00264 mImages.push_back(new ImageWithID(-1, 0));
00265 mLRU.push_back(i);
00266 }
00267 }
00268
00269 #ifdef USE_BOOST_THREADPOOL
00270 class OglImageLoader {
00271 public:
00272 OglImageLoader(TableDataSource *s, std::string column, int row, OGLIMAGE *result)
00273 {
00274 mSource = s;
00275 mColumn = column;
00276 mRow = row;
00277 mImage = result;
00278 }
00279
00280 void operator()() {
00281 ILOG_DEBUG("Worker thread retrieving " << mColumn << "x" << mRow);
00282 LoadImage();
00283 }
00284
00285 int LoadImage()
00286 {
00287 Array2dVec3UInt8* ar = mSource->GetImageDataByID(mColumn, mRow);
00288 if (ar == 0)
00289 return 0;
00290
00291
00292
00293
00294
00295
00296
00297
00298 mImage->imageHandle = ar;
00299 mImage->h = ar->CH();
00300 mImage->w = ar->CW();
00301 mImage->changed = 1;
00302 ILOG_DEBUG("Loaded image " << mColumn << "x" << mRow << " as " << mImage->w << "x" << mImage->h <<" pixels in " << mImage);
00303
00304 return 1;
00305 }
00306
00307 private:
00308 TableDataSource *mSource;
00309 std::string mColumn;
00310 int mRow;
00311 OGLIMAGE* mImage;
00312 };
00313 #endif
00314
00315
00316 int mCacheSize;
00317
00318 std::list<int> mLRU;
00319 std::vector<ImageWithID*> mImages;
00320 TableDataSource* mSource;
00321
00322 static ImageCache* sInstance;
00323
00324 #ifdef USE_BOOST_THREADPOOL
00325 Core::Array::Array2dVec3UInt8* mEmptyArray;
00326 boost::threadpool::pool *mThreadPool;
00327 bool mActiveTasks;
00328 #endif
00329
00330 ILOG_VAR_DEC;
00331 };
00332
00333 ImageCache* ImageCache::sInstance = 0;
00334
00335 ILOG_VAR_INIT(ImageCache, Application.MediaTable);
00336
00337 }
00338 }
00339 }
00340 #endif // ImageCache_h