r573: no message
[ctsim.git] / src / threadrecon.cpp
index e43299a356cb925614cbe003a014a566f0420570..e53daacb2458f53faa63a3f062496b1432ee755c 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
-**  $Id: threadrecon.cpp,v 1.2 2001/02/22 15:00:20 kevin Exp $
+**  $Id: threadrecon.cpp,v 1.3 2001/02/22 18:22:40 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
@@ -51,34 +51,34 @@ END_EVENT_TABLE()
 
 enum {
   RTHREAD_UNIT_COMPLETE = -1,
-  RTHREAD_THREAD_DONE = -2,
-  RTHREAD_THREAD_CANCELLED = -3,
+    RTHREAD_THREAD_DONE = -2,
+    RTHREAD_THREAD_CANCELLED = -3,
 };
 
 ThreadedReconstructor::ThreadedReconstructor (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_pDialogProgress(NULL), m_pGauge(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), 
-    m_bDone(false), BackgroundTask()
+                                              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_pDialogProgress(NULL), m_pGauge(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), 
+                                              BackgroundTask()
 {
   m_iNumThreads = theApp->getNumberCPU();
-//  ++m_iNumThreads;
+  //  ++m_iNumThreads;
   m_iTotalViews = m_pProjView->GetDocument()->getProjections().nView();
   int iBaseViews = m_iTotalViews / m_iNumThreads;
   int iExtraViews = m_iTotalViews % m_iNumThreads;
-
+  
   m_vecpChildImageFile.reserve (m_iNumThreads);
   m_vecpReconstructor.reserve (m_iNumThreads);
   m_vecpThread.reserve (m_iNumThreads);
-
+  
   for (unsigned int iProc = 0; iProc < m_iNumThreads; iProc++) {
     m_vecpChildImageFile[iProc] = new ImageFile (iImageNX, iImageNY);
     m_vecpReconstructor[iProc] = new Reconstructor (m_pProjView->GetDocument()->getProjections(), *m_vecpChildImageFile[iProc],
-    pszFilterName, dFilterParam, pszFilterMethod, iZeropad, pszFilterGenerationName, 
-    pszInterpName, iInterpParam, pszBackprojectName, Trace::TRACE_NONE);
-
+      pszFilterName, dFilterParam, pszFilterMethod, iZeropad, pszFilterGenerationName, 
+      pszInterpName, iInterpParam, pszBackprojectName, Trace::TRACE_NONE);
+    
     int iStartView = iProc * iBaseViews;
     int iNumViews = iBaseViews;
     if (iProc < iExtraViews)
@@ -89,7 +89,7 @@ ThreadedReconstructor::ThreadedReconstructor (ProjectionFileView* pProjView,
       break;
     }
   }
-
+  
 }
 
 
@@ -98,117 +98,140 @@ ThreadedReconstructor::start()
 {
   if (m_bFail)
     return false;
-
+  
   m_pProjView->GetDocument()->addReconstructor (this);
   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
-    m_pGauge = theApp->getBackgroundManager()->addTask (this, m_iTotalViews);
-
+    m_pGauge = theApp->getBackgroundManager()->addTask (this, m_iTotalViews, m_pProjView->GetFrame()->GetTitle());
+  
   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();
-
-
+  
   if (m_bCancelled)
     return false;
-
+  
   return true;
 }
 
 void
 ThreadedReconstructor::cancel()
 {
-  if (m_bCancelled)
+  if (isDone() || m_bCancelled)
     return;
+  m_bCancelled = true;
+  m_bCancelling = false;
+  cleanUp();
+}
 
-  wxCriticalSectionLocker locker (m_criticalSection);
-
+void
+ThreadedReconstructor::cleanUp()
+{
+  wxCriticalSection cleanSection;
+  cleanSection.Enter();
+  
   for (int i = 0; i < m_iNumThreads; i++) 
-    if (m_vecpThread[i])
+    if (m_vecpThread[i] && m_vecpThread[i]->IsRunning()) {
+      m_vecpThread[i]->Pause();
       m_vecpThread[i]->Delete();
-
-  for (i = 0; i < m_iNumThreads; i++)
-    delete m_vecpReconstructor[i];
-
-  m_iNumThreads = 0;
-  m_iRunning = 0;
-  delete m_pDialogProgress;
-  delete m_pTimer;
-  m_pDialogProgress = NULL;
-  m_pProjView->GetDocument()->removeReconstructor (this);
-  m_bCancelled = true;
-  m_bDone = true;
-  theApp->getBackgroundManager()->taskDone (this);
+    }
+    
+    for (i = 0; i < m_iNumThreads; i++) {
+      delete m_vecpChildImageFile[i];
+      m_vecpChildImageFile[i] = NULL;
+    }
+    for (i = 0; i < m_iNumThreads; i++) {
+      delete m_vecpReconstructor[i];
+      m_vecpReconstructor[i] = NULL;
+    }
+    
+    
+    m_iNumThreads = 0;
+    m_iRunning = 0;
+    delete m_pDialogProgress;
+    delete m_pTimer;
+    m_pDialogProgress = NULL;
+    m_pGauge = NULL;
+    setDone();
+    m_pProjView->GetDocument()->removeReconstructor (this);
+    theApp->getBackgroundManager()->taskDone (this);
+    
+    cleanSection.Leave();
 }
 
 void
 ThreadedReconstructor::onDone()
 {
-    for (int i = 0; i < m_iNumThreads; i++)
-      delete m_vecpReconstructor[i];
+  wxCriticalSection doneSection;
+  doneSection.Enter();
 
-    m_pProjView->GetDocument()->removeReconstructor (this);
-      ImageFileDocument* pReconDoc = theApp->newImageDoc();
-      if (! pReconDoc) {
-        sys_error (ERR_SEVERE, "Unable to create image file");
-        return;
-      }
-      
-      ImageFile* pImageFile = getImageFile();
-      pReconDoc->setImageFile (pImageFile);
-      if (theApp->getAskDeleteNewDocs())
-        pReconDoc->Modify (true);
-      pReconDoc->UpdateAllViews (m_pProjView);
-      if (ImageFileView* rasterView = pReconDoc->getView()) {
-        rasterView->OnUpdate (rasterView, NULL);
-        rasterView->getFrame()->SetFocus();
-        rasterView->getFrame()->Show(true);
-      }
-      *theApp->getLog() << m_strLabel << "\n";
-      pImageFile->labelAdd (m_pProjView->GetDocument()->getProjections().getLabel());
-      pImageFile->labelAdd (m_strLabel.c_str(), m_pTimer->timerEnd());
-      delete m_pTimer;
-
-      wxIdleEvent event;
-      theApp->OnIdle(event);
-      m_bDone = true;
-   theApp->getBackgroundManager()->taskDone (this);
-      // delete this;
+  m_pProjView->GetDocument()->removeReconstructor (this);
+  ImageFileDocument* pReconDoc = theApp->newImageDoc();
+  if (! pReconDoc) {
+    sys_error (ERR_SEVERE, "Unable to create image file");
+    doneSection.Leave();
+    return;
+  }
+  
+  for (int i = 0; i < m_iNumThreads; i++) {
+    delete m_vecpReconstructor[i];
+    m_vecpReconstructor[i] = NULL;
+  }
+  
+  ImageFile* pImageFile = getImageFile();
+  pReconDoc->setImageFile (pImageFile);
+  if (theApp->getAskDeleteNewDocs())
+    pReconDoc->Modify (true);
+  pReconDoc->UpdateAllViews (m_pProjView);
+  if (ImageFileView* rasterView = pReconDoc->getView()) {
+    rasterView->OnUpdate (rasterView, NULL);
+    rasterView->getFrame()->SetFocus();
+    rasterView->getFrame()->Show(true);
+  }
+  *theApp->getLog() << m_strLabel << "\n";
+  pImageFile->labelAdd (m_pProjView->GetDocument()->getProjections().getLabel());
+  pImageFile->labelAdd (m_strLabel.c_str(), m_pTimer->timerEnd());
+  
+  doneSection.Leave();
+  cleanUp();
 }
 
 
 void
 ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event)
 {
-  if (m_bCancelling) {
-    cancel();
+  if (isDone())
+    return;
+  wxCriticalSection eventSection;
+  eventSection.Enter();
+  if (isDone()) {
+    eventSection.Leave();
     return;
   }
-
-  wxCriticalSectionLocker locker (m_criticalSection);
-
+  
   int iEventId = event.GetInt();
   if (iEventId == RTHREAD_UNIT_COMPLETE) {
     ++m_iViewsDone;
-    *theApp->getLog() << "Views done: " << static_cast<int>(m_iViewsDone) <<"\n";
-
+    
+#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 if (m_pGauge) {
-      m_pGauge->SetValue (m_iViewsDone - 1);
+      m_pGauge->SetValue (m_iViewsDone - 1); 
+      eventSection.Leave();
       m_bCancelling = theApp->getBackgroundManager()->isCancelling(this);
     }
-    if (m_iViewsDone == m_iTotalViews) {
-      delete m_pDialogProgress;
-      m_pDialogProgress = NULL;
-      onDone();
-    }
-    if (m_bCancelling) {
+    if (! isDone() && m_bCancelling) {
+      eventSection.Leave();
       cancel();
       return;
     }
@@ -217,19 +240,25 @@ ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event)
     m_iRunning--;
     m_vecpThread[event.GetInt()] = NULL;
     *theApp->getLog() << "Thread finished. Remaining threads: " << m_iRunning << "\n";
+    if (m_iRunning <= 0) {
+      eventSection.Leave();
+      onDone();
+      return;
+    }
   }
   else
     *theApp->getLog() << "Got event #" << iEventId << "\n";
-
+  
+  eventSection.Leave();
 }
 
 ImageFile*
-ThreadedReconstructor::getImageFile() const
+ThreadedReconstructor::getImageFile()
 {
   ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY);
   pImageFile->arrayDataClear();
   ImageFileArray pArray = pImageFile->getArray();
+  
   int i;
   for (i = 0; i < m_iNumThreads; i++) {
     ImageFileArrayConst pChildArray = m_vecpChildImageFile[i]->getArray();
@@ -237,19 +266,14 @@ ThreadedReconstructor::getImageFile() const
       for (int iy = 0; iy < m_iImageNY; iy++)
         pArray[ix][iy] += pChildArray[ix][iy];
   }
-
-  for (i = 0; i < m_iNumThreads; i++) {
-    delete m_vecpChildImageFile[i];
-//    m_vecpChildImageFile[i] = NULL;
-  }
-
+  
   return (pImageFile);
 }
 
 bool
 ThreadedReconstructor::testDone()
 {
-    return (m_iRunning <= 0 ? true : false);
+  return (m_iRunning <= 0 ? true : false);
 }
 
 
@@ -259,35 +283,35 @@ ThreadedReconstructor::~ThreadedReconstructor()
 
 
 ReconstructionThread::ReconstructionThread (ThreadedReconstructor* pSupervisor, 
-                         Reconstructor* pReconstructor, int iThread, int iStartView, int iNumViews)
-: m_pSupervisor(pSupervisor), m_pReconstructor(pReconstructor), 
-  m_iStartView(iStartView), m_iNumViews(iNumViews), m_iThread(iThread), 
-  wxThread(wxTHREAD_DETACHED)
+                                            Reconstructor* pReconstructor, int iThread, int iStartView, int iNumViews)
+                                            : m_pSupervisor(pSupervisor), m_pReconstructor(pReconstructor), 
+                                            m_iStartView(iStartView), m_iNumViews(iNumViews), m_iThread(iThread), 
+                                            wxThread(wxTHREAD_DETACHED)
 {
 }
 
 wxThread::ExitCode
 ReconstructionThread::Entry ()
 {
-   wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, RECONSTRUCTION_THREAD_EVENT);
-   for (int iView = 0; iView < m_iNumViews; iView++) {
-     if (TestDestroy()) {
+  wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, RECONSTRUCTION_THREAD_EVENT);
+  for (int iView = 0; iView < m_iNumViews; iView++) {
+    if (TestDestroy()) {
       wxString msg;
       msg.Printf("TestDestroy TRUE at 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
       return reinterpret_cast<wxThread::ExitCode>(RTHREAD_THREAD_CANCELLED);
-     }
-     m_pReconstructor->reconstructView (iView + m_iStartView, 1);
-     eventProgress.SetInt (RTHREAD_UNIT_COMPLETE);
-     wxPostEvent (m_pSupervisor, eventProgress);
-   }
-
-   eventProgress.SetInt (m_iThread); // Send back thread# that has finished
-   wxPostEvent (m_pSupervisor, eventProgress);
-
-   return reinterpret_cast<wxThread::ExitCode>(0);
+    }
+    m_pReconstructor->reconstructView (iView + m_iStartView, 1);
+    eventProgress.SetInt (RTHREAD_UNIT_COMPLETE);
+    wxPostEvent (m_pSupervisor, eventProgress);
+  }
+  
+  eventProgress.SetInt (m_iThread); // Send back thread# that has finished
+  wxPostEvent (m_pSupervisor, eventProgress);
+  
+  return reinterpret_cast<wxThread::ExitCode>(0);
 }
 
 void