From 3b09207d7c37bc3d48e331657353123ed2f66ed9 Mon Sep 17 00:00:00 2001 From: "Kevin M. Rosenberg" Date: Sun, 25 Feb 2001 06:32:12 +0000 Subject: [PATCH] r578: no message --- ChangeLog | 12 +- msvc/ctsim/ctsim.dsp | 8 + msvc/ctsim/ctsim.plg | 21 +-- src/backgroundmgr.cpp | 12 +- src/backgroundsupr.cpp | 245 +++++++++++++++++++++++++++++ src/backgroundsupr.h | 140 +++++++++++++++++ src/dialogs.cpp | 4 +- src/docs.cpp | 24 ++- src/threadrecon.cpp | 338 +++++++++++++++-------------------------- src/threadrecon.h | 163 +++++++------------- src/views.cpp | 11 +- 11 files changed, 626 insertions(+), 352 deletions(-) create mode 100644 src/backgroundsupr.cpp create mode 100644 src/backgroundsupr.h diff --git a/ChangeLog b/ChangeLog index 31ab14c..5ebfd0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,15 +2,23 @@ * 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 diff --git a/msvc/ctsim/ctsim.dsp b/msvc/ctsim/ctsim.dsp index fb1cdcc..47a6472 100644 --- a/msvc/ctsim/ctsim.dsp +++ b/msvc/ctsim/ctsim.dsp @@ -97,6 +97,10 @@ SOURCE=..\..\src\backgroundmgr.cpp # 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 @@ -157,6 +161,10 @@ SOURCE=..\..\src\backgroundmgr.h # 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 diff --git a/msvc/ctsim/ctsim.plg b/msvc/ctsim/ctsim.plg index 85cc112..9af1f67 100644 --- a/msvc/ctsim/ctsim.plg +++ b/msvc/ctsim/ctsim.plg @@ -6,19 +6,13 @@ --------------------Configuration: ctsim - Win32 Debug--------------------

Command Lines

-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 @@ -32,6 +26,7 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.lib ..\.. .\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" @@ -42,12 +37,10 @@ winmm.lib rpcrt4.lib ws2_32.lib ../libctsim/Debug/libctsim.lib libcmtd.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"

Output Window

Compiling... -docs.cpp -Compiling... -threadrecon.cpp +backgroundsupr.cpp Linking... diff --git a/src/backgroundmgr.cpp b/src/backgroundmgr.cpp index ee789de..b6d0bd6 100644 --- a/src/backgroundmgr.cpp +++ b/src/backgroundmgr.cpp @@ -9,7 +9,7 @@ ** 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 @@ -35,7 +35,7 @@ #include "ctsim.h" #include "docs.h" #include "views.h" -#include "threadrecon.h" +#include "backgroundsupr.h" #include "backgroundmgr.h" @@ -141,7 +141,11 @@ BackgroundManager::OnAddTask (wxCommandEvent& event) 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 @@ -197,6 +201,8 @@ BackgroundManager::lookupGauge (BackgroundSupervisor* pTask) { 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]; diff --git a/src/backgroundsupr.cpp b/src/backgroundsupr.cpp new file mode 100644 index 0000000..c0326d6 --- /dev/null +++ b/src/backgroundsupr.cpp @@ -0,0 +1,245 @@ +/***************************************************************************** +** 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(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(); +} + diff --git a/src/backgroundsupr.h b/src/backgroundsupr.h new file mode 100644 index 0000000..faae6e0 --- /dev/null +++ b/src/backgroundsupr.h @@ -0,0 +1,140 @@ +/***************************************************************************** +** 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 +#include +#include +#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 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 diff --git a/src/dialogs.cpp b/src/dialogs.cpp index 7b4d7d1..806b3fc 100644 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -9,7 +9,7 @@ ** 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 @@ -243,7 +243,7 @@ DialogPreferences::DialogPreferences (wxWindow* pParent, const char* const pszTi 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); diff --git a/src/docs.cpp b/src/docs.cpp index bb8ec90..16462d7 100644 --- a/src/docs.cpp +++ b/src/docs.cpp @@ -9,7 +9,7 @@ ** 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 @@ -149,13 +149,16 @@ ProjectionFileDocument::OnSaveDocument(const wxString& filename) 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; } @@ -177,7 +180,7 @@ ProjectionFileDocument::OnRemoveBackground (wxCommandEvent& event) BackgroundSupervisor* pSupervisor = reinterpret_cast(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(); @@ -187,8 +190,13 @@ ProjectionFileDocument::OnRemoveBackground (wxCommandEvent& event) 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 diff --git a/src/threadrecon.cpp b/src/threadrecon.cpp index 0fd94b2..7a7b3dd 100644 --- a/src/threadrecon.cpp +++ b/src/threadrecon.cpp @@ -9,7 +9,7 @@ ** 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 @@ -37,150 +37,120 @@ #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(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; } @@ -194,76 +164,13 @@ ReconstructorSupervisor::onDone() 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(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() @@ -273,7 +180,7 @@ 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++) @@ -283,67 +190,74 @@ ReconstructorSupervisor::getImageFile() 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(-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(-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; diff --git a/src/threadrecon.h b/src/threadrecon.h index e96bb2d..f4f9105 100644 --- a/src/threadrecon.h +++ b/src/threadrecon.h @@ -9,7 +9,7 @@ ** 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 @@ -32,157 +32,106 @@ #include #include #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 m_vecpChildImageFile; - typedef std::vector 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(); }; diff --git a/src/views.cpp b/src/views.cpp index 8203cbc..1e28647 100644 --- a/src/views.cpp +++ b/src/views.cpp @@ -9,7 +9,7 @@ ** 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 @@ -113,6 +113,7 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event) { if (! m_pView) return; + wxClientDC dc(this); PrepareDC(dc); @@ -2438,15 +2439,17 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event) } 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); -- 2.34.1