r578: no message
authorKevin M. Rosenberg <kevin@rosenberg.net>
Sun, 25 Feb 2001 06:32:12 +0000 (06:32 +0000)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Sun, 25 Feb 2001 06:32:12 +0000 (06:32 +0000)
ChangeLog
msvc/ctsim/ctsim.dsp
msvc/ctsim/ctsim.plg
src/backgroundmgr.cpp
src/backgroundsupr.cpp [new file with mode: 0644]
src/backgroundsupr.h [new file with mode: 0644]
src/dialogs.cpp
src/docs.cpp
src/threadrecon.cpp
src/threadrecon.h
src/views.cpp

index 31ab14cd0faaf93525c00542a3de34b03dfa1d92..5ebfd0ec6fa18d10c508d3accc236d40ca3bbbaa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,15 +2,23 @@
 
        * ctsim: Added tips to be displayed at startup and via the help menu.
 
 
        * 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.
        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
 
        
        * 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
 3.0.3 - Released 2/20/01
 
        * ctsim: Fixed core dump on Linux with OpenGL
index fb1cdcc70ef16ecf2d070f5b53390a6a549841ce..47a647291fcfb3d062c2ada38e7cb7aba516098c 100644 (file)
@@ -97,6 +97,10 @@ SOURCE=..\..\src\backgroundmgr.cpp
 # End Source File
 # Begin Source File
 
 # 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
 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
 
 # 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
 SOURCE="..\..\src\ctsim-map.h"
 # End Source File
 # Begin Source File
index 85cc1125b7ccea08b0a0a052680f2a35a367eb89..9af1f671abceffaef91e4149e79bf40a526a7547 100644 (file)
@@ -6,19 +6,13 @@
 --------------------Configuration: ctsim - Win32 Debug--------------------
 </h3>
 <h3>Command Lines</h3>
 --------------------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 
 [
 /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
 [
 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\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"
 \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
 ]
 \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...
 <h3>Output Window</h3>
 Compiling...
-docs.cpp
-Compiling...
-threadrecon.cpp
+backgroundsupr.cpp
 Linking...
 
 
 Linking...
 
 
index ee789deb155b0128914c7f259a24c42b9c8cda9e..b6d0bd66d0091744e88e79f324da91fdf02638c8 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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 "ctsim.h"
 #include "docs.h"
 #include "views.h"
-#include "threadrecon.h"
+#include "backgroundsupr.h"
 #include "backgroundmgr.h"
 
 
 #include "backgroundmgr.h"
 
 
@@ -141,7 +141,11 @@ BackgroundManager::OnAddTask (wxCommandEvent& event)
   m_iNumTasks++;
 
   resizeWindow();
   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
 }
 
 void
@@ -197,6 +201,8 @@ BackgroundManager::lookupGauge (BackgroundSupervisor* pTask)
 {
   wxGauge* pGauge = NULL;
   int i = 0;
 {
   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];
   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 (file)
index 0000000..c0326d6
--- /dev/null
@@ -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<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();
+}
+
diff --git a/src/backgroundsupr.h b/src/backgroundsupr.h
new file mode 100644 (file)
index 0000000..faae6e0
--- /dev/null
@@ -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 <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
index 7b4d7d141c2b514080456913d1d45ead0de750ad..806b3fc996a429b445efce01ca8f6f2e5a984742 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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);
   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);
   pTopSizer->Add (m_pCBUseBackgroundTasks, 0, wxALIGN_CENTER_VERTICAL);
 
   pTopSizer->Add (new wxStaticLine (this, -1, wxDefaultPosition, wxSize(3,3), wxHORIZONTAL), 0, wxEXPAND | wxALL, 5);
index bb8ec90d973e122046ac32d95cda6c34d7f52bb4..16462d7bb27544ff5cdc8c9e51b6de72ae6d91cb 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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()
 {
 
 ProjectionFileDocument::~ProjectionFileDocument()
 {
+  m_criticalSection.Enter();
   for (BackgroundContainer::iterator i = m_vecpBackgroundSupervisors.begin(); 
   for (BackgroundContainer::iterator i = m_vecpBackgroundSupervisors.begin(); 
-        i != m_vecpBackgroundSupervisors.end(); i++) {
+        i != m_vecpBackgroundSupervisors.end(); i++)
           BackgroundSupervisor::cancelSupervisor(*i);
           BackgroundSupervisor::cancelSupervisor(*i);
-    }
-  
-  while (m_vecpBackgroundSupervisors.size() > 0)
-    ::wxYield();
+  m_criticalSection.Leave();
+
+  while (m_vecpBackgroundSupervisors.size() > 0) {
+     ::wxUsleep(50);
+     ::wxYield();
+  }
 
   delete m_pProjectionFile;
 }
 
   delete m_pProjectionFile;
 }
@@ -177,7 +180,7 @@ ProjectionFileDocument::OnRemoveBackground (wxCommandEvent& event)
   BackgroundSupervisor* pSupervisor = reinterpret_cast<BackgroundSupervisor*>(event.GetClientData());
   wxASSERT (pSupervisor != NULL);
 
   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(); 
   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;
         }
             bFound = true;
             break;
         }
-   if (! bFound) 
+  m_criticalSection.Leave();
+
+  if (! bFound) 
      sys_error (ERR_SEVERE, "Could not find background task [ProjectionFileDocument::removeBackgroundTask");
      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 
 }
 
 bool 
index 0fd94b293460292533316dd82abbdab4ad0b17eb..7a7b3ddb1c33f530bcd2a348851f8dd44f882fa1 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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 "views.h"
 #include "threadrecon.h"
 #include "backgroundmgr.h"
+#include "backgroundsupr.h"
 
 #if defined(HAVE_CONFIG_H)
 #include "config.h"
 #endif
 
 
 
 #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;
     }    
       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;
 }
 
 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");
 
   ImageFileDocument* pReconDoc = theApp->newImageDoc();
   if (! pReconDoc) {
     sys_error (ERR_SEVERE, "Unable to create image file");
-    doneSection.Leave();
     return;
   }
     
     return;
   }
     
@@ -194,76 +164,13 @@ ReconstructorSupervisor::onDone()
     rasterView->getFrame()->SetFocus();
     rasterView->getFrame()->Show(true);
   }
     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_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()
 
 ImageFile*
 ReconstructorSupervisor::getImageFile()
@@ -273,7 +180,7 @@ ReconstructorSupervisor::getImageFile()
   ImageFileArray pArray = pImageFile->getArray();
   
   int i;
   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++)
     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);
 }
 
   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(), 
 }
 
 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()) {
   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 );
       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);
 
       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
     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;
 #endif
       delete pReconstructor;
+      wxPostEvent (m_pSupervisor, eventDone);
+  
       return reinterpret_cast<wxThread::ExitCode>(-1);
     }
       return reinterpret_cast<wxThread::ExitCode>(-1);
     }
-    pReconstructor->reconstructView (iView + m_iStartView, 1);
+    pReconstructor->reconstructView (iUnit + m_iStartUnit, 1);
     wxPostEvent (m_pSupervisor, eventProgress);
   }
   pReconstructor->postProcessing();
   
     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;
   wxPostEvent (m_pSupervisor, eventDone);
   
   delete pReconstructor;
index e96bb2d8f85c76d4adea9ebb2295ec594c138e11..f4f91057787b14351797669be6655b00b17796df 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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 <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:
 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:
 
 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:
 
 
 class ReconstructorSupervisor : public BackgroundSupervisor {
 private:
-  DECLARE_DYNAMIC_CLASS(ReconstructorSupervisor)
-  wxCriticalSection m_critsectThreadContainer;
 
   std::vector<ImageFile*> m_vecpChildImageFile;
 
   std::vector<ImageFile*> m_vecpChildImageFile;
-  typedef std::vector<ReconstructorWorker*> ThreadContainer;
-  ThreadContainer m_vecpThread;
   ProjectionFileDocument* m_pProjDoc;
   ProjectionFileView* m_pProjView;
   ProjectionFileDocument* m_pProjDoc;
   ProjectionFileView* m_pProjView;
-  wxProgressDialog* m_pDialogProgress;
     
     
-  volatile bool m_bFail;
-  int m_iNumThreads;
   const int m_iImageNX;
   const int m_iImageNY;
   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:
 
 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();
 
   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();
 
 
   ImageFile* getImageFile();
 
-  DECLARE_EVENT_TABLE()
 };
 
 
 
 };
 
 
 
-class ReconstructorWorker : public wxThread {
+
+class ReconstructorWorker : public BackgroundWorkerThread {
 private:
 private:
-  ReconstructorSupervisor* m_pSupervisor;
-  int m_iStartView;
-  int m_iNumViews;
-  int m_iThread;
   ProjectionFileView* m_pProjView;
   ImageFile* m_pImageFile;
   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:
 
 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
 
    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();
 };
 
   virtual void OnExit();
 };
 
index 8203cbc4198af168c8c7fc30dc18942893c66bb3..1e28647cc9f1868223d8759c553555a8bffe5b72 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (c) 1983-2001 Kevin Rosenberg
 **
 **  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
 **
 **  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;
 {
   if (! m_pView)
     return;
+
   
   wxClientDC dc(this);
   PrepareDC(dc);
   
   wxClientDC dc(this);
   PrepareDC(dc);
@@ -2438,15 +2439,17 @@ ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
         
       } else {
         if (theApp->getUseBackgroundTasks() || theApp->getNumberCPU() > 1) {
         
       } 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());
             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;
             return;
           }
-          // delete pReconstructor;  // reconstructor is still running
+//          pReconstructor->SetPriority (60);
+          pReconstructor->Run();
         } else {
           ImageFile* pImageFile = new ImageFile;
           pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY);
         } else {
           ImageFile* pImageFile = new ImageFile;
           pImageFile->setArraySize (m_iDefaultNX, m_iDefaultNY);