]> Creatis software - creaImageIO.git/blob - src/creaImageIOMultiThreadImageReader.h
d72981d23479fa44019a1f055e8f28c04d235c29
[creaImageIO.git] / src / creaImageIOMultiThreadImageReader.h
1 #ifndef __creaImageIOThreadedImageReader_h_INCLUDED__
2 #define __creaImageIOThreadedImageReader_h_INCLUDED__
3
4 #include <creaImageIOSystem.h>
5 #include <creaImageIOImageReader.h>
6 #include <creaImageIOIndexedHeap.h>
7 #include <map>
8 #include <deque>
9 #include <wx/thread.h>
10 #include <queue>
11
12 namespace creaImageIO
13 {
14
15   //=====================================================================
16   class ThreadedImageReader;
17   class MultiThreadImageReader;
18   //=====================================================================
19   
20   //=====================================================================
21   class CREAIMAGEIO_EXPORT MultiThreadImageReaderUser
22   {
23   public:
24     friend class ThreadedImageReader;
25     friend class MultiThreadImageReader;
26
27     MultiThreadImageReaderUser() {}
28     virtual ~MultiThreadImageReaderUser() {}
29
30     typedef enum 
31       {
32         ThreadedReaderStarted,
33         ThreadedReaderStopped,
34         ImageLoaded,
35         ImageUnloaded,
36         Error
37       }
38       EventType;
39     /// The virtual method to overload by MultiThreadImageReader users
40       /// It is called when an image has been loaded or unloaded 
41       /// Provides :
42       /// * The image file name which was requested 
43       /// * The type of event 
44       /// * If type==ImageLoaded the image pointer, else NULL pointer 
45     virtual void OnMultiThreadImageReaderEvent( const std::string& filename,
46                                                 EventType type,
47                                                 vtkImageData* image) 
48     {}
49     inline void MultiThreadImageReaderEventLock() 
50     { mMultiThreadImageReaderUserMutex.Lock(); }
51     inline void MultiThreadImageReaderEventUnlock() 
52     { mMultiThreadImageReaderUserMutex.Unlock(); }
53     inline wxMutex& GetMultiThreadImageReaderUserMutex() 
54     { return mMultiThreadImageReaderUserMutex; }
55   private:
56     /// 
57     void MultiThreadImageReaderSendEvent( const std::string& filename,
58                                           EventType type,
59                                           vtkImageData* image);
60     wxMutex mMultiThreadImageReaderUserMutex;
61   };
62   //=====================================================================
63
64   //=====================================================================
65   /// 
66   /// TAKE CARE : For the moment it only supports a **SINGLE USER** 
67   class MultiThreadImageReader : public MultiThreadImageReaderUser
68   {
69   public:
70     friend class ThreadedImageReader;
71
72     /// Ctor with the number of threads to use
73     MultiThreadImageReader(int number_of_threads = 1);
74     /// Dtor 
75     ~MultiThreadImageReader();
76
77     /// Starts the reader = create the threads which start to check 
78     /// periodically the queue of requested images to read
79     bool Start();
80     /// Stops the reader = stops the threads and delete the images loaded
81     void Stop();
82
83     /// Request the image "filename" with a given priority 
84     /// When the image is ready (or an error occurred) 
85     /// The observer's callback is invoked 
86     void Request( MultiThreadImageReaderUser* user,
87                   const std::string& filename, 
88                   int priority );
89     
90     /// Request the image "filename" immediately 
91         /// Blocks until image loaded
92     /// (no user callback but image returned)
93     vtkImageData* GetImage(const std::string& filename);
94
95     /// 
96     int GetMaximalPriority(); 
97     
98     ///
99     void OnMultiThreadImageReaderEvent( const std::string& filename,
100                                         EventType type,
101                                         vtkImageData* image);
102     
103   protected:
104     int GetMaximalPriorityWithoutLocking();
105     // 
106     class ImageToLoad
107     {
108     public:
109       ImageToLoad( MultiThreadImageReaderUser* user,
110                    const std::string& filename, 
111                    int prio=0) 
112         : mUser(user),
113           mFilename(filename), 
114           mPriority(prio), 
115           mIndex(-1), 
116           mUnloadIndex(-1), 
117           mImage(0)
118       {}
119       ~ImageToLoad()
120       {
121         if (mImage>0) 
122           {
123             //      std::cout << "Refs = "<<mImage->GetReferenceCount()<<std::endl;
124             mImage->Delete();
125           }
126       }
127       MultiThreadImageReaderUser* GetUser() const { return mUser; }
128       void SetUser( MultiThreadImageReaderUser* u ) { mUser = u; }
129       const std::string& GetFilename() const { return mFilename; }
130       int GetPriority() const { return mPriority; }
131       void SetPriority(int p) { mPriority=p; }
132       int& Index() { return mIndex; }
133       int& UnloadIndex() { return mUnloadIndex; }
134       vtkImageData* GetImage() const { return mImage; }
135       void SetImage( vtkImageData* i ) { mImage=i; }
136     private:
137       MultiThreadImageReaderUser* mUser;
138       std::string mFilename;
139       int mPriority;
140       int mIndex;
141       int mUnloadIndex;
142       vtkImageData* mImage;
143     };
144     // 
145
146     /// Type of pointer on an ImageToLoad struct
147     typedef ImageToLoad* ImageToLoadPtr;
148
149     /// ImageToLoadPtr comparator on priority (for image queue)
150     struct ImageToLoadPtrPriorityComparator
151     {
152       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
153         const 
154       {
155         return ( a->GetPriority() > b->GetPriority() );
156       }
157     };
158     /// ImageToLoadPtr comparator on inverse priority (for image to unload queue)
159     struct ImageToLoadPtrInversePriorityComparator
160     {
161       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
162         const 
163       {
164         return ( a->GetPriority() < b->GetPriority() );
165       }
166     };
167
168
169     /// ImageToLoadPtr comparator on filename (for image map)
170     struct ImageToLoadPtrFilenameComparator
171     {
172       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
173         const 
174       {
175         return ( a->GetFilename() < b->GetFilename() );
176       }
177     };
178
179     /// ImageToLoadPtr indexer for image queue
180     struct ImageToLoadPtrIndexer
181     {
182       int& operator()(ImageToLoadPtr & t) const { return t->Index(); }
183     };
184     /// ImageToLoadPtr indexer for to unload image queue
185     struct ImageToUnloadPtrIndexer
186     {
187       int& operator()(ImageToLoadPtr & t) const { return t->UnloadIndex(); }
188     };
189
190     /// The callback from threaded readers when an image is read
191     void SignalImageRead(ImageToLoadPtr p, bool purge);
192   
193     /// The type of map of images 
194     typedef std::map<ImageToLoadPtr,vtkImageData*,
195                      ImageToLoadPtrFilenameComparator> ImageMapType;
196     /// The map of images
197     ImageMapType mImages;
198     /// Comparator for the image to load queue
199     ImageToLoadPtrPriorityComparator mComparator;
200     /// Indexer for the image to load queue 
201     ImageToLoadPtrIndexer mIndexer;
202     /// The image to load priority queue
203     IndexedHeap<ImageToLoadPtr,
204                 ImageToLoadPtrPriorityComparator,
205                 ImageToLoadPtrIndexer> mQueue;
206
207     /// The type of list of threaded readers
208     typedef std::vector<ThreadedImageReader*> ThreadedImageReaderListType;
209     ThreadedImageReaderListType mThreadedImageReaderList;
210     /// The number of currently running threaded readers
211     int mNumberOfThreadedReadersRunning;
212     /// The mutex used to access safely internal data from any thread
213     /// LG : Removed ! We now use the embedded mutex in User from which 
214     /// we inherit...
215     //  wxMutex mMutex;
216
217     /// For GetImage : the filename requested
218     std::string mRequestedFilename;
219     /// For GetImage : the image requested
220     vtkImageData* mRequestedImage;
221
222     /// If number of threads == 0 then uses an internal non-threaded reader
223     ImageReader* mReader;
224
225     /// The type of list of images loaded 
226     /// used to unload oldest image when memory limit exceeded
227    /// The image to unload priority queue
228     IndexedHeap<ImageToLoadPtr,
229                 ImageToLoadPtrInversePriorityComparator,
230                 ImageToUnloadPtrIndexer> mUnloadQueue;
231
232     void UpdateUnloadPriority(ImageToLoadPtr p, int priority);
233     long mTotalMem;
234     long mTotalMemMax;
235
236
237   }; // class MultiThreadImageReader
238   //=====================================================================
239
240
241
242 } // namespace creaImageIO
243
244
245
246 #endif // #ifndef __creaImageIOThreadedImageReader_h_INCLUDED__