* ctsim: Added tips to be displayed at startup and via the help menu.
- * ctsim: Added threaded reconstructions for background
- processing as well as taking advantage of multiple-CPU's
+ * ctsim: Added generic threaded tasks and background manager for
+ background processing as well as taking advantage of multiple-CPU's
on SMP systems.
+
+ * ctsim: Added background and SMP processing for reconstructions.
* ctsim: Added "Verbose Logging", "Startup Tips", and
"Background processes" options to Preferences dialog.
* ctsim: Added accelerator key for File-Properties
+ * views.cpp: Added out of memory checks to display for huge
+ image and projection files.
+
+ * distribution: fixed problem with documentation files not
+ being included with the distribution [Reported by Ian Kay].
+
3.0.3 - Released 2/20/01
* ctsim: Fixed core dump on Linux with OpenGL
# End Source File
# Begin Source File
+SOURCE=..\..\src\backgroundsupr.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\..\src\ctsim.cpp
# ADD CPP /D CTSIMVERSION=\"3.0.0alpha5\"
# End Source File
# End Source File
# Begin Source File
+SOURCE=..\..\src\backgroundsupr.h
+# End Source File
+# Begin Source File
+
SOURCE="..\..\src\ctsim-map.h"
# End Source File
# Begin Source File
--------------------Configuration: ctsim - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19D.tmp" with contents
-[
-/nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "\wx2.2.5\include" /I "..\..\..\fftw-2.1.3\fftw" /I "\wx2.2.5\src\png" /I "\wx2.2.5\src\zlib" /I "..\..\include" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\rfftw" /D VERSION=\"3.0.0beta1\" /D "_DEBUG" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D CTSIMVERSION=\"3.0.4\" /D CTSIMVERSION=\"3.0.0alpha5\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
-"C:\ctsim\src\docs.cpp"
-]
-Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19D.tmp"
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19E.tmp" with contents
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP21E.tmp" with contents
[
/nologo /G6 /MTd /W3 /Gm /Gi /GR /GX /Zi /Od /Gy /I "\wx2.2.5\include" /I "..\..\..\fftw-2.1.3\fftw" /I "\wx2.2.5\src\png" /I "\wx2.2.5\src\zlib" /I "..\..\include" /I "..\..\getopt" /I "..\..\..\fftw-2.1.3\rfftw" /D VERSION=\"3.0.0beta1\" /D "_DEBUG" /D "__WXMSW__" /D "HAVE_SGP" /D "HAVE_PNG" /D "HAVE_WXWINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "HAVE_STRING_H" /D "HAVE_FFTW" /D "HAVE_RFFTW" /D "HAVE_GETOPT_H" /D "MSVC" /D "__WIN95__" /D "__WIN32__" /D WINVER=0x0400 /D "STRICT" /D CTSIMVERSION=\"3.0.4\" /FR"Debug/" /Fp"Debug/ctsim.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
-"C:\ctsim\src\threadrecon.cpp"
+"C:\ctsim\src\backgroundsupr.cpp"
]
-Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19E.tmp"
-Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19F.tmp" with contents
+Creating command line "cl.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP21E.tmp"
+Creating temporary file "C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP21F.tmp" with contents
[
winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\..\..\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib ..\..\..\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib wxd.lib xpmd.lib tiffd.lib zlibd.lib pngd.lib comctl32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib opengl32.lib glu32.lib htmlhelp.lib /nologo /subsystem:windows /incremental:yes /pdb:"Debug/ctsim.pdb" /debug /machine:I386 /out:"Debug/ctsim.exe" /pdbtype:sept /libpath:"\wx2.2.5\lib"
.\Debug\backgroundmgr.obj
.\Debug\tips.obj
.\Debug\views.obj
.\Debug\ctsim.res
+.\Debug\backgroundsupr.obj
\ctsim\msvc\libctsim\Debug\libctsim.lib
"\fftw-2.1.3\Win32\FFTW2st\Debug\FFTW2st.lib"
"\fftw-2.1.3\Win32\RFFTW2st\Debug\RFFTW2st.lib"
\wx2.2.5\lib\zlibd.lib
\wx2.2.5\lib\tiffd.lib
]
-Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP19F.tmp"
+Creating command line "link.exe @C:\DOCUME~1\kevin\LOCALS~1\Temp\RSP21F.tmp"
<h3>Output Window</h3>
Compiling...
-docs.cpp
-Compiling...
-threadrecon.cpp
+backgroundsupr.cpp
Linking...
** This is part of the CTSim program
** Copyright (C) 1983-2001 Kevin Rosenberg
**
-** $Id: backgroundmgr.cpp,v 1.5 2001/02/23 21:58:31 kevin Exp $
+** $Id: backgroundmgr.cpp,v 1.6 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
#include "ctsim.h"
#include "docs.h"
#include "views.h"
-#include "threadrecon.h"
+#include "backgroundsupr.h"
#include "backgroundmgr.h"
m_iNumTasks++;
resizeWindow();
- Show(true);
+ if (m_iNumTasks == 1) {
+ theApp->getMainFrame()->SetFocus(); // necessary to keep wxWindows from crashing
+ Show(true);
+ theApp->getMainFrame()->SetFocus(); // necessary to keep wxWindows from crashing
+ }
}
void
{
wxGauge* pGauge = NULL;
int i = 0;
+
+ wxCriticalSectionLocker locker (m_criticalSection);
for (TaskContainer::iterator iTask = m_vecpBackgroundTasks.begin(); iTask != m_vecpBackgroundTasks.end(); iTask++) {
if (*iTask == pTask) {
pGauge = m_vecpGauges[i];
--- /dev/null
+/*****************************************************************************
+** FILE IDENTIFICATION
+**
+** Name: BackgroundSupr.cpp
+** Purpose: Background Supervisor classes
+** Programmer: Kevin Rosenberg
+** Date Started: February 2001
+**
+** This is part of the CTSim program
+** Copyright (C) 1983-2001 Kevin Rosenberg
+**
+** $Id: backgroundsupr.cpp,v 1.1 2001/02/25 06:32:12 kevin Exp $
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License (version 2) as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+******************************************************************************/
+
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "ct.h"
+#include "ctsim.h"
+#include "docs.h"
+#include "views.h"
+#include "backgroundsupr.h"
+#include "backgroundmgr.h"
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Class BackgroundSupervisor -- An event handler run by a SupervisorThread
+//
+////////////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_DYNAMIC_CLASS(BackgroundSupervisor, wxEvtHandler)
+BEGIN_EVENT_TABLE(BackgroundSupervisor, BackgroundSupervisor)
+EVT_MENU(MSG_BACKGROUND_SUPERVISOR_CANCEL, BackgroundSupervisor::OnCancel)
+EVT_MENU(MSG_WORKER_THREAD_FAIL, BackgroundSupervisor::OnWorkerFail)
+EVT_MENU(MSG_WORKER_THREAD_DONE, BackgroundSupervisor::OnWorkerDone)
+EVT_MENU(MSG_WORKER_THREAD_UNIT_TICK, BackgroundSupervisor::OnWorkerUnitTick)
+EVT_MENU(MSG_DOCUMENT_ACK_REMOVE, BackgroundSupervisor::OnAckDocumentRemove)
+END_EVENT_TABLE()
+
+// Static function
+void
+BackgroundSupervisor::cancelSupervisor (BackgroundSupervisor* pSupervisor)
+{
+ wxCommandEvent cancelEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_CANCEL);
+ wxPostEvent (pSupervisor, cancelEvent);
+}
+
+
+BackgroundSupervisor::BackgroundSupervisor (wxFrame* pParentFrame, wxDocument* pDocument, const char* const pszProcessTitle, int iTotalUnits)
+ : m_pParentFrame(pParentFrame), m_pDocument(pDocument), m_pDialogProgress(NULL), m_strProcessTitle(pszProcessTitle),
+ m_iTotalUnits(iTotalUnits), m_iNumThreads(0), m_bDone(false), m_bFail(false), m_bCancelled(false),
+ m_pTimer(NULL), m_bBackgroundTaskAdded(false),
+ wxEvtHandler()
+{
+ m_iNumThreads = theApp->getNumberCPU();
+ // ++m_iNumThreads;
+
+ m_vecpThreads.reserve (m_iNumThreads);
+ for (int iThread = 0; iThread < m_iNumThreads; iThread++)
+ m_vecpThreads[iThread] = NULL;
+
+}
+
+BackgroundSupervisor::~BackgroundSupervisor()
+{
+ if (m_bBackgroundTaskAdded) {
+ wxCommandEvent doneEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_REMOVE);
+ doneEvent.SetClientData (this);
+ wxPostEvent (theApp->getBackgroundManager(), doneEvent);
+ wxPostEvent (m_pDocument, doneEvent);
+ }
+
+ while (m_bBackgroundTaskAdded) {
+ Sleep(50);
+ ::wxYield();
+ }
+
+ delete m_pTimer;
+ delete m_pDialogProgress;
+}
+
+void
+BackgroundSupervisor::deleteAnyWorkers()
+{
+ m_critsectThreadContainer.Enter();
+ for (int i = 0; i < m_iNumThreads; i++)
+ if (m_vecpThreads[i]) {
+ m_vecpThreads[i]->Delete(); // sends Destroy message to workers
+ }
+ m_critsectThreadContainer.Leave();
+
+ while (m_iRunning > 0) {
+ Sleep(50);
+ ::wxYield();
+ }
+}
+
+
+bool
+BackgroundSupervisor::start()
+{
+ int iBaseUnits = m_iTotalUnits / m_iNumThreads;
+ int iExtraUnits = m_iTotalUnits % m_iNumThreads;
+ for (int iThread = 0; iThread < m_iNumThreads; iThread++) {
+ int iStartUnit = iThread * iBaseUnits;
+ int iNumUnits = iBaseUnits;
+ if (iThread < iExtraUnits)
+ ++iNumUnits;
+ m_vecpThreads[iThread] = createWorker (iThread, iStartUnit, iNumUnits);
+ if (! m_vecpThreads[iThread]) {
+ m_bFail = true;
+ m_strFailMessage = "createWorker returned NULL [BackgroundSupervisor]";
+ break;
+ }
+ if (m_vecpThreads[iThread]->Create () != wxTHREAD_NO_ERROR) {
+ m_bFail = true;
+ m_strFailMessage = "Thread creation failed [BackgroundSupervisor]";
+ break;
+ }
+ m_vecpThreads[iThread]->SetPriority (40);
+ }
+ if (m_bFail)
+ return false;
+
+ m_pTimer = new Timer;
+
+ if (! theApp->getUseBackgroundTasks())
+ m_pDialogProgress = new wxProgressDialog (_T("Filtered Backprojection"), _T("Reconstruction Progress"),
+ m_iTotalUnits, m_pParentFrame, wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
+ else {
+ std::string strLabel (m_strProcessTitle);
+ strLabel += " ";
+ strLabel += m_pParentFrame->GetTitle();
+ wxCommandEvent addTaskEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_ADD);
+ addTaskEvent.SetString (strLabel.c_str());
+ addTaskEvent.SetInt (m_iTotalUnits);
+ addTaskEvent.SetClientData (this);
+ wxPostEvent (theApp->getBackgroundManager(), addTaskEvent);
+ wxPostEvent (m_pDocument, addTaskEvent);
+ m_bBackgroundTaskAdded = true;
+ }
+
+ m_iRunning = m_iNumThreads;
+ m_iUnitsDone = 0;
+
+ for (int i = 0; i < m_iNumThreads; i++)
+ m_vecpThreads[i]->Run();
+
+ return true;
+}
+
+void
+BackgroundSupervisor::OnCancel(wxCommandEvent& event)
+{
+ m_bCancelled = true;
+ deleteAnyWorkers();
+ m_bDone = true;
+}
+
+void
+BackgroundSupervisor::OnAckDocumentRemove(wxCommandEvent& event)
+{
+ m_bBackgroundTaskAdded = false;
+}
+
+void
+BackgroundSupervisor::OnWorkerUnitTick (wxCommandEvent& event)
+{
+ ++m_iUnitsDone;
+
+#ifdef DEBUG
+ if (theApp->getVerboseLogging())
+ *theApp->getLog() << "Units done: " << static_cast<int>(m_iUnitsDone) <<"\n";
+#endif
+
+ if (m_pDialogProgress) {
+ if (! m_pDialogProgress->Update (m_iUnitsDone - 1)) {
+ wxCommandEvent dummy;
+ OnCancel (dummy);
+ }
+ } else {
+ wxCommandEvent addTaskEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_UNIT_TICK);
+ addTaskEvent.SetInt (m_iUnitsDone - 1);
+ addTaskEvent.SetClientData (this);
+ wxPostEvent (theApp->getBackgroundManager(), addTaskEvent);
+ }
+}
+
+void
+BackgroundSupervisor::OnWorkerDone (wxCommandEvent& event)
+{
+ m_iRunning--;
+ wxASSERT (m_iRunning >= 0);
+ m_critsectThreadContainer.Enter();
+ m_vecpThreads[event.GetInt()] = NULL;
+ m_critsectThreadContainer.Leave();
+
+#ifdef DEBUG
+ if (theApp->getVerboseLogging()) {
+ wxString msg;
+ msg.Printf("Background Supervisor: Thread finished. Remaining threads: %d\n", m_iRunning);
+ wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+ eventLog.SetString( msg );
+ wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
+ }
+#endif
+ if (m_iRunning <= 0 && ! m_bCancelled)
+ onDone();
+}
+
+void
+BackgroundSupervisor::OnWorkerFail (wxCommandEvent& event)
+{
+ m_iRunning--;
+ m_critsectThreadContainer.Enter();
+ m_vecpThreads[event.GetInt()] = NULL;
+ m_critsectThreadContainer.Leave();
+ wxCommandEvent eventLog( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+ eventLog.SetString( event.GetString() );
+ wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
+
+ onDone();
+}
+
--- /dev/null
+/*****************************************************************************
+** FILE IDENTIFICATION
+**
+** Name: backgroundsupr.h
+** Purpose: Header file for background supervisors
+** Programmer: Kevin Rosenberg
+** Date Started: February 2001
+**
+** This is part of the CTSim program
+** Copyright (C) 1983-2001 Kevin Rosenberg
+**
+** $Id: backgroundsupr.h,v 1.1 2001/02/25 06:32:12 kevin Exp $
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License (version 2) as
+** published by the Free Software Foundation.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+******************************************************************************/
+
+#ifndef _BACKGROUNDSUPR_H
+#define _BACKGROUNDSUPR_H
+
+#include <vector>
+#include <wx/thread.h>
+#include <wx/progdlg.h>
+#include "timer.h"
+
+// This thread creates a SupervisorTask event handler object
+// The thread is detached and terminates when SupervisorTask terminates
+class SupervisorThread : public wxThread {
+private:
+
+public:
+ SupervisorThread()
+ : wxThread(wxTHREAD_DETACHED)
+ {}
+
+};
+
+
+// Pure virtual class for BackgroundSupervisor that can communication
+// with BackgroundManager via messages
+class BackgroundWorkerThread;
+
+class BackgroundSupervisor : public wxEvtHandler {
+private:
+ DECLARE_DYNAMIC_CLASS(BackgroundSupervisor)
+
+ typedef std::vector<BackgroundWorkerThread*> ThreadContainer;
+ ThreadContainer m_vecpThreads;
+ wxCriticalSection m_critsectThreadContainer;
+ wxFrame* m_pParentFrame;
+ wxDocument* m_pDocument;
+ const std::string m_strProcessTitle;
+ wxProgressDialog* m_pDialogProgress;
+
+ volatile bool m_bFail;
+ std::string m_strFailMessage;
+ int m_iNumThreads;
+ volatile int m_iRunning;
+ unsigned int m_iUnitsDone;
+ const unsigned int m_iTotalUnits;
+ bool m_bCancelled;
+ bool m_bDone;
+ Timer* m_pTimer;
+ bool m_bBackgroundTaskAdded;
+
+public:
+ enum {
+ MSG_BACKGROUND_SUPERVISOR_ADD = 7500, // sends to BackgroundManager and Document
+ MSG_BACKGROUND_SUPERVISOR_REMOVE = 7501, // sends to BackgroundManager and Document
+ MSG_BACKGROUND_SUPERVISOR_UNIT_TICK = 7502, // sends to BackgroundManager for progress bars
+ MSG_BACKGROUND_SUPERVISOR_CANCEL = 7503, // *sent* to Supervisor to cancel process
+ MSG_DOCUMENT_ACK_REMOVE = 7504,
+
+ MSG_WORKER_THREAD_UNIT_TICK = 7505,
+ MSG_WORKER_THREAD_DONE = 7506,
+ MSG_WORKER_THREAD_FAIL = 7507, // sent by workers when they fail
+ };
+
+ BackgroundSupervisor (wxFrame* pParentFrame, wxDocument* pDocument, const char* const pszProcessTitle,
+ int iTotalUnits);
+
+ BackgroundSupervisor ()
+ : m_iTotalUnits(0), wxEvtHandler()
+ {}
+
+ virtual ~BackgroundSupervisor();
+
+ virtual BackgroundWorkerThread* createWorker (int iThread, int iStartUnit, int iNumUnits)
+ { return NULL; }
+
+ bool start();
+ void deleteAnyWorkers();
+ virtual void onDone() {};
+
+ virtual void OnWorkerFail(wxCommandEvent& event);
+ virtual void OnWorkerUnitTick(wxCommandEvent& event);
+ virtual void OnWorkerDone(wxCommandEvent& event);
+ virtual void OnCancel(wxCommandEvent& event);
+ virtual void OnAckDocumentRemove(wxCommandEvent& event);
+
+ bool anyWorkersRunning() const { return m_iRunning > 0 ? true : false; }
+ bool isDone() const {return m_bDone;}
+ void setDone() { m_bDone = true; }
+ bool fail() const {return m_bFail;}
+ const std::string& getFailMessage() const { return m_strFailMessage; }
+
+ int getNumWorkers() const { return m_iNumThreads; }
+ double getTimerEnd() { return m_pTimer->timerEnd(); }
+
+ static void cancelSupervisor (BackgroundSupervisor* pSupervisor);
+
+ DECLARE_EVENT_TABLE()
+};
+
+
+class BackgroundWorkerThread : public wxThread {
+protected:
+ BackgroundSupervisor* m_pSupervisor;
+ const int m_iStartUnit;
+ const int m_iNumUnits;
+ const int m_iThread;
+
+public:
+ BackgroundWorkerThread (BackgroundSupervisor* pSupervisor, int iThread, int iStartUnit, int iNumUnits)
+ : m_pSupervisor(pSupervisor), m_iThread(iThread), m_iStartUnit(iStartUnit), m_iNumUnits(iNumUnits),
+ wxThread (wxTHREAD_DETACHED)
+ {}
+};
+
+#endif // _BACKGROUNDSUPR_H_
\ No newline at end of file
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: dialogs.cpp,v 1.42 2001/02/22 18:22:40 kevin Exp $
+** $Id: dialogs.cpp,v 1.43 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
pTopSizer->Add (m_pCBStartupTips, 0, wxALIGN_CENTER_VERTICAL);
m_pCBUseBackgroundTasks = new wxCheckBox (this, -1, "Put Tasks in Background", wxDefaultPosition, wxSize(250, 25), 0);
- m_pCBUseBackgroundTasks->SetValue (bStartupTips);
+ m_pCBUseBackgroundTasks->SetValue (bUseBackgroundTasks);
pTopSizer->Add (m_pCBUseBackgroundTasks, 0, wxALIGN_CENTER_VERTICAL);
pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5);
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: docs.cpp,v 1.27 2001/02/23 21:58:31 kevin Exp $
+** $Id: docs.cpp,v 1.28 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
ProjectionFileDocument::~ProjectionFileDocument()
{
+ m_criticalSection.Enter();
for (BackgroundContainer::iterator i = m_vecpBackgroundSupervisors.begin();
- i != m_vecpBackgroundSupervisors.end(); i++) {
+ i != m_vecpBackgroundSupervisors.end(); i++)
BackgroundSupervisor::cancelSupervisor(*i);
- }
-
- while (m_vecpBackgroundSupervisors.size() > 0)
- ::wxYield();
+ m_criticalSection.Leave();
+
+ while (m_vecpBackgroundSupervisors.size() > 0) {
+ ::wxUsleep(50);
+ ::wxYield();
+ }
delete m_pProjectionFile;
}
BackgroundSupervisor* pSupervisor = reinterpret_cast<BackgroundSupervisor*>(event.GetClientData());
wxASSERT (pSupervisor != NULL);
- wxCriticalSectionLocker locker (m_criticalSection);
+ m_criticalSection.Enter();
bool bFound = false;
for (BackgroundContainer::iterator i = m_vecpBackgroundSupervisors.begin();
i != m_vecpBackgroundSupervisors.end();
bFound = true;
break;
}
- if (! bFound)
+ m_criticalSection.Leave();
+
+ if (! bFound)
sys_error (ERR_SEVERE, "Could not find background task [ProjectionFileDocument::removeBackgroundTask");
+
+ wxCommandEvent ackEvent (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_DOCUMENT_ACK_REMOVE);
+ wxPostEvent (pSupervisor, ackEvent);
}
bool
** This is part of the CTSim program
** Copyright (C) 1983-2001 Kevin Rosenberg
**
-** $Id: threadrecon.cpp,v 1.7 2001/02/23 21:58:32 kevin Exp $
+** $Id: threadrecon.cpp,v 1.8 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
#include "views.h"
#include "threadrecon.h"
#include "backgroundmgr.h"
+#include "backgroundsupr.h"
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
-IMPLEMENT_DYNAMIC_CLASS(ReconstructorSupervisor, BackgroundSupervisor)
-BEGIN_EVENT_TABLE(ReconstructorSupervisor, BackgroundSupervisor)
-EVT_MENU(MSG_BACKGROUND_SUPERVISOR_CANCEL, ReconstructorSupervisor::OnCancel)
-EVT_MENU(MSG_WORKER_THREAD_FAIL, ReconstructorSupervisor::OnWorkerFail)
-EVT_MENU(MSG_WORKER_THREAD_DONE, ReconstructorSupervisor::OnWorkerDone)
-EVT_MENU(MSG_WORKER_THREAD_UNIT_TICK, ReconstructorSupervisor::OnWorkerUnitTick)
-END_EVENT_TABLE()
+/////////////////////////////////////////////////////////////////////
+//
+// Class ReconstructorSupervisorThread -- Thread for Background Supervisor
+//
+/////////////////////////////////////////////////////////////////////
-ReconstructorSupervisor::ReconstructorSupervisor (ProjectionFileView* pProjView,
- int iImageNX, int iImageNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod,
- int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
- const char* pszBackprojectName, const char* const pszLabel)
- : m_pDialogProgress(NULL), m_bFail(false), m_iNumThreads(0), m_iImageNX(iImageNX),
- m_iImageNY(iImageNY), m_strLabel(pszLabel), m_pTimer(NULL), m_bCancelled(false), m_bCancelling(false),
- BackgroundSupervisor()
+ReconstructorSupervisorThread::ReconstructorSupervisorThread (ProjectionFileView* pProjView, int iNX, int iNY,
+ const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
+ const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
+ const char* pszBackprojectName, const char* const pszLabel)
+: m_pProjView(pProjView), m_iNX(iNX), m_iNY(iNY), m_strFilterName(pszFilterName), m_dFilterParam(dFilterParam),
+ m_strFilterMethod(pszFilterMethod), m_iZeropad(iZeropad), m_strFilterGenerationName(pszFilterGenerationName),
+ m_strInterpName(pszInterpName), m_iInterpParam(iInterpParam), m_strBackprojectName(pszBackprojectName), m_strLabel(pszLabel),
+ SupervisorThread()
{
- m_iNumThreads = theApp->getNumberCPU();
- // ++m_iNumThreads;
- m_iTotalViews = pProjView->GetDocument()->getProjections().nView();
- int iBaseViews = m_iTotalViews / m_iNumThreads;
- int iExtraViews = m_iTotalViews % m_iNumThreads;
-
- m_vecpChildImageFile.reserve (m_iNumThreads);
- m_vecpThread.reserve (m_iNumThreads);
-
- for (unsigned int iProc = 0; iProc < m_iNumThreads; iProc++) {
- m_vecpChildImageFile[iProc] = new ImageFile (iImageNX, iImageNY);
-
- int iStartView = iProc * iBaseViews;
- int iNumViews = iBaseViews;
- if (iProc < iExtraViews)
- ++iNumViews;
- m_vecpThread[iProc] = new ReconstructorWorker (this, pProjView, m_vecpChildImageFile[iProc], iProc, iStartView, iNumViews,
- pszFilterName, dFilterParam, pszFilterMethod, iZeropad, pszFilterGenerationName, pszInterpName, iInterpParam, pszBackprojectName);
- if (m_vecpThread[iProc]->Create () != wxTHREAD_NO_ERROR) {
- m_bFail = true;
- break;
- }
+}
+
+wxThread::ExitCode
+ReconstructorSupervisorThread::Entry()
+{
+ ReconstructorSupervisor reconSupervisor (m_pProjView, m_iNX, m_iNY,
+ m_strFilterName.c_str(), m_dFilterParam, m_strFilterMethod.c_str(), m_iZeropad, m_strFilterGenerationName.c_str(),
+ m_strInterpName.c_str(), m_iInterpParam, m_strBackprojectName.c_str(), m_strLabel.c_str());
+
+ reconSupervisor.start();
+ while (! reconSupervisor.isDone() && ! reconSupervisor.fail()) {
+ Sleep(50);
+ Yield();
+ }
+ if (reconSupervisor.fail())
+ {
+ wxString msg ("Error starting reconstructor supervisor: ");
+ msg += reconSupervisor.getFailMessage().c_str();
+ msg += "\n";
+ wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+ eventLog.SetString( msg );
+ wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
+ }
+
+ while (reconSupervisor.anyWorkersRunning()) {
+ Sleep(50);
+ Yield();
}
- m_pProjView = pProjView;
- m_pProjDoc = pProjView->GetDocument();
+
+ return reinterpret_cast<wxThread::ExitCode>(0);
}
-// Static function
-void
-BackgroundSupervisor::cancelSupervisor (BackgroundSupervisor* pSupervisor)
+void
+ReconstructorSupervisorThread::OnExit()
{
- wxCommandEvent cancelEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_CANCEL);
- wxPostEvent (pSupervisor, cancelEvent);
}
-bool
-ReconstructorSupervisor::start()
+/////////////////////////////////////////////////////////////////////
+//
+// Class ReconstructorSupervisor -- A Background Supervisor
+//
+/////////////////////////////////////////////////////////////////////
+
+ReconstructorSupervisor::ReconstructorSupervisor (ProjectionFileView* pProjView,
+ int iImageNX, int iImageNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod,
+ int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
+ const char* pszBackprojectName, const char* const pszLabel)
+ : m_pProjView(pProjView), m_pProjDoc(pProjView->GetDocument()),
+ m_iImageNX(iImageNX), m_iImageNY(iImageNY),
+ m_pszFilterName(pszFilterName), m_dFilterParam(dFilterParam), m_pszFilterMethod(pszFilterMethod),
+ m_iZeropad(iZeropad), m_pszFilterGenerationName(pszFilterGenerationName), m_pszInterpName(pszInterpName),
+ m_iInterpParam(iInterpParam), m_pszBackprojectName(pszBackprojectName), m_pszLabel(pszLabel),
+ BackgroundSupervisor (pProjView->GetFrame(), pProjView->GetDocument(), "Reconstructing", pProjView->GetDocument()->getProjections().nView())
{
- if (m_bFail)
- return false;
-
- if (! theApp->getUseBackgroundTasks())
- m_pDialogProgress = new wxProgressDialog (_T("Filtered Backprojection"), _T("Reconstruction Progress"), m_iTotalViews, m_pProjView->getFrame(), wxPD_CAN_ABORT | wxPD_AUTO_HIDE);
- else {
- std::string strLabel ("Reconstructing ");
- strLabel += m_pProjView->GetFrame()->GetTitle();
- wxCommandEvent addTaskEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_ADD);
- addTaskEvent.SetString (strLabel.c_str());
- addTaskEvent.SetInt (m_iTotalViews);
- addTaskEvent.SetClientData (this);
- wxPostEvent (theApp->getBackgroundManager(), addTaskEvent);
- wxPostEvent (m_pProjDoc, addTaskEvent);
+ m_vecpChildImageFile.reserve (getNumWorkers());
+ for (unsigned int iThread = 0; iThread < getNumWorkers(); iThread++) {
+ m_vecpChildImageFile[iThread] = new ImageFile (iImageNX, iImageNY);
}
-
- m_iRunning = m_iNumThreads;
- m_iViewsDone = 0;
- m_pTimer = new Timer;
-
- // starting all threads
- for (int i = 0; i < m_iNumThreads; i++)
- m_vecpThread[i]->Run();
-
- return true;
-}
-void
-ReconstructorSupervisor::OnCancel(wxCommandEvent& event)
-{
- if (isDone() || m_bCancelled)
- return;
- m_bCancelled = true;
- m_bCancelling = false;
- cleanUp();
}
-void
-ReconstructorSupervisor::cleanUp()
+ReconstructorSupervisor::~ReconstructorSupervisor()
{
- wxCriticalSection cleanSection;
- cleanSection.Enter();
-
- m_critsectThreadContainer.Enter();
- for (int i = 0; i < m_iNumThreads; i++)
- if (m_vecpThread[i] && m_vecpThread[i]->IsRunning()) {
- m_vecpThread[i]->Pause();
- m_vecpThread[i]->Delete();
- }
-
- for (i = 0; i < m_iNumThreads; i++) {
+ for (int i = 0; i < getNumWorkers(); i++) {
delete m_vecpChildImageFile[i];
m_vecpChildImageFile[i] = NULL;
}
- m_critsectThreadContainer.Leave();
-
- m_iNumThreads = 0;
- m_iRunning = 0;
- delete m_pDialogProgress;
- delete m_pTimer;
- m_pDialogProgress = NULL;
- setDone();
-
- wxCommandEvent doneEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_REMOVE);
- doneEvent.SetClientData (this);
- wxPostEvent (theApp->getBackgroundManager(), doneEvent);
- wxPostEvent (m_pProjDoc, doneEvent);
-
- cleanSection.Leave();
+
+}
+
+BackgroundWorkerThread*
+ReconstructorSupervisor::createWorker (int iThread, int iStartUnit, int iNumUnits)
+{
+ ReconstructorWorker* pThread = new ReconstructorWorker (this, iThread, iStartUnit, iNumUnits);
+ pThread->SetParameters (m_pProjView, m_vecpChildImageFile[iThread], m_pszFilterName, m_dFilterParam,
+ m_pszFilterMethod, m_iZeropad, m_pszFilterGenerationName, m_pszInterpName,
+ m_iInterpParam, m_pszBackprojectName);
+
+ return pThread;
}
void
ReconstructorSupervisor::onDone()
{
wxCriticalSection doneSection;
- doneSection.Enter();
-
+ wxCriticalSectionLocker critsect (doneSection);
ImageFileDocument* pReconDoc = theApp->newImageDoc();
if (! pReconDoc) {
sys_error (ERR_SEVERE, "Unable to create image file");
- doneSection.Leave();
return;
}
rasterView->getFrame()->SetFocus();
rasterView->getFrame()->Show(true);
}
- *theApp->getLog() << m_strLabel << "\n";
+ *theApp->getLog() << m_pszLabel << "\n";
pImageFile->labelAdd (m_pProjView->GetDocument()->getProjections().getLabel());
- pImageFile->labelAdd (m_strLabel.c_str(), m_pTimer->timerEnd());
-
- doneSection.Leave();
- cleanUp();
-}
-
-void
-ReconstructorSupervisor::OnWorkerUnitTick (wxCommandEvent& event)
-{
- ++m_iViewsDone;
-
-#ifdef DEBUG
- if (theApp->getVerboseLogging())
- *theApp->getLog() << "Views done: " << static_cast<int>(m_iViewsDone) <<"\n";
-#endif
-
- if (m_pDialogProgress)
- m_bCancelling = ! m_pDialogProgress->Update (m_iViewsDone - 1);
- else {
- wxCommandEvent addTaskEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_UNIT_TICK);
- addTaskEvent.SetInt (m_iViewsDone - 1);
- addTaskEvent.SetClientData (this);
- wxPostEvent (theApp->getBackgroundManager(), addTaskEvent);
- }
-}
-
-void
-ReconstructorSupervisor::OnWorkerDone (wxCommandEvent& event)
-{
- m_iRunning--;
- wxASSERT (m_iRunning >= 0);
- m_critsectThreadContainer.Enter();
- m_vecpThread[event.GetInt()] = NULL;
- m_critsectThreadContainer.Leave();
+ pImageFile->labelAdd (m_pszLabel, getTimerEnd());
-#ifdef DEBUG
- if (theApp->getVerboseLogging()) {
- wxString msg;
- msg.Printf("Reconstructor Supervisor: Thread finished. Remaining threads: %d\n", m_iRunning);
- wxCommandEvent eventLog (wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
- eventLog.SetString( msg );
- wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
- }
-#endif
- if (m_iRunning <= 0) {
- onDone();
- return;
- }
+ setDone();
}
-void
-ReconstructorSupervisor::OnWorkerFail (wxCommandEvent& event)
-{
- if (isDone())
- return;
-
- m_iRunning--;
- m_critsectThreadContainer.Enter();
- m_vecpThread[event.GetInt()] = NULL;
- m_critsectThreadContainer.Leave();
- wxCommandEvent eventLog( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
- eventLog.SetString( event.GetString() );
- wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
-
- onDone();
-}
-
-
ImageFile*
ReconstructorSupervisor::getImageFile()
ImageFileArray pArray = pImageFile->getArray();
int i;
- for (i = 0; i < m_iNumThreads; i++) {
+ for (i = 0; i < getNumWorkers(); i++) {
ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray();
for (int ix = 0; ix < m_iImageNX; ix++)
for (int iy = 0; iy < m_iImageNY; iy++)
return (pImageFile);
}
-bool
-ReconstructorSupervisor::testDone()
-{
- return (m_iRunning <= 0 ? true : false);
-}
+/////////////////////////////////////////////////////////////////////
+//
+// Class ReconstructorWorker -- A worker thread
+//
+/////////////////////////////////////////////////////////////////////
-ReconstructorSupervisor::~ReconstructorSupervisor()
-{
-}
-
-
-ReconstructorWorker::ReconstructorWorker
-(ReconstructorSupervisor* pSupervisor, ProjectionFileView* pProjView, ImageFile* pImageFile, int iThread, int iStartView, int iNumViews,
- const char* pszFilterName, double dFilterParam, const char* pszFilterMethod,
- int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
- const char* pszBackprojectName)
- : m_pSupervisor(pSupervisor), m_iStartView(iStartView), m_iNumViews(iNumViews), m_iThread(iThread),
- m_pProjView(pProjView), m_pImageFile(pImageFile), m_strFilterName(pszFilterName), m_dFilterParam(dFilterParam), m_strFilterMethod(pszFilterMethod),
- m_iZeropad(iZeropad), m_strFilterGenerationName(pszFilterGenerationName), m_strInterpName(pszInterpName),
- m_iInterpParam(iInterpParam), m_strBackprojectName(pszBackprojectName),
- wxThread(wxTHREAD_DETACHED)
+ReconstructorWorker::SetParameters (ProjectionFileView* pProjView, ImageFile* pImageFile,
+ const char* pszFilterName, double dFilterParam, const char* pszFilterMethod, int iZeropad,
+ const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
+ const char* pszBackprojectName)
{
+ m_pProjView = pProjView;
+ m_pImageFile = pImageFile;
+ m_pszFilterName = pszFilterName;
+ m_dFilterParam = dFilterParam;
+ m_pszFilterMethod = pszFilterMethod;
+ m_iZeropad = iZeropad;
+ m_pszFilterGenerationName = pszFilterGenerationName;
+ m_pszInterpName = pszInterpName;
+ m_iInterpParam = iInterpParam;
+ m_pszBackprojectName = pszBackprojectName;
}
wxThread::ExitCode
ReconstructorWorker::Entry ()
{
Reconstructor* pReconstructor = new Reconstructor (m_pProjView->GetDocument()->getProjections(),
- *m_pImageFile, m_strFilterName.c_str(), m_dFilterParam, m_strFilterMethod.c_str(), m_iZeropad,
- m_strFilterGenerationName.c_str(), m_strInterpName.c_str(), m_iInterpParam, m_strBackprojectName.c_str(), Trace::TRACE_NONE);
+ *m_pImageFile, m_pszFilterName, m_dFilterParam, m_pszFilterMethod, m_iZeropad,
+ m_pszFilterGenerationName, m_pszInterpName, m_iInterpParam, m_pszBackprojectName, Trace::TRACE_NONE);
+
+ wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
+ eventDone.SetInt (m_iThread); // Send back thread# that has finished
+
if (pReconstructor->fail()) {
- wxString msg;
- msg.Printf("Unable to make reconstructor: %s", pReconstructor->failMessage());
- wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_FAIL );
+ wxString msg("Unable to make reconstructor: ");
+ msg += pReconstructor->failMessage().c_str();
+ wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
event.SetString( msg );
- wxPostEvent( theApp->getMainFrame(), event ); // send in a thread-safe way
+ wxPostEvent( theApp->getMainFrame(), event );
+
+ wxPostEvent (m_pSupervisor, eventDone);
return reinterpret_cast<wxThread::ExitCode>(-1);
}
wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_UNIT_TICK);
- for (int iView = 0; iView < m_iNumViews; iView++) {
+ for (int iUnit = 0; iUnit < m_iNumUnits; iUnit++) {
if (TestDestroy()) {
#ifdef DEBUG
- wxString msg;
- msg.Printf("Received destroy message view #%d\n", iView);
- wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
- event.SetString( msg );
- wxPostEvent( theApp->getMainFrame(), event ); // send in a thread-safe way
+ if (theApp->getVerboseLogging()) {
+ wxString msg;
+ msg.Printf("Worker thread: Received destroy message at work unit #%d\n", iUnit);
+ wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+ event.SetString( msg );
+ wxPostEvent( theApp->getMainFrame(), event );
+ }
#endif
delete pReconstructor;
+ wxPostEvent (m_pSupervisor, eventDone);
+
return reinterpret_cast<wxThread::ExitCode>(-1);
}
- pReconstructor->reconstructView (iView + m_iStartView, 1);
+ pReconstructor->reconstructView (iUnit + m_iStartUnit, 1);
wxPostEvent (m_pSupervisor, eventProgress);
}
pReconstructor->postProcessing();
- wxCommandEvent eventDone (wxEVT_COMMAND_MENU_SELECTED, BackgroundSupervisor::MSG_WORKER_THREAD_DONE);
- eventProgress.SetInt (m_iThread); // Send back thread# that has finished
wxPostEvent (m_pSupervisor, eventDone);
delete pReconstructor;
** This is part of the CTSim program
** Copyright (C) 1983-2001 Kevin Rosenberg
**
-** $Id: threadrecon.h,v 1.7 2001/02/23 21:58:32 kevin Exp $
+** $Id: threadrecon.h,v 1.8 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
#include <wx/thread.h>
#include <wx/progdlg.h>
#include "timer.h"
+#include "backgroundsupr.h"
-// This thread creates a SupervisorTask event handler object
-// The thread is detached and terminates when SupervisorTask terminates
-class SupervisorTaskThread : public wxThread {
-private:
-
-public:
- SupervisorTaskThread();
-
- virtual wxThread::ExitCode Entry() = 0;
-
- // called when the thread exits - whether it terminates normally or is stopped with Delete()
- virtual void OnExit();
-};
+class Reconstructor;
+class ImageFile;
+class ProjectionFileDocument;
+class ReconstructorWorker;
+class ProjectionFileView;
-class ReconstructorSupervisorThread : public SupervisorTaskThread {
-private:
-public:
-};
-
-
-// Pure virtual class for BackgroundSupervisor that can communication
-// with BackgroundManager via messages
-
-class BackgroundSupervisor : public wxEvtHandler {
+class ReconstructorSupervisorThread : public SupervisorThread {
private:
- bool m_bDone;
+ ProjectionFileView* m_pProjView;
+ ImageFile* m_pImageFile;
+ const int m_iNX;
+ const int m_iNY;
+ const std::string m_strFilterName;
+ const double m_dFilterParam;
+ const std::string m_strFilterMethod;
+ const int m_iZeropad;
+ const std::string m_strFilterGenerationName;
+ const std::string m_strInterpName;
+ const int m_iInterpParam;
+ const std::string m_strBackprojectName;
+ const std::string m_strLabel;
public:
+ ReconstructorSupervisorThread(ProjectionFileView* pProjView, int iNX, int iNY, const char* pszFilterName,
+ double dFilterParam, const char* pszFilterMethod, int iZeropad, const char* pszFilterGenerationName,
+ const char* pszInterpName, int iInterpParam, const char* pszBackprojectName, const char* const pszLabel);
- enum {
- MSG_BACKGROUND_SUPERVISOR_ADD = 7500, // sends to BackgroundManager and Document
- MSG_BACKGROUND_SUPERVISOR_REMOVE = 7501, // sends to BackgroundManager and Document
- MSG_BACKGROUND_SUPERVISOR_UNIT_TICK = 7502, // sends to BackgroundManager for progress bars
- MSG_BACKGROUND_SUPERVISOR_CANCEL = 7503, // *sent* to Supervisor to cancel process
+ virtual wxThread::ExitCode Entry();
- MSG_WORKER_THREAD_UNIT_TICK = 7504,
- MSG_WORKER_THREAD_DONE = 7505,
- MSG_WORKER_THREAD_FAIL = 7506, // sent by workers when they fail
- };
-
- BackgroundSupervisor()
- : m_bDone(false), wxEvtHandler()
- {}
-
- virtual ~BackgroundSupervisor()
- {}
-
- virtual bool start() = 0;
- virtual bool testDone() = 0;
- virtual void OnWorkerFail(wxCommandEvent& event) = 0;
- virtual void OnWorkerUnitTick(wxCommandEvent& event) = 0;
- virtual void OnWorkerDone(wxCommandEvent& event) = 0;
- virtual void OnCancel(wxCommandEvent& event) = 0;
-
- bool isDone() const {return m_bDone;}
- void setDone() { m_bDone = true; }
-
- static void cancelSupervisor (BackgroundSupervisor* pSupervisor);
+ virtual void OnExit();
};
-class Reconstructor;
-class ImageFile;
-class ProjectionFileDocument;
-class ReconstructorWorker;
-class ProjectionFileView;
class ReconstructorSupervisor : public BackgroundSupervisor {
private:
- DECLARE_DYNAMIC_CLASS(ReconstructorSupervisor)
- wxCriticalSection m_critsectThreadContainer;
std::vector<ImageFile*> m_vecpChildImageFile;
- typedef std::vector<ReconstructorWorker*> ThreadContainer;
- ThreadContainer m_vecpThread;
ProjectionFileDocument* m_pProjDoc;
ProjectionFileView* m_pProjView;
- wxProgressDialog* m_pDialogProgress;
- volatile bool m_bFail;
- int m_iNumThreads;
const int m_iImageNX;
const int m_iImageNY;
- volatile int m_iRunning;
- volatile unsigned int m_iViewsDone;
- volatile unsigned int m_iTotalViews;
- wxString m_strLabel;
- Timer* m_pTimer;
- bool m_bCancelled;
- bool m_bCancelling;
+
+ const char* const m_pszFilterName;
+ const double m_dFilterParam;
+ const char* const m_pszFilterMethod;
+ const int m_iZeropad;
+ const char* const m_pszFilterGenerationName;
+ const char* const m_pszInterpName;
+ const int m_iInterpParam;
+ const char* const m_pszBackprojectName;
+ const char* const m_pszLabel;
public:
- ReconstructorSupervisor (ProjectionFileView* pProjView,
- int iNX, int iNY, const char* pszFilterName, double dFilterParam, const char* pszFilterMethod,
- int iZeropad, const char* pszFilterGenerationName, const char* pszInterpName, int iInterpParam,
- const char* pszBackprojectName, const char* const pszLabel);
+ ReconstructorSupervisor (ProjectionFileView* pProjView, int iNX, int iNY, const char* pszFilterName,
+ double dFilterParam, const char* pszFilterMethod, int iZeropad, const char* pszFilterGenerationName,
+ const char* pszInterpName, int iInterpParam, const char* pszBackprojectName, const char* const pszLabel);
- ReconstructorSupervisor ()
- : m_bFail(true), m_iNumThreads(0), m_iImageNX(0), m_iImageNY(0), m_iTotalViews(0),
- BackgroundSupervisor()
- {}
+ virtual BackgroundWorkerThread* createWorker (int iThread, int iStartUnit, int iNumUnits);
- ~ReconstructorSupervisor ();
+ virtual ~ReconstructorSupervisor ();
void onDone();
- bool start();
- bool fail() const {return m_bFail;}
- bool testDone();
- void cleanUp();
- virtual void OnWorkerFail(wxCommandEvent& event);
- virtual void OnWorkerUnitTick(wxCommandEvent& event);
- virtual void OnWorkerDone(wxCommandEvent& event);
- virtual void OnCancel(wxCommandEvent& event);
ImageFile* getImageFile();
- DECLARE_EVENT_TABLE()
};
-class ReconstructorWorker : public wxThread {
+
+class ReconstructorWorker : public BackgroundWorkerThread {
private:
- ReconstructorSupervisor* m_pSupervisor;
- int m_iStartView;
- int m_iNumViews;
- int m_iThread;
ProjectionFileView* m_pProjView;
ImageFile* m_pImageFile;
- const std::string m_strFilterName;
- const double m_dFilterParam;
- const std::string m_strFilterMethod;
- const int m_iZeropad;
- const std::string m_strFilterGenerationName;
- const std::string m_strInterpName;
- const int m_iInterpParam;
- const std::string m_strBackprojectName;
+ const char* m_pszFilterName;
+ double m_dFilterParam;
+ const char* m_pszFilterMethod;
+ int m_iZeropad;
+ const char* m_pszFilterGenerationName;
+ const char* m_pszInterpName;
+ int m_iInterpParam;
+ const char* m_pszBackprojectName;
public:
- ReconstructorWorker (ReconstructorSupervisor* pSupervisor,
- ProjectionFileView* pProjFile, ImageFile* pImageFile,
- int iThread, int iStartView, int iNumViews,
+ ReconstructorWorker (ReconstructorSupervisor* pSupervisor, int iThread, int iStartView, int iNumViews)
+ : BackgroundWorkerThread (pSupervisor, iThread, iStartView, iNumViews)
+ {}
+
+ SetParameters (ProjectionFileView* pProjFile, ImageFile* pImageFile,
const char* const pszFilterName, double dFilterParam, const char* const pszFilterMethod,
int iZeropad, const char* const pszFilterGenerationName, const char* const pszInterpName, int iInterpParam,
const char* pszBackprojectName);
virtual wxThread::ExitCode Entry(); // thread execution starts here
- // called when the thread exits - whether it terminates normally or is stopped with Delete()
virtual void OnExit();
};
** This is part of the CTSim program
** Copyright (c) 1983-2001 Kevin Rosenberg
**
-** $Id: views.cpp,v 1.116 2001/02/23 21:58:32 kevin Exp $
+** $Id: views.cpp,v 1.117 2001/02/25 06:32:12 kevin Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
{
if (! m_pView)
return;
+
wxClientDC dc(this);
PrepareDC(dc);
} else {
if (theApp->getUseBackgroundTasks() || theApp->getNumberCPU() > 1) {
- ReconstructorSupervisor* pReconstructor = new ReconstructorSupervisor (this,
+ ReconstructorSupervisorThread* pReconstructor = new ReconstructorSupervisorThread (this,
m_iDefaultNX, m_iDefaultNY, optFilterName.c_str(),
m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(),
optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), os.str().c_str());
- if (! pReconstructor->start()) {
+ if (pReconstructor->Create() != wxTHREAD_NO_ERROR) {
+ sys_error (ERR_SEVERE, "Error creating reconstructor thread");
delete pReconstructor;
return;
}
- // delete pReconstructor; // reconstructor is still running
+// pReconstructor->SetPriority (60);
+ pReconstructor->Run();
} else {
ImageFile* pImageFile = new ImageFile;
pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY);