1 /*
2     delaboratory - color correction utility
3     Copyright (C) 2011 Jacek Poplawski
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #include "layer_processor_threads.h"
20 #include "layer_processor.h"
21 #include "main_window.h"
22 #include "main_frame.h"
23 #include "layer_frame_manager.h"
24 #include "layer_stack.h"
25 #include "view_manager.h"
26 #include <string>
27 #include "base_layer.h"
28 #include "channel_manager.h"
29 #include "str.h"
30 #include <wx/progdlg.h>
31 #include <iostream>
32 #include "logger.h"
33 #include "renderer.h"
34 #include "image_io.h"
35 
36 class deLayerProcessorWorkerThread:public wxThread
37 {
38     private:
performTasks()39         void performTasks()
40         {
41             while (true)
42             {
43                 if (processor.isClosing())
44                 {
45                     return;
46                 }
47 
48 #ifdef DEBUG_LOG
49                 logInfo("worker thread wait...");
50 #endif
51                 semaphore.wait();
52                 Sleep(10);
53 
54                 if (TestDestroy())
55                 {
56                     return;
57                 }
58 
59                 processor.tickWork();
60 
61                 if (TestDestroy())
62                 {
63                     return;
64                 }
65             }
66         }
67 
Entry()68         virtual void *Entry()
69         {
70             performTasks();
71             logInfo("worker thread finished");
72             return NULL;
73         }
74         deLayerProcessor& processor;
75         deSemaphore& semaphore;
76 
77     public:
deLayerProcessorWorkerThread(deLayerProcessor & _processor,deSemaphore & _semaphore)78         deLayerProcessorWorkerThread(deLayerProcessor& _processor, deSemaphore& _semaphore)
79         :processor(_processor),
80          semaphore(_semaphore)
81         {
82             logInfo("worker thread created");
83         }
~deLayerProcessorWorkerThread()84         virtual ~deLayerProcessorWorkerThread()
85         {
86         }
87 };
88 
89 class deRenderWorkerThread:public wxThread
90 {
91     private:
performTasks()92         void performTasks()
93         {
94             while (true)
95             {
96                 if (processor.isClosing())
97                 {
98                     return;
99                 }
100 
101 #ifdef DEBUG_LOG
102                 logInfo("render thread wait...");
103 #endif
104                 semaphore.wait();
105                 Sleep(10);
106 
107                 if (TestDestroy())
108                 {
109                     return;
110                 }
111 
112                 if (processor.prepareImage())
113                 {
114                     processor.sendRepaintEvent();
115                 }
116 
117                 if (TestDestroy())
118                 {
119                     return;
120                 }
121             }
122         }
123 
Entry()124         virtual void *Entry()
125         {
126             performTasks();
127             logInfo("render thread finished");
128             return NULL;
129         }
130 
131         deLayerProcessor& processor;
132         deSemaphore& semaphore;
133 
134     public:
deRenderWorkerThread(deLayerProcessor & _processor,deSemaphore & _semaphore)135         deRenderWorkerThread(deLayerProcessor& _processor, deSemaphore& _semaphore)
136         :processor(_processor),
137          semaphore(_semaphore)
138         {
139             logInfo("render thread created");
140         }
~deRenderWorkerThread()141         virtual ~deRenderWorkerThread()
142         {
143         }
144 };
145 
146 class deHistogramWorkerThread:public wxThread
147 {
148     private:
performTasks()149         void performTasks()
150         {
151             while (true)
152             {
153                 if (processor.isClosing())
154                 {
155                     return;
156                 }
157 
158 #ifdef DEBUG_LOG
159                 logInfo("histogram thread wait...");
160 #endif
161                 semaphore.wait();
162                 Sleep(10);
163 
164                 if (TestDestroy())
165                 {
166                     return;
167                 }
168 
169                 processor.onGenerateHistogram();
170                 processor.sendHistogramEvent();
171 
172                 if (TestDestroy())
173                 {
174                     return;
175                 }
176             }
177         }
178 
Entry()179         virtual void *Entry()
180         {
181             performTasks();
182             logInfo("histogram thread finished");
183             return NULL;
184         }
185 
186         deLayerProcessor& processor;
187         deSemaphore& semaphore;
188 
189     public:
deHistogramWorkerThread(deLayerProcessor & _processor,deSemaphore & _semaphore)190         deHistogramWorkerThread(deLayerProcessor& _processor, deSemaphore& _semaphore)
191         :processor(_processor),
192          semaphore(_semaphore)
193         {
194             logInfo("histogram thread created");
195         }
~deHistogramWorkerThread()196         virtual ~deHistogramWorkerThread()
197         {
198         }
199 };
200 
201 
202 
stopWorkerThread()203 void deLayerProcessorThreads::stopWorkerThread()
204 {
205     logInfo("stop worker, render and histogram threads");
206 
207     workerSemaphore.post();
208     workerThread->Delete();
209 
210     renderWorkerSemaphore.post();
211     renderWorkerThread->Delete();
212 
213     histogramWorkerSemaphore.post();
214     histogramWorkerThread->Delete();
215 
216     wxThread::Sleep(200);
217 
218     logInfo("stopped worker, render and histogram threads");
219 
220 }
221 
startWorkerThread()222 void deLayerProcessorThreads::startWorkerThread()
223 {
224     logInfo("start worker, render and histogram threads");
225 
226     workerThread = new deLayerProcessorWorkerThread(layerProcessor, workerSemaphore);
227 
228     if ( workerThread->Create() != wxTHREAD_NO_ERROR )
229     {
230     }
231 
232     if ( workerThread->Run() != wxTHREAD_NO_ERROR )
233     {
234     }
235 
236     renderWorkerThread = new deRenderWorkerThread(layerProcessor, renderWorkerSemaphore);
237 
238     if ( renderWorkerThread->Create() != wxTHREAD_NO_ERROR )
239     {
240     }
241 
242     if ( renderWorkerThread->Run() != wxTHREAD_NO_ERROR )
243     {
244     }
245 
246     histogramWorkerThread = new deHistogramWorkerThread(layerProcessor, histogramWorkerSemaphore);
247 
248     if ( histogramWorkerThread->Create() != wxTHREAD_NO_ERROR )
249     {
250     }
251 
252     if ( histogramWorkerThread->Run() != wxTHREAD_NO_ERROR )
253     {
254     }
255 
256     logInfo("started worker, render and histogram threads");
257 }
258 
259