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