X-Git-Url: http://git.kpe.io/?a=blobdiff_plain;f=src%2Fthreadrecon.cpp;h=0fd94b293460292533316dd82abbdab4ad0b17eb;hb=6480e936da257519dd36840862ac995ca8c374da;hp=159e9d43975749c2e1ad154c54203150e236238e;hpb=b0df0a0f3008d0fee67f388cfa1c37af6383b38f;p=ctsim.git diff --git a/src/threadrecon.cpp b/src/threadrecon.cpp index 159e9d4..0fd94b2 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.5 2001/02/23 03:28:26 kevin Exp $ +** $Id: threadrecon.cpp,v 1.7 2001/02/23 21:58:32 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 @@ -43,29 +43,26 @@ #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(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() -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_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), - BackgroundTask() + BackgroundSupervisor() { m_iNumThreads = theApp->getNumberCPU(); // ++m_iNumThreads; - m_iTotalViews = m_pProjView->GetDocument()->getProjections().nView(); + m_iTotalViews = pProjView->GetDocument()->getProjections().nView(); int iBaseViews = m_iTotalViews / m_iNumThreads; int iExtraViews = m_iTotalViews % m_iNumThreads; @@ -79,30 +76,43 @@ 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; break; } } - + m_pProjView = pProjView; + m_pProjDoc = pProjView->GetDocument(); +} + +// Static function +void +BackgroundSupervisor::cancelSupervisor (BackgroundSupervisor* pSupervisor) +{ + wxCommandEvent cancelEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_CANCEL); + wxPostEvent (pSupervisor, cancelEvent); } bool -ThreadedReconstructor::start() +ReconstructorSupervisor::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 { std::string strLabel ("Reconstructing "); strLabel += m_pProjView->GetFrame()->GetTitle(); - m_pGauge = theApp->getBackgroundManager()->addTask (this, m_iTotalViews, strLabel.c_str()); + 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_iRunning = m_iNumThreads; @@ -112,15 +122,12 @@ ThreadedReconstructor::start() // 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() +ReconstructorSupervisor::OnCancel(wxCommandEvent& event) { if (isDone() || m_bCancelled) return; @@ -130,42 +137,46 @@ 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(); } - for (i = 0; i < m_iNumThreads; i++) { + for (i = 0; i < m_iNumThreads; i++) { 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; - m_pGauge = NULL; setDone(); - m_pProjView->GetDocument()->removeReconstructor (this); - theApp->getBackgroundManager()->taskDone (this); - + + wxCommandEvent doneEvent (wxEVT_COMMAND_MENU_SELECTED, MSG_BACKGROUND_SUPERVISOR_REMOVE); + doneEvent.SetClientData (this); + wxPostEvent (theApp->getBackgroundManager(), doneEvent); + wxPostEvent (m_pProjDoc, doneEvent); + cleanSection.Leave(); } void -ThreadedReconstructor::onDone() +ReconstructorSupervisor::onDone() { wxCriticalSection doneSection; doneSection.Enter(); - m_pProjView->GetDocument()->removeReconstructor (this); + ImageFileDocument* pReconDoc = theApp->newImageDoc(); if (! pReconDoc) { sys_error (ERR_SEVERE, "Unable to create image file"); @@ -191,21 +202,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 @@ -215,35 +214,59 @@ ThreadedReconstructor::OnThreadEvent (wxCommandEvent& event) if (m_pDialogProgress) 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; + 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(); + +#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 } - else - *theApp->getLog() << "Got event #" << iEventId << "\n"; - - eventSection.Leave(); +#endif + if (m_iRunning <= 0) { + onDone(); + return; + } +} + +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* -ThreadedReconstructor::getImageFile() +ReconstructorSupervisor::getImageFile() { ImageFile* pImageFile = new ImageFile (m_iImageNX, m_iImageNY); pImageFile->arrayDataClear(); @@ -261,59 +284,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(-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(RTHREAD_THREAD_CANCELLED); +#endif + delete pReconstructor; + return reinterpret_cast(-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(0); } void -ReconstructionThread::OnExit () +ReconstructorWorker::OnExit () { - delete m_pReconstructor; }