]> Creatis software - creaImageIO.git/blobdiff - src/creaImageIOMultiThreadImageReader.h
move directory
[creaImageIO.git] / src / creaImageIOMultiThreadImageReader.h
diff --git a/src/creaImageIOMultiThreadImageReader.h b/src/creaImageIOMultiThreadImageReader.h
new file mode 100644 (file)
index 0000000..c5a9ef9
--- /dev/null
@@ -0,0 +1,254 @@
+#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__