r576: no message
[ctsim.git] / src / threadrecon.cpp
index 159e9d43975749c2e1ad154c54203150e236238e..03d4d39d37987dd4bbc18277f0c2d6f07b65d614 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2001 Kevin Rosenberg
 **
-**  $Id: threadrecon.cpp,v 1.5 2001/02/23 03:28:26 kevin Exp $
+**  $Id: threadrecon.cpp,v 1.6 2001/02/23 18:56:56 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
 #endif
 
 
-IMPLEMENT_DYNAMIC_CLASS(ThreadedReconstructor, BackgroundTask)
-BEGIN_EVENT_TABLE(ThreadedReconstructor, BackgroundTask)
-EVT_MENU(RECONSTRUCTION_THREAD_EVENT, ThreadedReconstructor::OnThreadEvent)
+IMPLEMENT_DYNAMIC_CLASS(ReconstructorSupervisor, BackgroundSupervisor)
+BEGIN_EVENT_TABLE(ReconstructorSupervisor, BackgroundSupervisor)
+EVT_MENU(RECONSTRUCTION_THREAD_EVENT, ReconstructorSupervisor::OnThreadEvent)
+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()
 
 
-enum {
-  RTHREAD_UNIT_COMPLETE = -1,
-    RTHREAD_THREAD_DONE = -2,
-    RTHREAD_THREAD_CANCELLED = -3,
-};
-
-ThreadedReconstructor::ThreadedReconstructor (ProjectionFileView* pProjView, 
+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_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()
+                                              BackgroundSupervisor()
 {
   m_iNumThreads = theApp->getNumberCPU();
   //  ++m_iNumThreads;
@@ -79,7 +76,7 @@ ThreadedReconstructor::ThreadedReconstructor (ProjectionFileView* pProjView,
     int iNumViews = iBaseViews;
     if (iProc < iExtraViews)
       ++iNumViews;
-      m_vecpThread[iProc] = new ReconstructionThread (this, pProjView, m_vecpChildImageFile[iProc], iProc, iStartView, 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;
@@ -91,7 +88,7 @@ ThreadedReconstructor::ThreadedReconstructor (ProjectionFileView* pProjView,
 
 
 bool
-ThreadedReconstructor::start()
+ReconstructorSupervisor::start()
 {
   if (m_bFail)
     return false;
@@ -120,7 +117,7 @@ ThreadedReconstructor::start()
 }
 
 void
-ThreadedReconstructor::cancel()
+ReconstructorSupervisor::cancel()
 {
   if (isDone() || m_bCancelled)
     return;
@@ -130,18 +127,20 @@ ThreadedReconstructor::cancel()
 }
 
 void
-ThreadedReconstructor::cleanUp()
+ReconstructorSupervisor::cleanUp()
 {
   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();
     }
+  m_critsectThreadContainer.Leave();
     
-    for (i = 0; i < m_iNumThreads; i++) {
+  for (i = 0; i < m_iNumThreads; i++) {
       delete m_vecpChildImageFile[i];
       m_vecpChildImageFile[i] = NULL;
     }    
@@ -160,7 +159,7 @@ ThreadedReconstructor::cleanUp()
 }
 
 void
-ThreadedReconstructor::onDone()
+ReconstructorSupervisor::onDone()
 {
   wxCriticalSection doneSection;
   doneSection.Enter();
@@ -191,21 +190,9 @@ ThreadedReconstructor::onDone()
   cleanUp();
 }
 
-
 void
-ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event)
+ReconstructorSupervisor::OnWorkerUnitTick (wxCommandEvent& event)
 {
-  if (isDone())
-    return;
-  wxCriticalSection eventSection;
-  eventSection.Enter();
-  if (isDone()) {
-    eventSection.Leave();
-    return;
-  }
-  
-  int iEventId = event.GetInt();
-  if (iEventId == RTHREAD_UNIT_COMPLETE) {
     ++m_iViewsDone;
     
 #ifdef DEBUG
@@ -217,33 +204,66 @@ ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event)
       m_bCancelling = ! m_pDialogProgress->Update (m_iViewsDone - 1);
     else if (m_pGauge) {
       m_pGauge->SetValue (m_iViewsDone - 1); 
-      eventSection.Leave();
       m_bCancelling = theApp->getBackgroundManager()->isCancelling(this);
     }
     if (! isDone() && m_bCancelling) {
-      eventSection.Leave();
       cancel();
       return;
     }
-  } 
-  else if (event.GetInt() >= 0) {
-    m_iRunning--;
-    m_vecpThread[event.GetInt()] = NULL;
-    *theApp->getLog() << "Thread finished. Remaining threads: " << m_iRunning << "\n";
-    if (m_iRunning <= 0) {
-      eventSection.Leave();
-      onDone();
-      return;
-    }
+}
+
+void
+ReconstructorSupervisor::OnWorkerDone (wxCommandEvent& event)
+{
+  if (isDone())
+    return;
+
+  m_iRunning--;
+  m_critsectThreadContainer.Enter();
+  m_vecpThread[event.GetInt()] = NULL;
+  m_critsectThreadContainer.Leave();
+  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
+
+  if (m_iRunning <= 0) {
+    onDone();
+    return;
   }
-  else
-    *theApp->getLog() << "Got event #" << iEventId << "\n";
-  
-  eventSection.Leave();
+}
+
+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();
+}
+
+
+void
+ReconstructorSupervisor::OnThreadEvent (wxCommandEvent& event)
+{
+      wxString msg;
+      msg.Printf("Reconstructor Supervisor: Received event #%d\n", event.GetInt());  
+      wxCommandEvent eventLog( wxEVT_COMMAND_MENU_SELECTED, MAINMENU_LOG_EVENT );
+      eventLog.SetString( msg );
+      wxPostEvent( theApp->getMainFrame(), eventLog ); // send log event
 }
 
 ImageFile*
-ThreadedReconstructor::getImageFile()
+ReconstructorSupervisor::getImageFile()
 {
   ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY);
   pImageFile->arrayDataClear();
@@ -261,59 +281,73 @@ ThreadedReconstructor::getImageFile()
 }
 
 bool
-ThreadedReconstructor::testDone()
+ReconstructorSupervisor::testDone()
 {
   return (m_iRunning <= 0 ? true : false);
 }
 
 
-ThreadedReconstructor::~ThreadedReconstructor()
+ReconstructorSupervisor::~ReconstructorSupervisor()
 {
 }
 
 
-ReconstructionThread::ReconstructionThread 
-(ThreadedReconstructor* pSupervisor, ProjectionFileView* pProjView, ImageFile* pImageFile, int iThread, int iStartView, int iNumViews, 
+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), 
-                                            wxThread(wxTHREAD_DETACHED)
+    : 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)
 {
-  m_pReconstructor = new Reconstructor (pProjView->GetDocument()->getProjections(), 
-    *pImageFile, pszFilterName, dFilterParam, pszFilterMethod, iZeropad, pszFilterGenerationName, 
-    pszInterpName, iInterpParam, pszBackprojectName, Trace::TRACE_NONE);
 }
 
 wxThread::ExitCode
-ReconstructionThread::Entry ()
+ReconstructorWorker::Entry ()
 {
-  wxCommandEvent eventProgress (wxEVT_COMMAND_MENU_SELECTED, RECONSTRUCTION_THREAD_EVENT);
+  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);
+  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 );
+      event.SetString( msg );
+      wxPostEvent( theApp->getMainFrame(), event ); // send in a thread-safe way
+      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++) {
     if (TestDestroy()) {
+#ifdef DEBUG
       wxString msg;
-      msg.Printf("TestDestroy TRUE at view #%d\n", iView);  
+      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
-      return reinterpret_cast<wxThread::ExitCode>(RTHREAD_THREAD_CANCELLED);
+#endif
+      delete pReconstructor;
+      return reinterpret_cast<wxThread::ExitCode>(-1);
     }
-    m_pReconstructor->reconstructView (iView + m_iStartView, 1);
-    eventProgress.SetInt (RTHREAD_UNIT_COMPLETE);
+    pReconstructor->reconstructView (iView + m_iStartView, 1);
     wxPostEvent (m_pSupervisor, eventProgress);
   }
-  m_pReconstructor->postProcessing();
+  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, eventProgress);
+  wxPostEvent (m_pSupervisor, eventDone);
   
+  delete pReconstructor;
   return reinterpret_cast<wxThread::ExitCode>(0);
 }
 
 void
-ReconstructionThread::OnExit ()
+ReconstructorWorker::OnExit ()
 {
-   delete m_pReconstructor;
 }