Medical Imaging Interaction Toolkit  2016.11.0
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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkImageAccessorBase.h"
18 #include "mitkImage.h"
19 
20 mitk::ImageAccessorBase::ThreadIDType mitk::ImageAccessorBase::CurrentThreadHandle()
21 {
22 #ifdef ITK_USE_SPROC
23  return GetCurrentThreadId();
24 #endif
25 
26 #ifdef ITK_USE_PTHREADS
27  return pthread_self();
28 #endif
29 
30 #ifdef ITK_USE_WIN32_THREADS
31  return GetCurrentThreadId();
32 #endif
33 }
34 
35 bool mitk::ImageAccessorBase::CompareThreadHandles(mitk::ImageAccessorBase::ThreadIDType handle1,
36  mitk::ImageAccessorBase::ThreadIDType handle2)
37 {
38  return handle1 == handle2;
39 }
40 
42 {
43 }
44 
46  const ImageDataItem *imageDataItem,
47  int OptionFlags)
48  : // m_Image(iP)
49  //, imageDataItem(iDI)
50  m_SubRegion(nullptr),
51  m_Options(OptionFlags),
52  m_CoherentMemory(false)
53 {
54  m_Thread = CurrentThreadHandle();
55 
56  // Initialize WaitLock
59 
60  // Check validity of ImageAccessor
61 
62  // Is there an Image?
63  /*
64  if(!m_Image)
65  {
66  mitkThrow() << "Invalid ImageAccessor: No Image was specified in constructor of ImageAccessor";
67  }
68  */
69 
70  if (image)
71  {
72  // Make sure, that the Image is initialized properly
73  if (image->m_Initialized == false)
74  {
75  if (image->GetSource().IsNull())
76  {
77  mitkThrow() << "ImageAccessor: No image source is defined";
78  }
79  image->m_ReadWriteLock.Lock();
80  if (image->GetSource()->Updating() == false)
81  {
82  image->GetSource()->UpdateOutputInformation();
83  }
84  image->m_ReadWriteLock.Unlock();
85  }
86  }
87 
88  // Investigate 4 cases of possible image parts/regions
89 
90  // Case 1: No ImageDataItem and no Subregion => Whole Image is accessed
91  if (imageDataItem == nullptr && m_SubRegion == nullptr)
92  {
93  m_CoherentMemory = true;
94 
95  // Organize first image channel
96  image->m_ReadWriteLock.Lock();
97  imageDataItem = image->GetChannelData();
98  image->m_ReadWriteLock.Unlock();
99 
100  // Set memory area
101  m_AddressBegin = imageDataItem->m_Data;
102  m_AddressEnd = (unsigned char *)m_AddressBegin + imageDataItem->m_Size;
103  }
104 
105  // Case 2: ImageDataItem but no Subregion
106  if (imageDataItem && m_SubRegion == nullptr)
107  {
108  m_CoherentMemory = true;
109 
110  // Set memory area
111  m_AddressBegin = imageDataItem->m_Data;
112  m_AddressEnd = (unsigned char *)m_AddressBegin + imageDataItem->m_Size;
113  }
114 
115  // Case 3: No ImageDataItem but a SubRegion
116  if (imageDataItem == nullptr && m_SubRegion)
117  {
118  mitkThrow() << "Invalid ImageAccessor: The use of a SubRegion is not supported (yet).";
119  }
120 
121  // Case 4: ImageDataItem and SubRegion
122  if (imageDataItem == nullptr && m_SubRegion)
123  {
124  mitkThrow() << "Invalid ImageAccessor: The use of a SubRegion is not supported (yet).";
125  }
126 }
127 
132 {
133  if (m_CoherentMemory)
134  {
135  if ((iAB->m_AddressBegin >= m_AddressBegin && iAB->m_AddressBegin < m_AddressEnd) ||
136  (iAB->m_AddressEnd > m_AddressBegin && iAB->m_AddressEnd <= m_AddressEnd))
137  {
138  return true;
139  }
140  if ((m_AddressBegin >= iAB->m_AddressBegin && m_AddressBegin < iAB->m_AddressEnd) ||
141  (m_AddressEnd > iAB->m_AddressBegin && m_AddressEnd <= iAB->m_AddressEnd))
142  {
143  return true;
144  }
145  }
146  else
147  {
148  GetImage()->m_ReadWriteLock.Unlock();
149  mitkThrow() << "ImageAccessor: incoherent memory area is not supported yet";
150  }
151 
152  return false;
153 }
154 
157 {
158  wL->m_Mutex.Lock();
159 
160  // Decrement
161  wL->m_WaiterCount -= 1;
162 
163  // If there are no more waiting ImageAccessors, delete the Mutex
164  // (Der Letzte macht das Licht aus!)
165  if (wL->m_WaiterCount <= 0)
166  {
167  wL->m_Mutex.Unlock();
168  delete wL;
169  }
170  else
171  {
172  wL->m_Mutex.Unlock();
173  }
174 }
175 
177 {
178 #ifdef MITK_USE_RECURSIVE_MUTEX_PREVENTION
179  // Prevent deadlock
180  ThreadIDType id = CurrentThreadHandle();
181  if (CompareThreadHandles(id, iAB->m_Thread))
182  {
183  GetImage()->m_ReadWriteLock.Unlock();
184  mitkThrow()
185  << "Prohibited image access: the requested image part is already in use and cannot be requested recursively!";
186  }
187 #endif
188 }
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...
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()
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...
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.