** 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
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)
break;
}
}
-
+
}
{
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;
}
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();
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);
}
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