Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkImageAccessorBase.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkImageAccessorBase.h"
14 #include "mitkImage.h"
15 
16 mitk::ImageAccessorBase::ThreadIDType mitk::ImageAccessorBase::CurrentThreadHandle()
17 {
18 #ifdef ITK_USE_SPROC
19  return GetCurrentThreadId();
20 #endif
21 
22 #ifdef ITK_USE_PTHREADS
23  return pthread_self();
24 #endif
25 
26 #ifdef ITK_USE_WIN32_THREADS
27  return GetCurrentThreadId();
28 #endif
29 }
30 
31 bool mitk::ImageAccessorBase::CompareThreadHandles(mitk::ImageAccessorBase::ThreadIDType handle1,
32  mitk::ImageAccessorBase::ThreadIDType handle2)
33 {
34  return handle1 == handle2;
35 }
36 
38 {
39 }
40 
42  const ImageDataItem *imageDataItem,
43  int OptionFlags)
44  : // m_Image(iP)
45  //, imageDataItem(iDI)
46  m_SubRegion(nullptr),
47  m_Options(OptionFlags),
48  m_CoherentMemory(false)
49 {
50  m_Thread = CurrentThreadHandle();
51 
52  // Initialize WaitLock
55 
56  // Check validity of ImageAccessor
57 
58  // Is there an Image?
59  /*
60  if(!m_Image)
61  {
62  mitkThrow() << "Invalid ImageAccessor: No Image was specified in constructor of ImageAccessor";
63  }
64  */
65 
66  if (image)
67  {
68  // Make sure, that the Image is initialized properly
69  if (image->m_Initialized == false)
70  {
71  if (image->GetSource().IsNull())
72  {
73  mitkThrow() << "ImageAccessor: No image source is defined";
74  }
75  image->m_ReadWriteLock.Lock();
76  if (image->GetSource()->Updating() == false)
77  {
78  image->GetSource()->UpdateOutputInformation();
79  }
80  image->m_ReadWriteLock.Unlock();
81  }
82  }
83 
84  // Investigate 4 cases of possible image parts/regions
85 
86  // Case 1: No ImageDataItem and no Subregion => Whole Image is accessed
87  if (imageDataItem == nullptr && m_SubRegion == nullptr)
88  {
89  m_CoherentMemory = true;
90 
91  // Organize first image channel
92  image->m_ReadWriteLock.Lock();
93  imageDataItem = image->GetChannelData();
94  image->m_ReadWriteLock.Unlock();
95 
96  // Set memory area
97  m_AddressBegin = imageDataItem->m_Data;
98  m_AddressEnd = (unsigned char *)m_AddressBegin + imageDataItem->m_Size;
99  }
100 
101  // Case 2: ImageDataItem but no Subregion
102  if (imageDataItem && m_SubRegion == nullptr)
103  {
104  m_CoherentMemory = true;
105 
106  // Set memory area
107  m_AddressBegin = imageDataItem->m_Data;
108  m_AddressEnd = (unsigned char *)m_AddressBegin + imageDataItem->m_Size;
109  }
110 
111  // Case 3: No ImageDataItem but a SubRegion
112  if (imageDataItem == nullptr && m_SubRegion)
113  {
114  mitkThrow() << "Invalid ImageAccessor: The use of a SubRegion is not supported (yet).";
115  }
116 
117  // Case 4: ImageDataItem and SubRegion
118  if (imageDataItem == nullptr && m_SubRegion)
119  {
120  mitkThrow() << "Invalid ImageAccessor: The use of a SubRegion is not supported (yet).";
121  }
122 }
123 
128 {
129  if (m_CoherentMemory)
130  {
131  if ((iAB->m_AddressBegin >= m_AddressBegin && iAB->m_AddressBegin < m_AddressEnd) ||
133  {
134  return true;
135  }
136  if ((m_AddressBegin >= iAB->m_AddressBegin && m_AddressBegin < iAB->m_AddressEnd) ||
137  (m_AddressEnd > iAB->m_AddressBegin && m_AddressEnd <= iAB->m_AddressEnd))
138  {
139  return true;
140  }
141  }
142  else
143  {
144  GetImage()->m_ReadWriteLock.Unlock();
145  mitkThrow() << "ImageAccessor: incoherent memory area is not supported yet";
146  }
147 
148  return false;
149 }
150 
153 {
154  wL->m_Mutex.Lock();
155 
156  // Decrement
157  wL->m_WaiterCount -= 1;
158 
159  // If there are no more waiting ImageAccessors, delete the Mutex
160  // (Der Letzte macht das Licht aus!)
161  if (wL->m_WaiterCount <= 0)
162  {
163  wL->m_Mutex.Unlock();
164  delete wL;
165  }
166  else
167  {
168  wL->m_Mutex.Unlock();
169  }
170 }
171 
173 {
174 #ifdef MITK_USE_RECURSIVE_MUTEX_PREVENTION
175  // Prevent deadlock
176  ThreadIDType id = CurrentThreadHandle();
177  if (CompareThreadHandles(id, iAB->m_Thread))
178  {
179  GetImage()->m_ReadWriteLock.Unlock();
180  mitkThrow()
181  << "Prohibited image access: the requested image part is already in use and cannot be requested recursively!";
182  }
183 #endif
184 }
void WaitForReleaseOf(ImageAccessorWaitLock *wL)
Uses the WaitLock to wait for another ImageAccessor.
itk::ImageRegion< 4 > * m_SubRegion
unsigned int m_WaiterCount
Holds the number of ImageAccessors, which are waiting until the represented ImageAccessor is released...
virtual const Image * GetImage() const =0
bool Overlap(const ImageAccessorBase *iAB)
Computes if there is an Overlap of the image part between this instantiation and another ImageAccesso...
unsigned char * m_Data
ImageAccessorWaitLock * m_WaitLock
Pointer to a WaitLock struct, that allows other ImageAccessors to wait for this ImageAccessor.
#define mitkThrow()
mitk::Image::Pointer image
void PreventRecursiveMutexLock(ImageAccessorBase *iAB)
Prevents a recursive mutex lock by comparing thread ids of competing image accessors.
ImageAccessorBase(ImageConstPointer iP, const ImageDataItem *iDI=nullptr, int OptionFlags=DefaultBehavior)
Checks validity of given parameters from inheriting classes and stores those parameters in member var...
int m_Options
Stores all extended properties of an ImageAccessor. The different flags in mitk::ImageAccessorBase::O...
itk::SimpleFastMutexLock m_Mutex
A mutex that allows other ImageAccessors to wait for the represented ImageAccessor.
This struct allows to make ImageAccessors wait for this particular ImageAccessor object.
Internal class for managing references on sub-images.