r617: *** empty log 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.12 2001/03/07 21:18:50 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 :   SupervisorThread(), m_pPhantomView(pProjView), m_iNX(iNX), m_iNY(iNY), m_iNSample(iNSample), m_dViewRatio(dViewRatio), m_strLabel(pszLabel)
62 {
63 }
64
65 wxThread::ExitCode
66 RasterizerSupervisorThread::Entry()
67 {
68   RasterizerSupervisor rasterSupervisor (this, m_pPhantomView, m_iNX, m_iNY, m_iNSample, m_dViewRatio, m_strLabel.c_str());
69
70   rasterSupervisor.start();
71
72   while (! rasterSupervisor.workersDone() && ! rasterSupervisor.fail() && ! rasterSupervisor.cancelled()) {
73     Sleep(100);
74   }
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   if (! rasterSupervisor.cancelled())
87     rasterSupervisor.onDone();
88   rasterSupervisor.deleteWorkers();
89
90     return static_cast<wxThread::ExitCode>(0);
91 }
92
93 void
94 RasterizerSupervisorThread::OnExit()
95 {
96 }
97
98
99 /////////////////////////////////////////////////////////////////////
100 //
101 // Class RasterizerSupervisor -- A Background Supervisor
102 //
103 /////////////////////////////////////////////////////////////////////
104
105 RasterizerSupervisor::RasterizerSupervisor (SupervisorThread* pThread, PhantomFileView* pPhantomView, int iNX, int iNY, 
106    int iNSample, double dViewRatio, const char* const pszLabel)
107     : BackgroundSupervisor (pThread, pPhantomView->GetFrame(), pPhantomView->GetDocument(), "Rasterizing", iNX),
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 {
111   m_vecpChildImageFiles.reserve (getNumWorkers());
112   for (int iThread = 0; iThread < getNumWorkers(); iThread++) {
113     m_vecpChildImageFiles[iThread] = new ImageFile;
114   }
115 }
116
117 RasterizerSupervisor::~RasterizerSupervisor()
118 {
119   for (int i = 0; i < getNumWorkers(); i++)
120     delete m_vecpChildImageFiles[i];
121 }
122
123 BackgroundWorkerThread*
124 RasterizerSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
125 {
126    RasterizerWorker* pThread = new RasterizerWorker (this, iThread, iStartUnit, iNumUnits);
127    m_vecpChildImageFiles[iThread]->setArraySize (iNumUnits, m_iNY);
128    pThread->SetParameters (m_pPhantomView, m_vecpChildImageFiles[iThread], m_iNX, m_iNY, m_iNSample, m_dViewRatio);
129
130    return pThread;
131 }
132
133 void
134 RasterizerSupervisor::onDone()
135 {
136   wxCriticalSection doneSection;
137   wxCriticalSectionLocker critsect (doneSection);
138
139   ImageFile* pImageFile = getImageFile();
140   pImageFile->labelAdd (m_pszLabel, getTimerEnd());
141
142   wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
143   wxString msg (m_pszLabel);
144   msg += "\n";
145   eventLog.SetString( msg );
146   wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
147
148   wxCommandEvent newImageEvent (wxEVT_COMMAND_MENU_SELECTED, NEW_IMAGEFILE_EVENT);
149   newImageEvent.SetClientData (pImageFile);
150   wxPostEvent (theApp->getMainFrame(), newImageEvent);
151   
152   setDone();
153 }
154
155
156 ImageFile*
157 RasterizerSupervisor::getImageFile()
158 {
159   ImageFile* pImageFile = new ImageFile (m_iNX, m_iNY);
160
161   size_t iColSize = sizeof(ImageFileValue) * m_iNY;
162
163   ImageFileArray globalArray = pImageFile->getArray();
164   int iGlobalCol = 0;
165   for (int iw = 0; iw < getNumWorkers(); iw++) {
166     ImageFileArray childArray = m_vecpChildImageFiles[iw]->getArray();
167     for (unsigned int iCol = 0; iCol < m_vecpChildImageFiles[iw]->nx(); iCol++) {
168       memcpy (globalArray[iGlobalCol++], childArray[iCol], iColSize);
169     }
170   }
171   return (pImageFile);
172 }
173
174
175 /////////////////////////////////////////////////////////////////////
176 //
177 // Class RasterizerWorker -- A worker thread
178 //
179 /////////////////////////////////////////////////////////////////////
180
181 void
182 RasterizerWorker::SetParameters (PhantomFileView* pPhantomView, ImageFile* pImageFile, int iNX, int iNY, int iNSample, double dViewRatio)
183 {
184   m_pImageFile = pImageFile;
185   m_iNX = iNX;
186   m_iNY = iNY;
187   m_pPhantomView = pPhantomView;
188   m_iNSample = iNSample;
189   m_dViewRatio = dViewRatio;
190 }
191
192 wxThread::ExitCode
193 RasterizerWorker::Entry ()
194 {
195   const Phantom& rPhantom = m_pPhantomView->GetDocument()->getPhantom();
196   wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
197   for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
198     if (TestDestroy()) {
199 #ifdef DEBUG
200       if (theApp->getVerboseLogging()) {
201         wxString msg;
202         msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);  
203         wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
204         event.SetString( msg );
205         wxPostEvent( theApp->getMainFrame(), event ); 
206       }
207 #endif
208       break;
209     }
210     rPhantom.convertToImagefile (*m_pImageFile, m_iNX, m_dViewRatio, m_iNSample, Trace::TRACE_NONE, iUnit + m_iStartUnit, 1, iUnit);
211
212         m_pSupervisor->onWorkerUnitTick();
213   }
214
215   m_pSupervisor->onWorkerDone (m_iThread);
216
217   while (! TestDestroy())
218     Sleep(100);
219
220   return static_cast<wxThread::ExitCode>(0);
221 }
222
223 void
224 RasterizerWorker::OnExit ()
225 {
226 }
227
228 #endif // HAVE_WXTHREADS