1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkDomainThreader_h
19 #define itkDomainThreader_h
20 
21 #include "itkObject.h"
22 #include "itkMultiThreaderBase.h"
23 
24 namespace itk
25 {
26 
27 /** \class DomainThreader
28  *  \brief Multi-threaded processing on a domain by processing sub-domains per
29  *  thread.
30  *
31  *  This class uses a ThreadedDomainPartitioner as a helper to split the
32  *  domain into subdomains.  Each subdomain is then processed in the
33  *  \c ThreadedExecution method.
34  *
35  *  The data on which to perform the processing is assumed to be members
36  *  of an associating class.  Therefore, to perform a threaded operation in a
37  *  class, the associating class usually will declare derived versions of this
38  *  class as a friend class.
39  *
40  *  To use this class, at a minimum,
41  *  \li Inherit from it.
42  *  \li Implement ThreadedExecution.
43  *  \li Create a member instance.
44  *  \li Run with m_DomainThreader->Execute( this, domain );
45  *
46  *  If a 'threaded method' is desired to perform some data processing in a
47  *  class, a derived version of this class can be defined to perform the threaded operation.
48  *  Since a threaded operation is relatively complex compared to a simple serial
49  *  operation, a class instead of a simple method is required.  Inside this
50  *  class, the method to partition the data is handled, the logic for
51  *  deciding the number of work units is determined, and operations surrounding
52  *  the threading are encapsulated into the class with the
53  *  \c DetermineNumberOfWorkUnitsToUse, \c BeforeThreadedExecution, \c ThreadedExecution,
54  *  and \c AfterThreadedExecution virtual methods.
55  *
56  *  \tparam TDomainPartitioner A class that inherits from
57  *  ThreadedDomainPartitioner.
58  *  \tparam TAssociate  The associated class that uses a derived version of
59  *  this class as a "threaded method".  The associated class usually declares
60  *  derived version of this class as nested classes so there is easy access to
61  *  its protected and private members in ThreadedExecution.
62  *
63  *  \ingroup ITKCommon
64  */
65 template< typename TDomainPartitioner, typename TAssociate >
66 class ITK_TEMPLATE_EXPORT DomainThreader: public Object
67 {
68 public:
69   ITK_DISALLOW_COPY_AND_ASSIGN(DomainThreader);
70 
71   /** Standard class type aliases. */
72   using Self = DomainThreader;
73   using Superclass = Object;
74   using Pointer = SmartPointer< Self >;
75   using ConstPointer = SmartPointer< const Self >;
76 
77   using DomainPartitionerType = TDomainPartitioner;
78   using DomainType = typename DomainPartitionerType::DomainType;
79 
80   using AssociateType = TAssociate;
81 
82   /** Run-time type information (and related methods). */
83   itkTypeMacro( DomainThreader, Object );
84 
85   /** Run the multi-threaded operation on the given domain.
86    *
87    * The domain is first partitioned by the ThreadedDomainPartitioner, then
88    * the virtual methods \c BeforeThreadedExecution, \c ThreadedExecution, and
89    * \c AfterThreadedExecution. are run, in order. */
90   void Execute( AssociateType * enclosingClass, const DomainType & domain );
91 
92   /** Set/Get the DomainPartitioner. */
93   itkSetObjectMacro( DomainPartitioner, DomainPartitionerType );
94   itkGetModifiableObjectMacro( DomainPartitioner, DomainPartitionerType );
95 
96   /** Accessor for number of work units that were actually used in the last
97    * ThreadedExecution. */
98   itkGetConstMacro( NumberOfWorkUnitsUsed, ThreadIdType );
99 
100   /** Return the multithreader used by this class. */
101   MultiThreaderBase * GetMultiThreader() const;
102 
103   /** Convenience methods to set/get the desired number of work units to use.
104    * \warning When setting the desired number of work units, it might be clamped by
105    * itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads().
106    * */
107   itkSetClampMacro(NumberOfWorkUnits, ThreadIdType, 1, ITK_MAX_THREADS);
108   itkGetConstMacro(NumberOfWorkUnits, ThreadIdType);
109 
110   /** Convenience methods to set/get the maximum number of threads to use.
111    * \warning When setting the maximum number of threads, it will be clamped by
112    * itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads().
113    * */
GetMaximumNumberOfThreads()114   ThreadIdType GetMaximumNumberOfThreads() const
115   {
116     return this->m_MultiThreader->GetMaximumNumberOfThreads();
117   }
118   void SetMaximumNumberOfThreads(const ThreadIdType threads);
119 
120 protected:
121   DomainThreader();
122   ~DomainThreader() override = default;
123 
124   /** This is evauated at the beginning of Execute() so that it can be used in
125    * BeforeThreadedExecution(). */
126   virtual void DetermineNumberOfWorkUnitsUsed();
127 
128   /** When \c Execute is run, this method is run singled-threaded before \c
129    * ThreadedExecution.  Inside this method optional operations such as
130    * creating instance variables needed per thread may be performed. */
BeforeThreadedExecution()131   virtual void BeforeThreadedExecution(){}
132 
133   /** Do the threaded operation, somewhat like \c ThreadedGenerateData in an
134    * ImageSource.
135    * \param subdomain The subdomain to operate on.
136    * \param threadId  The identifier for the current thread.
137    * Data to perform the operation on can be accessed by dereferencing
138    * this->m_Associate, which has direct access to private and protected
139    * members the enclosing class.
140    */
141   virtual void ThreadedExecution( const DomainType& subdomain,
142                                   const ThreadIdType threadId ) = 0;
143 
144   /** When \c Execute in run, this method is run single-threaded after \c
145    * ThreadedExecution.  Optionally collect results, etc. E.g. calculate the
146    * global minimum from the minimums calculated per thread. */
AfterThreadedExecution()147   virtual void AfterThreadedExecution(){}
148 
149   itkSetObjectMacro( MultiThreader, MultiThreaderBase );
150 
151   /** Static function used as a "callback" by the MultiThreaderBase.  The threading
152    * library will call this routine for each thread, which will delegate the
153    * control to the ThreadFunctor. */
154   static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION ThreaderCallback( void *arg );
155 
156   AssociateType * m_Associate;
157 
158 private:
159   void StartThreadingSequence();
160 
161   /** This contains the object passed to the threading library. */
162   struct ThreadStruct
163     {
164     DomainThreader     * domainThreader;
165     };
166 
167   /** Store the actual number of work units used, which may be less than
168    * the number allocated by the threader if the object does not split
169    * well into that number.
170    * This value is determined at the beginning of \c Execute(). */
171   ThreadIdType                             m_NumberOfWorkUnitsUsed{0};
172   ThreadIdType                             m_NumberOfWorkUnits;
173   typename DomainPartitionerType::Pointer  m_DomainPartitioner;
174   DomainType                               m_CompleteDomain;
175   MultiThreaderBase::Pointer               m_MultiThreader;
176 };
177 
178 }
179 
180 #ifndef ITK_MANUAL_INSTANTIATION
181 #include "itkDomainThreader.hxx"
182 #endif
183 
184 #endif
185