#include #include #include namespace creaImageIO { //===================================================================== void MultiThreadImageReaderUser::MultiThreadImageReaderSendEvent ( const std::string& filename, EventType type, vtkImageData* image) { wxMutexLocker lock(mMultiThreadImageReaderUserMutex); this->OnMultiThreadImageReaderEvent(filename,type,image); } //===================================================================== //===================================================================== class ThreadedImageReader: public wxThread { public: ThreadedImageReader(MultiThreadImageReader* tir) : mMultiThreadImageReader(tir) {} void* Entry(); void OnExit(); vtkImageData* Read(const std::string& filename); private: ImageReader mReader; MultiThreadImageReader* mMultiThreadImageReader; }; //===================================================================== //===================================================================== MultiThreadImageReader::MultiThreadImageReader(int number_of_threads) : //mDoNotSignal(false), mReader(0), mTotalMem(0), mTotalMemMax(10000) { // std::cout << "#### MultiThreadImageReader::MultiThreadImageReader(" // << " #threads= " << number_of_threads <<" )"<Create(); if ( (*i)->Run() != wxTHREAD_NO_ERROR ) { std::cout << "ERROR starting a thread"<< std::endl; return false; } else { // std::cout << " ===> Thread "<<(*i)->GetCurrentId() // <<" successfully created"<< std::endl; } } wxMutexLocker locker(GetMultiThreadImageReaderUserMutex()); // std::cout << "EO Start : #Threads running = " // << mNumberOfThreadedReadersRunning<Delete(); } mThreadedImageReaderList.clear(); // Wait a little to be sure that all threads have stopped // A better way to do this ? // wxMilliSleep(1000); // New method : the threads generate a stop event when they have finished // We wait until all threads have stopped // std::cout << "Waiting for stop signals..."<first; } mImages.clear(); } //===================================================================== //===================================================================== MultiThreadImageReader::~MultiThreadImageReader() { // std::cout << "#### MultiThreadImageReader::~MultiThreadImageReader()" // <UnloadIndex()<0) return; int old_prio = p->GetPriority(); if (priority > old_prio) { p->SetPriority(priority); mUnloadQueue.downsort(p->UnloadIndex()); } else if ( old_prio > priority ) { p->SetPriority(priority); mUnloadQueue.upsort(p->UnloadIndex()); } } //===================================================================== //===================================================================== void MultiThreadImageReader::Request( MultiThreadImageReaderUser* user, const std::string& filename, int priority ) { wxMutexLocker lock(GetMultiThreadImageReaderUserMutex()); //mMutex); if (mThreadedImageReaderList.size()==0) { // no detached reader : use self reader ImageToLoad itl(user,filename); ImageMapType::iterator i = mImages.find(&itl); if (i!=mImages.end()) { ImageToLoadPtr pitl = const_cast(i->first); // Already inserted if (pitl->GetImage() != 0) { // Already read pitl->SetUser(user); UpdateUnloadPriority(pitl,priority); SignalImageRead(pitl,false); return; // pitl->GetImage(); } } ImageToLoadPtr pitl = new ImageToLoad(user,filename,0); mImages[pitl] = 0; pitl->SetImage(mReader->Read(filename)); UpdateUnloadPriority(pitl,priority); SignalImageRead(pitl,true); // return pitl->GetImage(); return; } ImageToLoad itl(user,filename); ImageMapType::iterator i = mImages.find(&itl); if (i!=mImages.end()) { // Already inserted if (i->first->GetImage() != 0) { // Already read : ok :signal the user UpdateUnloadPriority(i->first,priority); SignalImageRead(i->first,false); return; } /// Already requested : change the priority ImageToLoadPtr pitl = const_cast(i->first); pitl->SetPriority(priority); // Already in queue if (pitl->Index()>=0) { // Re-sort the queue mQueue.upsort(pitl->Index()); } // Not read but not in queue = being read = ok else { } } else { // Never requested before or unloaded ImageToLoadPtr pitl = new ImageToLoad(user,filename,priority); mImages[pitl] = 0; mQueue.insert(pitl); } } //===================================================================== //===================================================================== void MultiThreadImageReader::OnMultiThreadImageReaderEvent (const std::string& filename, MultiThreadImageReaderUser::EventType e, vtkImageData* image) { if ((e==MultiThreadImageReaderUser::ImageLoaded) && (filename == mRequestedFilename)) { mRequestedImage = image; } else if (e==MultiThreadImageReaderUser::ThreadedReaderStarted) { mNumberOfThreadedReadersRunning++; // std::cout << "#TR=" << mNumberOfThreadedReadersRunning << std::endl; } else if (e==MultiThreadImageReaderUser::ThreadedReaderStopped) { mNumberOfThreadedReadersRunning--; // std::cout << "#TR=" << mNumberOfThreadedReadersRunning << std::endl; } } //===================================================================== //===================================================================== vtkImageData* MultiThreadImageReader::GetImage(const std::string& filename) { // std::cout << "** MultiThreadImageReader::GetImage('"<(i->first); // Already inserted if (pitl->GetImage() != 0) { // Already read UpdateUnloadPriority(pitl, GetMaximalPriorityWithoutLocking()+1); return pitl->GetImage(); } } ImageToLoadPtr pitl = new ImageToLoad(this,filename,0); mImages[pitl] = 0; pitl->SetImage(mReader->Read(filename)); UpdateUnloadPriority(pitl, GetMaximalPriorityWithoutLocking()+1); return pitl->GetImage(); } mRequestedFilename = filename; mRequestedImage = 0; ImageToLoad itl(this,filename); ImageMapType::iterator i = mImages.find(&itl); if (i!=mImages.end()) { // Already inserted in queue if (i->first->GetImage() != 0) { // Already read : ok : return it return i->first->GetImage(); } /// Already requested : change the priority ImageToLoadPtr pitl = const_cast(i->first); pitl->SetPriority( GetMaximalPriorityWithoutLocking() + 1 ); pitl->SetUser( this ); // Already in queue if (pitl->Index()>=0) { // Re-sort the queue mQueue.upsort(pitl->Index()); } // Not read but not in queue = being read = ok else { pitl->SetUser( this ); } } else { // Never requested before or unloaded ImageToLoadPtr pitl = new ImageToLoad(this,filename, GetMaximalPriorityWithoutLocking() + 1); mImages[pitl] = 0; mQueue.insert(pitl); } } while (0); // std::cout << "Waiting..."< Total mem = "< mTotalMemMax) { // std::cout // <<" ! Exceeded max of " // << mTotalMemMax << " : unloading oldest image ... " // << std::endl; if ( mUnloadQueue.size() <= 1 ) { // std::cout << "Only one image : cannot load AND unload it !!" // <GetUser(); if ((user!=0)&&(user!=this)) { user->GetMultiThreadImageReaderUserMutex().Lock(); } // std::cout << "'" << unload->GetFilename() << "'" << std::endl; mTotalMem -= unload->GetImage()->GetEstimatedMemorySize(); // std::cout << " ==> Total mem = "<GetFilename(); if (unload->Index()>=0) { // std::cout << "still in queue"<Index() = -1; ImageMapType::iterator it = mImages.find(unload); if (it!=mImages.end()) { mImages.erase(it); } // std::cout << "delete..."<GetMultiThreadImageReaderUserMutex().Unlock(); // std::cout << "event"<MultiThreadImageReaderSendEvent (filename, MultiThreadImageReaderUser::ImageUnloaded, 0); // std::cout << "event ok"<0) { max = mQueue.top()->GetPriority(); } if (mUnloadQueue.size()>0) { int max2 = mUnloadQueue.top()->GetPriority(); if (max2>max) max=max2; } return max; } //===================================================================== //===================================================================== //===================================================================== //===================================================================== //===================================================================== //===================================================================== void* ThreadedImageReader::Entry() { // std::cout << "### Thread "<MultiThreadImageReaderSendEvent ("", MultiThreadImageReaderUser::ThreadedReaderStarted, 0); // While was not deleted while (!TestDestroy()) { // std::cout << "### Thread "<MultiThreadImageReaderEventLock(); //mMutex.Lock(); // If image in queue if (mMultiThreadImageReader->mQueue.size()>0) { MultiThreadImageReader::ImageToLoadPtr i = mMultiThreadImageReader->mQueue.remove_top(); mMultiThreadImageReader->MultiThreadImageReaderEventUnlock(); //mMutex.Unlock(); // std::cout << "### Thread "<GetFilename() << "'" << std::endl; // Do the job vtkImageData* im = Read(i->GetFilename()); // Store it in the map mMultiThreadImageReader->MultiThreadImageReaderEventLock(); //mMutex.Lock(); MultiThreadImageReader::ImageToLoad itl(0,i->GetFilename()); MultiThreadImageReader::ImageMapType::iterator it = mMultiThreadImageReader->mImages.find(&itl); MultiThreadImageReader::ImageToLoadPtr pitl = const_cast (it->first); pitl->SetImage(im); mMultiThreadImageReader->SignalImageRead(pitl,true);//i->GetFilename()); mMultiThreadImageReader->MultiThreadImageReaderEventUnlock(); //mMutex.Unlock(); // std::cout << "### Thread "<GetFilename() << "' : DONE" << std::endl; } else { mMultiThreadImageReader->MultiThreadImageReaderEventUnlock(); //mMutex.Unlock(); // Wait a little to avoid blocking Sleep(10); } }; // std::cout << "### Thread "<MultiThreadImageReaderSendEvent ("", MultiThreadImageReaderUser::ThreadedReaderStopped, 0); } //===================================================================== //===================================================================== vtkImageData* ThreadedImageReader::Read(const std::string& filename) { return mReader.Read(filename); } //===================================================================== } // namespace creaImageIO