--- /dev/null
+#ifndef __creaImageIOThreadedImageReader_h_INCLUDED__
+#define __creaImageIOThreadedImageReader_h_INCLUDED__
+
+#include <creaImageIOSystem.h>
+#include <creaImageIOImageReader.h>
+#include <creaImageIOIndexedHeap.h>
+#include <map>
+#include <deque>
+#include <wx/thread.h>
+#include <queue>
+
+
+
+namespace creaImageIO
+{
+ /**
+ * \ingroup IO
+ */
+ //=====================================================================
+ class ThreadedImageReader;
+ class MultiThreadImageReader;
+ //=====================================================================
+
+ //=====================================================================
+ class CREAIMAGEIO_EXPORT MultiThreadImageReaderUser
+ {
+ public:
+ friend class ThreadedImageReader;
+ friend class MultiThreadImageReader;
+
+ MultiThreadImageReaderUser() {}
+ virtual ~MultiThreadImageReaderUser() {}
+
+ typedef enum
+ {
+ ThreadedReaderStarted,
+ ThreadedReaderStopped,
+ ImageLoaded,
+ ImageUnloaded,
+ Error
+ }
+ EventType;
+ /// The virtual method to overload by MultiThreadImageReader users
+ /// It is called when an image has been loaded or unloaded
+ /// Provides :
+ /// * The image file name which was requested
+ /// * The type of event
+ /// * If type==ImageLoaded the image pointer, else NULL pointer
+ virtual void OnMultiThreadImageReaderEvent( const std::string& filename,
+ EventType type,
+ vtkImageData* image)
+ {}
+ inline void MultiThreadImageReaderEventLock()
+ { mMultiThreadImageReaderUserMutex.Lock(); }
+ inline void MultiThreadImageReaderEventUnlock()
+ { mMultiThreadImageReaderUserMutex.Unlock(); }
+ inline wxMutex& GetMultiThreadImageReaderUserMutex()
+ { return mMultiThreadImageReaderUserMutex; }
+ private:
+ ///
+ void MultiThreadImageReaderSendEvent( const std::string& filename,
+ EventType type,
+ vtkImageData* image);
+ wxMutex mMultiThreadImageReaderUserMutex;
+ };
+ //=====================================================================
+
+ //=====================================================================
+ ///
+ /// TAKE CARE : For the moment it only supports a **SINGLE USER**
+
+ ///Class that allows parallel lectures of several images
+ class MultiThreadImageReader : public MultiThreadImageReaderUser
+ {
+ public:
+ friend class ThreadedImageReader;
+
+ /// Ctor with the number of threads to use
+ MultiThreadImageReader(int number_of_threads = 1);
+ /// Dtor
+ ~MultiThreadImageReader();
+
+ /// Starts the reader = create the threads which start to check
+ /// periodically the queue of requested images to read
+ bool Start();
+ /// Stops the reader = stops the threads and delete the images loaded
+ void Stop();
+
+ /// Request the image "filename" with a given priority
+ /// When the image is ready (or an error occurred)
+ /// The observer's callback is invoked
+ void Request( MultiThreadImageReaderUser* user,
+ const std::string& filename,
+ int priority );
+
+ /// Request the image "filename" immediately
+ /// Blocks until image loaded
+ /// (no user callback but image returned)
+ vtkImageData* GetImage(const std::string& filename);
+
+ ///
+ int GetMaximalPriority();
+
+ ///
+ void OnMultiThreadImageReaderEvent( const std::string& filename,
+ EventType type,
+ vtkImageData* image);
+
+ protected:
+ bool mDone;
+ int GetMaximalPriorityWithoutLocking();
+ ///Class that represents an image to be loaded
+ class ImageToLoad
+ {
+ public:
+ ImageToLoad( MultiThreadImageReaderUser* user,
+ const std::string& filename,
+ int prio=0)
+ : mUser(user),
+ mFilename(filename),
+ mPriority(prio),
+ mIndex(-1),
+ mUnloadIndex(-1),
+ mImage(0)
+ {}
+ ~ImageToLoad()
+ {
+ if (mImage>0)
+ {
+ // std::cout << "Refs = "<<mImage->GetReferenceCount()<<std::endl;
+ mImage->Delete();
+ }
+ }
+ MultiThreadImageReaderUser* GetUser() const { return mUser; }
+ void SetUser( MultiThreadImageReaderUser* u ) { mUser = u; }
+ const std::string& GetFilename() const { return mFilename; }
+ int GetPriority() const { return mPriority; }
+ void SetPriority(int p) { mPriority=p; }
+ int& Index() { return mIndex; }
+ int& UnloadIndex() { return mUnloadIndex; }
+ vtkImageData* GetImage() const { return mImage; }
+ void SetImage( vtkImageData* i ) { mImage=i; }
+ private:
+ MultiThreadImageReaderUser* mUser;
+ std::string mFilename;
+ int mPriority;
+ int mIndex;
+ int mUnloadIndex;
+ vtkImageData* mImage;
+ };
+ //
+
+ /// Type of pointer on an ImageToLoad struct
+ typedef ImageToLoad* ImageToLoadPtr;
+
+ /// ImageToLoadPtr comparator on priority (for image queue)
+ struct ImageToLoadPtrPriorityComparator
+ {
+ bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
+ const
+ {
+ return ( a->GetPriority() > b->GetPriority() );
+ }
+ };
+ /// ImageToLoadPtr comparator on inverse priority (for image to unload queue)
+ struct ImageToLoadPtrInversePriorityComparator
+ {
+ bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
+ const
+ {
+ return ( a->GetPriority() < b->GetPriority() );
+ }
+ };
+
+
+ /// ImageToLoadPtr comparator on filename (for image map)
+ struct ImageToLoadPtrFilenameComparator
+ {
+ bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
+ const
+ {
+ return ( a->GetFilename() < b->GetFilename() );
+ }
+ };
+
+ /// ImageToLoadPtr indexer for image queue
+ struct ImageToLoadPtrIndexer
+ {
+ int& operator()(ImageToLoadPtr & t) const { return t->Index(); }
+ };
+ /// ImageToLoadPtr indexer for to unload image queue
+ struct ImageToUnloadPtrIndexer
+ {
+ int& operator()(ImageToLoadPtr & t) const { return t->UnloadIndex(); }
+ };
+
+ /// The callback from threaded readers when an image is read
+ void SignalImageRead(ImageToLoadPtr p, bool purge);
+
+ /// The type of map of images
+ typedef std::map<ImageToLoadPtr,vtkImageData*,
+ ImageToLoadPtrFilenameComparator> ImageMapType;
+ /// The map of images
+ ImageMapType mImages;
+ /// Comparator for the image to load queue
+ ImageToLoadPtrPriorityComparator mComparator;
+ /// Indexer for the image to load queue
+ ImageToLoadPtrIndexer mIndexer;
+ /// The image to load priority queue
+ IndexedHeap<ImageToLoadPtr,
+ ImageToLoadPtrPriorityComparator,
+ ImageToLoadPtrIndexer> mQueue;
+
+ /// The type of list of threaded readers
+ typedef std::vector<boost::shared_ptr<ThreadedImageReader> > ThreadedImageReaderListType;
+ //typedef std::vector<ThreadedImageReader* > ThreadedImageReaderListType;
+ ThreadedImageReaderListType mThreadedImageReaderList;
+ /// The number of currently running threaded readers
+ int mNumberOfThreadedReadersRunning;
+ /// The mutex used to access safely internal data from any thread
+ /// LG : Removed ! We now use the embedded mutex in User from which
+ /// we inherit...
+ // wxMutex mMutex;
+
+ /// For GetImage : the filename requested
+ std::string mRequestedFilename;
+ /// For GetImage : the image requested
+ vtkImageData* mRequestedImage;
+
+ /// If number of threads == 0 then uses an internal non-threaded reader
+ ImageReader* mReader;
+
+ /// The type of list of images loaded
+ /// used to unload oldest image when memory limit exceeded
+ /// The image to unload priority queue
+ IndexedHeap<ImageToLoadPtr,
+ ImageToLoadPtrInversePriorityComparator,
+ ImageToUnloadPtrIndexer> mUnloadQueue;
+
+ void UpdateUnloadPriority(ImageToLoadPtr p, int priority);
+ long mTotalMem;
+ long mTotalMemMax;
+
+
+ }; // class MultiThreadImageReader
+ //=====================================================================
+
+
+
+} // namespace creaImageIO
+
+
+
+#endif // #ifndef __creaImageIOThreadedImageReader_h_INCLUDED__