X-Git-Url: http://git.kpe.io/?p=ctsim.git;a=blobdiff_plain;f=src%2Fthreadrecon.cpp;h=e53daacb2458f53faa63a3f062496b1432ee755c;hp=e43299a356cb925614cbe003a014a566f0420570;hb=9776c9a12ba53419d34563a5ec57c90e3d6798f4;hpb=e081109a4a541c8780aaa253b874acada5957200 diff --git a/src/threadrecon.cpp b/src/threadrecon.cpp index e43299a..e53daac 100644 --- a/src/threadrecon.cpp +++ b/src/threadrecon.cpp @@ -9,7 +9,7 @@ ** This is part of the CTSim program ** Copyright (C) 1983-2001 Kevin Rosenberg ** -** $Id: threadrecon.cpp,v 1.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(m_iViewsDone) <<"\n"; - + +#ifdef DEBUG + if (theApp->getVerboseLogging()) + *theApp->getLog() << "Views done: " << static_cast(m_iViewsDone) <<"\n"; +#endif + if (m_pDialogProgress) m_bCancelling = ! m_pDialogProgress->Update (m_iViewsDone - 1); else 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(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(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(0); } void