]> Creatis software - creaImageIO.git/blob - src/creaImageIOQMultiThreadImageReader.h
#3185 creaImageIO Feature New Normal - Clean code
[creaImageIO.git] / src / creaImageIOQMultiThreadImageReader.h
1 /*
2 # ---------------------------------------------------------------------
3 #
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image 
5 #                        pour la Santé)
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9 #
10 #  This software is governed by the CeCILL-B license under French law and 
11 #  abiding by the rules of distribution of free software. You can  use, 
12 #  modify and/ or redistribute the software under the terms of the CeCILL-B 
13 #  license as circulated by CEA, CNRS and INRIA at the following URL 
14 #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html 
15 #  or in the file LICENSE.txt.
16 #
17 #  As a counterpart to the access to the source code and  rights to copy,
18 #  modify and redistribute granted by the license, users are provided only
19 #  with a limited warranty  and the software's author,  the holder of the
20 #  economic rights,  and the successive licensors  have only  limited
21 #  liability. 
22 #
23 #  The fact that you are presently reading this means that you have had
24 #  knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------
26 */
27
28
29 #ifndef __creaImageIOQMultiThreadImageReader_h_INCLUDED__
30 #define __creaImageIOQMultiThreadImageReader_h_INCLUDED__
31
32 #include <creaImageIOSystem.h>
33 #include <creaImageIOImageReader.h>
34 #include <creaImageIOIndexedHeap.h>
35 #include <map>
36 #include <deque>
37 #include <QMutex>
38 #include <queue>
39
40
41
42 namespace creaImageIO
43 {
44         /**
45         * \ingroup IO
46         */
47   //=====================================================================
48   class ThreadedImageReader;
49   class MultiThreadImageReader;
50   //=====================================================================
51   
52   //=====================================================================
53   class CREAIMAGEIO_EXPORT MultiThreadImageReaderUser
54   {
55   public:
56     friend class ThreadedImageReader;
57     friend class MultiThreadImageReader;
58
59     MultiThreadImageReaderUser() {}
60     virtual ~MultiThreadImageReaderUser() {}
61
62     typedef enum 
63       {
64         ThreadedReaderStarted,
65         ThreadedReaderStopped,
66         ImageLoaded,
67         ImageUnloaded,
68         Error
69       }
70       EventType;
71     /// The virtual method to overload by MultiThreadImageReader users
72       /// It is called when an image has been loaded or unloaded 
73       /// Provides :
74       /// * The image file name which was requested 
75       /// * The type of event 
76       /// * If type==ImageLoaded the image pointer, else NULL pointer 
77     virtual void OnMultiThreadImageReaderEvent( const std::string& filename,
78                                                 EventType type,
79                                                 vtkImageData* image) 
80     {}
81     inline void MultiThreadImageReaderEventLock() 
82     { mMultiThreadImageReaderUserMutex.lock(); }
83     inline void MultiThreadImageReaderEventUnlock() 
84     { mMultiThreadImageReaderUserMutex.unlock(); }
85     inline QMutex* GetMultiThreadImageReaderUserMutex() 
86     { return &mMultiThreadImageReaderUserMutex; }
87   private:
88     /// 
89     void MultiThreadImageReaderSendEvent( const std::string& filename,
90                                           EventType type,
91                                           vtkImageData* image);
92     QMutex mMultiThreadImageReaderUserMutex;
93   };
94   //=====================================================================
95
96   //=====================================================================
97   /// 
98   /// TAKE CARE : For the moment it only supports a **SINGLE USER** 
99
100    ///Class that allows parallel lectures of several images
101   class MultiThreadImageReader : public MultiThreadImageReaderUser
102   {
103   public:
104     friend class ThreadedImageReader;
105
106     /// Ctor with the number of threads to use
107     MultiThreadImageReader(int number_of_threads = 1);
108     /// Dtor 
109     ~MultiThreadImageReader();
110
111     /// Starts the reader = create the threads which start to check 
112     /// periodically the queue of requested images to read
113     bool Start();
114     /// Stops the reader = stops the threads and delete the images loaded
115     void Stop();
116
117     /// Request the image "filename" with a given priority 
118     /// When the image is ready (or an error occurred) 
119     /// The observer's callback is invoked 
120     void Request( MultiThreadImageReaderUser* user,
121                   const std::string& filename, 
122                   int priority );
123     
124     /// Request the image "filename" immediately 
125         /// Blocks until image loaded
126     /// (no user callback but image returned)
127     vtkImageData* GetImage(const std::string& filename);
128
129     /// 
130     int GetMaximalPriority(); 
131     
132     ///
133     void OnMultiThreadImageReaderEvent( const std::string& filename,
134                                         EventType type,
135                                         vtkImageData* image);
136    
137     /// Function to read attributes for a file 
138         void getAttributes(const std::string filename, std::map <std::string , std::string> &infos, std::vector<std::string> i_attr);
139
140   protected:
141           bool mDone;
142     int GetMaximalPriorityWithoutLocking();
143     ///Class that represents an image to be loaded
144     class ImageToLoad
145     {
146     public:
147       ImageToLoad( MultiThreadImageReaderUser* user,
148                    const std::string& filename, 
149                    int prio=0) 
150         : mUser(user),
151           mFilename(filename), 
152           mPriority(prio), 
153           mIndex(-1), 
154           mUnloadIndex(-1), 
155           mImage(0)
156       {}
157       ~ImageToLoad()
158       {
159         if (mImage>0) 
160           {
161             //      std::cout << "Refs = "<<mImage->GetReferenceCount()<<std::endl;
162             mImage->Delete();
163           }
164       }
165       MultiThreadImageReaderUser* GetUser() const { return mUser; }
166       void SetUser( MultiThreadImageReaderUser* u ) { mUser = u; }
167       const std::string& GetFilename() const { return mFilename; }
168       int GetPriority() const { return mPriority; }
169       void SetPriority(int p) { mPriority=p; }
170       int& Index() { return mIndex; }
171       int& UnloadIndex() { return mUnloadIndex; }
172       vtkImageData* GetImage() const { return mImage; }
173       void SetImage( vtkImageData* i ) { mImage=i; }
174
175           std::map<std::string, std::string> getAttributes(const std::vector<std::string> i_attr);
176     private:
177       MultiThreadImageReaderUser* mUser;
178       std::string mFilename;
179       int mPriority;
180       int mIndex;
181       int mUnloadIndex;
182       vtkImageData* mImage;
183     };
184     // 
185
186     /// Type of pointer on an ImageToLoad struct
187     typedef ImageToLoad* ImageToLoadPtr;
188
189     /// ImageToLoadPtr comparator on priority (for image queue)
190     struct ImageToLoadPtrPriorityComparator
191     {
192       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
193         const 
194       {
195         return ( a->GetPriority() > b->GetPriority() );
196       }
197     };
198     /// ImageToLoadPtr comparator on inverse priority (for image to unload queue)
199     struct ImageToLoadPtrInversePriorityComparator
200     {
201       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
202         const 
203       {
204         return ( a->GetPriority() < b->GetPriority() );
205       }
206     };
207
208
209     /// ImageToLoadPtr comparator on filename (for image map)
210     struct ImageToLoadPtrFilenameComparator
211     {
212       bool operator() (ImageToLoadPtr const & a, ImageToLoadPtr const & b)
213         const 
214       {
215         return ( a->GetFilename() < b->GetFilename() );
216       }
217     };
218
219     /// ImageToLoadPtr indexer for image queue
220     struct ImageToLoadPtrIndexer
221     {
222       int& operator()(ImageToLoadPtr & t) const { return t->Index(); }
223     };
224     /// ImageToLoadPtr indexer for to unload image queue
225     struct ImageToUnloadPtrIndexer
226     {
227       int& operator()(ImageToLoadPtr & t) const { return t->UnloadIndex(); }
228     };
229
230     /// The callback from threaded readers when an image is read
231     void SignalImageRead(ImageToLoadPtr p, bool purge);
232   
233     /// The type of map of images 
234     typedef std::map<ImageToLoadPtr,vtkImageData*,
235                      ImageToLoadPtrFilenameComparator> ImageMapType;
236     /// The map of images
237     ImageMapType mImages;
238     /// Comparator for the image to load queue
239     ImageToLoadPtrPriorityComparator mComparator;
240     /// Indexer for the image to load queue 
241     ImageToLoadPtrIndexer mIndexer;
242     /// The image to load priority queue
243     IndexedHeap<ImageToLoadPtr,
244                 ImageToLoadPtrPriorityComparator,
245                 ImageToLoadPtrIndexer> mQueue;
246
247     /// The type of list of threaded readers
248         typedef std::vector<boost::shared_ptr<ThreadedImageReader> > ThreadedImageReaderListType;
249         //typedef std::vector<ThreadedImageReader* > ThreadedImageReaderListType;
250     ThreadedImageReaderListType mThreadedImageReaderList;
251     /// The number of currently running threaded readers
252     int mNumberOfThreadedReadersRunning;
253     /// The mutex used to access safely internal data from any thread
254     /// LG : Removed ! We now use the embedded mutex in User from which 
255     /// we inherit...
256     //  wxMutex mMutex;
257
258     /// For GetImage : the filename requested
259     std::string mRequestedFilename;
260     /// For GetImage : the image requested
261     vtkImageData* mRequestedImage;
262
263     /// If number of threads == 0 then uses an internal non-threaded reader
264     ImageReader* mReader;
265
266     /// The type of list of images loaded 
267     /// used to unload oldest image when memory limit exceeded
268    /// The image to unload priority queue
269     IndexedHeap<ImageToLoadPtr,
270                 ImageToLoadPtrInversePriorityComparator,
271                 ImageToUnloadPtrIndexer> mUnloadQueue;
272
273     void UpdateUnloadPriority(ImageToLoadPtr p, int priority);
274     long mTotalMem;
275     long mTotalMemMax;
276
277
278   }; // class MultiThreadImageReader
279   //=====================================================================
280
281
282
283 } // namespace creaImageIO
284
285
286
287 #endif // #ifndef __creaImageIOQMultiThreadImageReader_h_INCLUDED__