ANIMA  4.0
animaNumberedThreadImageToImageFilter.hxx
Go to the documentation of this file.
1 #pragma once
3 
4 namespace anima
5 {
6 
7 template <typename TInputImage, typename TOutputImage>
8 void
9 NumberedThreadImageToImageFilter <TInputImage, TOutputImage>
10 ::BeforeThreadedGenerateData()
11 {
12  m_ThreadIdsVector.clear();
13  Superclass::BeforeThreadedGenerateData();
14 
15  if (m_ComputationRegion.GetSize(0) == 0)
16  {
17  m_ComputationRegion = this->GetOutput(0)->GetRequestedRegion();
18  m_NumberOfPointsToProcess = m_ComputationRegion.GetNumberOfPixels();
19  }
20 
21  unsigned int maxNumSlices = m_ComputationRegion.GetSize()[0];
22  m_ProcessedDimension = 0;
23  for (unsigned int i = 1;i < OutputImageRegionType::ImageDimension;++i)
24  {
25  if (maxNumSlices <= m_ComputationRegion.GetSize()[i])
26  {
27  maxNumSlices = m_ComputationRegion.GetSize()[i];
28  m_ProcessedDimension = i;
29  }
30  }
31 
32  m_NumberOfProcessedPoints = 0;
33  this->UpdateProgress(0.0);
34 
35  // Since image requested region may now be smaller than the image, fill the outputs with zeros
36  typedef typename TOutputImage::PixelType OutputPixelType;
37 
38  for (unsigned int i = 0;i < this->GetNumberOfOutputs();++i)
39  {
40  OutputPixelType zeroPixel;
41  this->InitializeZeroPixel(this->GetOutput(i),zeroPixel);
42  this->GetOutput(i)->FillBuffer(zeroPixel);
43  }
44 }
45 
46 template< typename TInputImage, typename TOutputImage >
47 void
49 ::GenerateData()
50 {
51  this->AllocateOutputs();
52  this->BeforeThreadedGenerateData();
53 
54  m_HighestProcessedSlice = 0;
55 
56  ThreadStruct str;
57  str.Filter = this;
58 
59  this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
60  this->GetMultiThreader()->SetSingleMethod(this->ThreaderMultiSplitCallback, &str);
61 
62  this->GetMultiThreader()->SingleMethodExecute();
63 
64  this->AfterThreadedGenerateData();
65 }
66 
67 template< typename TInputImage, typename TOutputImage >
68 ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION
70 ::ThreaderMultiSplitCallback(void *arg)
71 {
72  ThreadStruct *str;
73 
74  str = (ThreadStruct *)( ( (itk::MultiThreaderBase::WorkUnitInfo *)( arg ) )->UserData );
75 
76  Self *filterPtr = dynamic_cast <Self *> (str->Filter.GetPointer());
77  filterPtr->ThreadProcessSlices();
78 
79  return ITK_THREAD_RETURN_DEFAULT_VALUE;
80 }
81 
82 template< typename TInputImage, typename TOutputImage >
83 void
85 ::ThreadProcessSlices()
86 {
87  OutputImageRegionType processedRegion = m_ComputationRegion;
88  processedRegion.SetSize(m_ProcessedDimension,1);
89  int highestToleratedSliceValue = m_ComputationRegion.GetSize()[m_ProcessedDimension] - 1;
90 
91  bool continueLoop = true;
92  while (continueLoop)
93  {
94  m_LockHighestProcessedSlice.lock();
95 
96  if (m_HighestProcessedSlice > highestToleratedSliceValue)
97  {
98  m_LockHighestProcessedSlice.unlock();
99  continueLoop = false;
100  continue;
101  }
102 
103  processedRegion.SetIndex(m_ProcessedDimension, m_ComputationRegion.GetIndex()[m_ProcessedDimension] + m_HighestProcessedSlice);
104  m_HighestProcessedSlice++;
105 
106  m_LockHighestProcessedSlice.unlock();
107 
108  this->DynamicThreadedGenerateData(processedRegion);
109  }
110 }
111 
112 template <typename TInputImage, typename TOutputImage>
113 void
115 ::IncrementNumberOfProcessedPoints()
116 {
117  m_LockProcessedPoints.lock();
118 
119  ++m_NumberOfProcessedPoints;
120 
121  double ratio = std::floor(m_NumberOfProcessedPoints * 100.0 / m_NumberOfPointsToProcess) / 100.0;
122  ratio = this->progressFixedToFloat(this->progressFloatToFixed(ratio));
123 
124  if (ratio != this->GetProgress())
125  this->UpdateProgress(ratio);
126 
127  m_LockProcessedPoints.unlock();
128 }
129 
130 template <typename TInputImage, typename TOutputImage>
131 unsigned int
133 ::GetSafeThreadId()
134 {
135  m_LockThreadIdNumber.lock();
136 
137  unsigned int threadId = 0;
138  bool presentInIdsVector = true;
139  while (presentInIdsVector)
140  {
141  presentInIdsVector = false;
142  for (unsigned int i = 0;i < m_ThreadIdsVector.size();++i)
143  {
144  if (m_ThreadIdsVector[i] == threadId)
145  {
146  presentInIdsVector = true;
147  break;
148  }
149  }
150 
151  if (presentInIdsVector)
152  threadId++;
153  }
154 
155  m_ThreadIdsVector.push_back(threadId);
156 
157  m_LockThreadIdNumber.unlock();
158 
159  return threadId;
160 }
161 
162 template <typename TInputImage, typename TOutputImage>
163 void
165 ::SafeReleaseThreadId(unsigned int threadId)
166 {
167  m_LockThreadIdNumber.lock();
168 
169  unsigned int indexThreadId = 0;
170  for (unsigned int i = 0;i < m_ThreadIdsVector.size();++i)
171  {
172  if (threadId == m_ThreadIdsVector[i])
173  {
174  indexThreadId = i;
175  break;
176  }
177  }
178 
179  m_ThreadIdsVector.erase(m_ThreadIdsVector.begin() + indexThreadId);
180 
181  m_LockThreadIdNumber.unlock();
182 }
183 
184 } // end namespace anima
Implements a class to handle thread number in a dynamic way for multithreaded methods needing thread ...