/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkProgressReporter_h #define itkProgressReporter_h #include "itkIntTypes.h" #include "itkProcessObject.h" namespace itk { /** \class ProgressReporter * \brief Implements progress tracking for a filter. * * This is a utility class for use by filter implementations in * GenerateData() and ThreadedGenerateData(). * * The class constructor sets the progress to 0, and the destructor * sets it to 1. In between, there should be one call to * CompletedPixel() per pixel. The reporter will automatically update * the filter's progress at an interval resulting in the specified * number of updates. The default number of updates is 100. * * Example usage: * \code ProgressReporter progress(this, threadId, threadRegion.GetNumberOfPixels(), 100); for( each pixel ) { ... progress.CompletedPixel(); } \endcode * * When used in a non-threaded filter, the threadId argument should be 0. * * \sa * This class is a tool for filter implementers to equip a filter to * report on its progress. For information on how to acquire this * progress information, see: * - ProcessObject::ReportProgress() * - Object::AddObserver() * \ingroup ITKCommon */ class ITKCommon_EXPORT ProgressReporter { public: ITK_DISALLOW_COPY_AND_MOVE(ProgressReporter); /** Constructor sets progress to 0 because the filter is starting. */ ProgressReporter(ProcessObject * filter, ThreadIdType threadId, SizeValueType numberOfPixels, SizeValueType numberOfUpdates = 100, float initialProgress = 0.0f, float progressWeight = 1.0f); /** Destructor sets progress to 1 because the filter has finished. */ ~ProgressReporter(); /** Check if the filter has the ProcessObject::AbortGenerateData * flag set. If true, then a ProcessAborted exception will be thrown. */ void CheckAbortGenerateData() { // all threads needs to check the abort flag if (m_Filter && m_Filter->GetAbortGenerateData()) { std::string msg; ProcessAborted e(__FILE__, __LINE__); msg += "Object " + std::string(m_Filter->GetNameOfClass()) + ": AbortGenerateDataOn"; e.SetDescription(msg); throw e; } } /** Called by a filter once per pixel. */ void CompletedPixel() { // Inline implementation for efficiency. if (--m_PixelsBeforeUpdate == 0) { m_PixelsBeforeUpdate = m_PixelsPerUpdate; m_CurrentPixel += m_PixelsPerUpdate; // only thread 0 should update the progress of the filter if (m_ThreadId == 0 && m_Filter) { m_Filter->UpdateProgress(static_cast(m_CurrentPixel) * m_InverseNumberOfPixels * m_ProgressWeight + m_InitialProgress); } this->CheckAbortGenerateData(); } } protected: ProcessObject * m_Filter; ThreadIdType m_ThreadId; float m_InverseNumberOfPixels; SizeValueType m_CurrentPixel; SizeValueType m_PixelsPerUpdate; SizeValueType m_PixelsBeforeUpdate; float m_InitialProgress; float m_ProgressWeight; }; } // end namespace itk #endif