Medical Imaging Interaction Toolkit  2018.4.99-b20efe7f
Medical Imaging Interaction Toolkit
mitkImageReadAccessor.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 "mitkImageReadAccessor.h"
14 
15 #include "mitkImage.h"
16 
18  : ImageAccessorBase(image, iDI, OptionFlags), m_Image(image)
19 {
20  if (!(OptionFlags & ImageAccessorBase::IgnoreLock))
21  {
22  try
23  {
24  OrganizeReadAccess();
25  }
26  catch (...)
27  {
28  delete m_WaitLock;
29  throw;
30  }
31  }
32 }
33 
35  : ImageAccessorBase(image.GetPointer(), iDI, OptionFlags), m_Image(image.GetPointer())
36 {
37  if (!(OptionFlags & ImageAccessorBase::IgnoreLock))
38  {
39  try
40  {
41  OrganizeReadAccess();
42  }
43  catch (...)
44  {
45  delete m_WaitLock;
46  throw;
47  }
48  }
49 }
50 
52  : ImageAccessorBase(image, iDI, ImageAccessorBase::DefaultBehavior), m_Image(image)
53 {
54  OrganizeReadAccess();
55 }
56 
58 {
60  {
61  // Future work: In case of non-coherent memory, copied area needs to be deleted
62 
63  m_Image->m_ReadWriteLock.Lock();
64 
65  // delete self from list of ImageReadAccessors in Image
66  auto it = std::find(m_Image->m_Readers.begin(), m_Image->m_Readers.end(), this);
67  m_Image->m_Readers.erase(it);
68 
69  // delete lock, if there are no waiting ImageAccessors
70  if (m_WaitLock->m_WaiterCount <= 0)
71  {
72  m_WaitLock->m_Mutex.Unlock();
73  delete m_WaitLock;
74  }
75  else
76  {
77  m_WaitLock->m_Mutex.Unlock();
78  }
79 
80  m_Image->m_ReadWriteLock.Unlock();
81  }
82  else
83  {
84  delete m_WaitLock;
85  }
86 }
87 
89 {
90  return m_Image.GetPointer();
91 }
92 
93 void mitk::ImageReadAccessor::OrganizeReadAccess()
94 {
95  m_Image->m_ReadWriteLock.Lock();
96 
97  // Check, if there is any Write-Access going on
98  if (m_Image->m_Writers.size() > 0)
99  {
100  // Check for every WriteAccessors, if the Region of this ImageAccessors overlaps
101  // make sure this iterator is not used, when m_ReadWriteLock is Unlocked!
102  auto it = m_Image->m_Writers.begin();
103 
104  for (; it != m_Image->m_Writers.end(); ++it)
105  {
106  ImageAccessorBase *w = *it;
107  if (Overlap(w))
108  {
109  // An Overlap was detected. There are two possibilities to deal with this situation:
110  // Throw an exception or wait for the WriteAccessor w until it is released and start again with the request
111  // afterwards.
112  if (!(m_Options & ExceptionIfLocked))
113  {
115 
116  // WAIT
117  w->Increment();
118  m_Image->m_ReadWriteLock.Unlock();
120 
121  // after waiting for the WriteAccessor w, start this method again
122  OrganizeReadAccess();
123  return;
124  }
125  else
126  {
127  // THROW EXCEPTION
128  m_Image->m_ReadWriteLock.Unlock();
130  << "The image part being ordered by the ImageAccessor is already in use and locked";
131  return;
132  }
133  } // if
134  } // for
135  } // if
136 
137  // Now, we know, that there is no conflict with a Write-Access
138  // Lock the Mutex in ImageAccessorBase, to make sure that every other ImageAccessor has to wait if it locks the mutex
139  m_WaitLock->m_Mutex.Lock();
140 
141  // insert self into readers list in Image
142  m_Image->m_Readers.push_back(this);
143 
144  // printf("ReadAccess %d %d\n",(int) m_Image->m_Readers.size(),(int) m_Image->m_Writers.size());
145  // fflush(0);
146  m_Image->m_ReadWriteLock.Unlock();
147 }
const Image * GetImage() const override
void WaitForReleaseOf(ImageAccessorWaitLock *wL)
Uses the WaitLock to wait for another ImageAccessor.
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...
ImageAccessorWaitLock * m_WaitLock
Pointer to a WaitLock struct, that allows other ImageAccessors to wait for this ImageAccessor.
Image class for storing images.
Definition: mitkImage.h:72
mitk::Image::Pointer image
ImageReadAccessor(ImageConstPointer image, const ImageDataItem *iDI=nullptr, int OptionFlags=ImageAccessorBase::DefaultBehavior)
Orders read access for a slice, volume or 4D-Image.
void PreventRecursiveMutexLock(ImageAccessorBase *iAB)
Prevents a recursive mutex lock by comparing thread ids of competing image accessors.
void Increment()
Increments m_WaiterCount. A call of this method is prohibited unless the Mutex m_ReadWriteLock in the...
#define mitkThrowException(classname)
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.
Internal class for managing references on sub-images.