r599: no message
[ctsim.git] / src / threadraster.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          threadraster.cpp
5 **   Purpose:       Threaded rasterizer class
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  February 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2001 Kevin Rosenberg
11 **
12 **  $Id: threadraster.cpp,v 1.3 2001/03/02 21:32:34 kevin Exp $
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28
29 #if defined(HAVE_CONFIG_H)
30 #include "config.h"
31 #endif
32
33 #include "wx/wxprec.h"
34
35 #ifndef WX_PRECOMP
36 #include "wx/wx.h"
37 #endif
38
39 #include "ct.h"
40 #include "ctsim.h"
41 #include "docs.h"
42 #include "views.h"
43
44
45 #ifdef HAVE_WXTHREADS
46
47
48 #include "threadraster.h"
49 #include "backgroundmgr.h"
50 #include "backgroundsupr.h"
51
52
53 /////////////////////////////////////////////////////////////////////
54 //
55 // Class RasterizerSupervisorThread -- Thread for Background Supervisor
56 //
57 /////////////////////////////////////////////////////////////////////
58
59 RasterizerSupervisorThread::RasterizerSupervisorThread (PhantomFileView* pProjView, int iNX, int iNY, 
60    int iNSample, double dViewRatio, const char* const pszLabel)
61 : m_pPhantomView(pProjView), m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_strLabel(pszLabel),
62   SupervisorThread()
63 {
64 }
65
66 wxThread::ExitCode
67 RasterizerSupervisorThread::Entry()
68 {
69   RasterizerSupervisor rasterSupervisor (this, m_pPhantomView, m_iNX, m_iNY, m_iNSample, m_dViewRatio, m_strLabel.c_str());
70
71   rasterSupervisor.start();
72   while (! rasterSupervisor.isDone() && ! rasterSupervisor.fail()) {
73     Sleep(100);
74     Yield();
75   }
76   if (rasterSupervisor.fail())
77   {
78     wxString msg ("Error starting Rasterizer supervisor: ");
79     msg += rasterSupervisor.getFailMessage().c_str();
80     msg += "\n";
81     wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
82     eventLog.SetString( msg );
83     wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
84   }
85
86   while (! rasterSupervisor.workersDeleted()) {
87     Sleep(50);
88     rasterSupervisor.ProcessPendingEvents();
89   }
90
91   return reinterpret_cast<wxThread::ExitCode>(0);
92 }
93
94 void
95 RasterizerSupervisorThread::OnExit()
96 {
97 }
98
99
100 /////////////////////////////////////////////////////////////////////
101 //
102 // Class RasterizerSupervisor -- A Background Supervisor
103 //
104 /////////////////////////////////////////////////////////////////////
105
106 RasterizerSupervisor::RasterizerSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNX, int iNY, 
107    int iNSample, double dViewRatio, const char* const pszLabel)
108     : m_pPhantomView(pPhantomView), m_pPhantomDoc(pPhantomView->GetDocument()), 
109       m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_pszLabel(pszLabel), 
110       BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), "Rasterizing", iNX)
111 {
112   m_vecpChildImageFiles.reserve (getNumWorkers());
113   for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
114     m_vecpChildImageFiles[iThread] = new ImageFile;
115   }
116
117
118
119 }
120
121 RasterizerSupervisor::~RasterizerSupervisor()
122 {
123   for (int i = 0; i < getNumWorkers(); i++)
124     delete m_vecpChildImageFiles[i];
125 }
126
127 BackgroundWorkerThread*
128 RasterizerSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
129 {
130    RasterizerWorker* pThread = new RasterizerWorker (this, iThread, iStartUnit, iNumUnits);
131    m_vecpChildImageFiles[iThread]->setArraySize (iNumUnits, m_iNY);
132    pThread->SetParameters (m_pPhantomView, m_vecpChildImageFiles[iThread], m_iNX, m_iNY, m_iNSample, m_dViewRatio);
133
134    return pThread;
135 }
136
137 void
138 RasterizerSupervisor::onDone()
139 {
140   wxCriticalSection doneSection;
141   wxCriticalSectionLocker critsect (doneSection);
142
143   ImageFile* pImageFile = getImageFile();
144
145   if (! wxThread::IsMain())
146     wxMutexGuiEnter();
147   ImageFileDocument* pImageDoc = theApp->newImageDoc();
148   if (! pImageDoc) {
149     sys_error (ERR_SEVERE, "Unable to create image file");
150     return;
151   }  
152   pImageDoc->setImageFile (pImageFile);
153   pImageDoc->UpdateAllViews (NULL);
154   if (ImageFileView* imageView = pImageDoc->getView()) {
155     imageView->OnUpdate (imageView, NULL);
156     imageView->getFrame()->SetFocus();
157     imageView->getFrame()->Show(true);
158   }
159   *theApp->getLog() << m_pszLabel << "\n";
160   if (! wxThread::IsMain())
161     wxMutexGuiLeave();
162   pImageFile->labelAdd (m_pszLabel, getTimerEnd());
163   if (theApp->getAskDeleteNewDocs())
164     pImageDoc->Modify (true);
165
166   setDone();
167 }
168
169
170 ImageFile*
171 RasterizerSupervisor::getImageFile()
172 {
173   ImageFile* pImageFile = new ImageFile (m_iNX, m_iNY);
174
175   size_t iColSize = sizeof(ImageFileValue) * m_iNY;
176
177   ImageFileArray globalArray = pImageFile->getArray();
178   int iGlobalCol = 0;
179   for (int iw = 0; iw < getNumWorkers(); iw++) {
180     ImageFileArray childArray = m_vecpChildImageFiles[iw]->getArray();
181     for (int iCol = 0; iCol < m_vecpChildImageFiles[iw]->nx(); iCol++) {
182       memcpy (globalArray[iGlobalCol++], childArray[iCol], iColSize);
183     }
184   }
185   return (pImageFile);
186 }
187
188
189 /////////////////////////////////////////////////////////////////////
190 //
191 // Class RasterizerWorker -- A worker thread
192 //
193 /////////////////////////////////////////////////////////////////////
194
195 void
196 RasterizerWorker::SetParameters (PhantomFileView* pPhantomView, ImageFile* pImageFile, int iNX, int iNY, int iNSample, double dViewRatio)
197 {
198   m_pImageFile = pImageFile;
199   m_iNX = iNX;
200   m_iNY = iNY;
201   m_pPhantomView = pPhantomView;
202   m_iNSample = iNSample;
203   m_dViewRatio = dViewRatio;
204 }
205
206 wxThread::ExitCode
207 RasterizerWorker::Entry ()
208 {
209   const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
210   wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
211   for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
212     if (TestDestroy()) {
213 #ifdef DEBUG
214       if (theApp->getVerboseLogging()) {
215         wxString msg;
216         msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);  
217         wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
218         event.SetString( msg );
219         wxPostEvent( theApp->getMainFrame(), event ); 
220       }
221 #endif
222       break;
223     }
224     rPhantom.convertToImagefile (*m_pImageFile, m_iNX, m_dViewRatio, m_iNSample, Trace::TRACE_NONE, 
225       iUnit + m_iStartUnit, 1, iUnit);
226     wxPostEvent (m_pSupervisor, eventProgress);
227   }
228   wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
229   eventDone.SetInt (m_iThread); // Send back thread# that has finished
230   wxPostEvent (m_pSupervisor, eventDone);
231
232   while (! TestDestroy())
233     Sleep(100);
234
235   return reinterpret_cast<wxThread::ExitCode>(0);
236 }
237
238 void
239 RasterizerWorker::OnExit ()
240 {
241 }
242
243 #endif // HAVE_WXTHREADS