Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
usModuleAbstractTracked.tpp
Go to the documentation of this file.
1 /*=============================================================================
2 
3  Library: CppMicroServices
4 
5  Copyright (c) German Cancer Research Center,
6  Division of Medical and Biological Informatics
7 
8  Licensed under the Apache License, Version 2.0 (the "License");
9  you may not use this file except in compliance with the License.
10  You may obtain a copy of the License at
11 
12  http://www.apache.org/licenses/LICENSE-2.0
13 
14  Unless required by applicable law or agreed to in writing, software
15  distributed under the License is distributed on an "AS IS" BASIS,
16  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  See the License for the specific language governing permissions and
18  limitations under the License.
19 
20 =============================================================================*/
21 
22 #include <usUtils_p.h>
23 #include <iterator>
24 
25 US_BEGIN_NAMESPACE
26 
27 template<class S, class TTT, class R>
28 const bool ModuleAbstractTracked<S,TTT,R>::DEBUG_OUTPUT = false;
29 
30 template<class S, class TTT, class R>
31 ModuleAbstractTracked<S,TTT,R>::ModuleAbstractTracked()
32 {
33  closed = false;
34 }
35 
36 template<class S, class TTT, class R>
37 ModuleAbstractTracked<S,TTT,R>::~ModuleAbstractTracked()
38 {
39 
40 }
41 
42 template<class S, class TTT, class R>
43 void ModuleAbstractTracked<S,TTT,R>::SetInitial(const std::vector<S>& initiallist)
44 {
45  std::copy(initiallist.begin(), initiallist.end(), std::back_inserter(initial));
46 
47  if (DEBUG_OUTPUT)
48  {
49  for(typename std::list<S>::const_iterator item = initial.begin();
50  item != initial.end(); ++item)
51  {
52  US_DEBUG << "ModuleAbstractTracked::setInitial: " << (*item);
53  }
54  }
55 }
56 
57 template<class S, class TTT, class R>
58 void ModuleAbstractTracked<S,TTT,R>::TrackInitial()
59 {
60  while (true)
61  {
62  S item;
63  {
64  US_UNUSED(Lock(this));
65  if (closed || (initial.size() == 0))
66  {
67  /*
68  * if there are no more initial items
69  */
70  return; /* we are done */
71  }
72  /*
73  * move the first item from the initial list to the adding list
74  * within this synchronized block.
75  */
76  item = initial.front();
77  initial.pop_front();
78  if (TTT::IsValid(tracked[item]))
79  {
80  /* if we are already tracking this item */
81  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already tracked]: " << item;
82  continue; /* skip this item */
83  }
84  if (std::find(adding.begin(), adding.end(), item) != adding.end())
85  {
86  /*
87  * if this item is already in the process of being added.
88  */
89  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already adding]: " << item;
90  continue; /* skip this item */
91  }
92  adding.push_back(item);
93  }
94  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial: " << item;
95  TrackAdding(item, R());
96  /*
97  * Begin tracking it. We call trackAdding
98  * since we have already put the item in the
99  * adding list.
100  */
101  }
102 }
103 
104 template<class S, class TTT, class R>
105 void ModuleAbstractTracked<S,TTT,R>::Close()
106 {
107  closed = true;
108 }
109 
110 template<class S, class TTT, class R>
111 void ModuleAbstractTracked<S,TTT,R>::Track(S item, R related)
112 {
113  T object = TTT::DefaultValue();
114  {
115  US_UNUSED(Lock(this));
116  if (closed)
117  {
118  return;
119  }
120  object = tracked[item];
121  if (!TTT::IsValid(object))
122  { /* we are not tracking the item */
123  if (std::find(adding.begin(), adding.end(),item) != adding.end())
124  {
125  /* if this item is already in the process of being added. */
126  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[already adding]: " << item;
127  return;
128  }
129  adding.push_back(item); /* mark this item is being added */
130  }
131  else
132  { /* we are currently tracking this item */
133  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[modified]: " << item;
134  Modified(); /* increment modification count */
135  }
136  }
137 
138  if (!TTT::IsValid(object))
139  { /* we are not tracking the item */
140  TrackAdding(item, related);
141  }
142  else
143  {
144  /* Call customizer outside of synchronized region */
145  CustomizerModified(item, related, object);
146  /*
147  * If the customizer throws an unchecked exception, it is safe to
148  * let it propagate
149  */
150  }
151 }
152 
153 template<class S, class TTT, class R>
154 void ModuleAbstractTracked<S,TTT,R>::Untrack(S item, R related)
155 {
156  T object = TTT::DefaultValue();
157  {
158  US_UNUSED(Lock(this));
159  std::size_t initialSize = initial.size();
160  initial.remove(item);
161  if (initialSize != initial.size())
162  { /* if this item is already in the list
163  * of initial references to process
164  */
165  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[removed from initial]: " << item;
166  return; /* we have removed it from the list and it will not be
167  * processed
168  */
169  }
170 
171  std::size_t addingSize = adding.size();
172  adding.remove(item);
173  if (addingSize != adding.size())
174  { /* if the item is in the process of
175  * being added
176  */
177  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[being added]: " << item;
178  return; /*
179  * in case the item is untracked while in the process of
180  * adding
181  */
182  }
183  object = tracked[item];
184  /*
185  * must remove from tracker before
186  * calling customizer callback
187  */
188  tracked.erase(item);
189  if (!TTT::IsValid(object))
190  { /* are we actually tracking the item */
191  return;
192  }
193  Modified(); /* increment modification count */
194  }
195  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[removed]: " << item;
196  /* Call customizer outside of synchronized region */
197  CustomizerRemoved(item, related, object);
198  /*
199  * If the customizer throws an unchecked exception, it is safe to let it
200  * propagate
201  */
202 }
203 
204 template<class S, class TTT, class R>
205 std::size_t ModuleAbstractTracked<S,TTT,R>::Size() const
206 {
207  return tracked.size();
208 }
209 
210 template<class S, class TTT, class R>
211 bool ModuleAbstractTracked<S,TTT,R>::IsEmpty() const
212 {
213  return tracked.empty();
214 }
215 
216 template<class S, class TTT, class R>
217 typename ModuleAbstractTracked<S,TTT,R>::T
218 ModuleAbstractTracked<S,TTT,R>::GetCustomizedObject(S item) const
219 {
220  typename TrackingMap::const_iterator i = tracked.find(item);
221  if (i != tracked.end()) return i->second;
222  return T();
223 }
224 
225 template<class S, class TTT, class R>
226 void ModuleAbstractTracked<S,TTT,R>::GetTracked(std::vector<S>& items) const
227 {
228  for (typename TrackingMap::const_iterator i = tracked.begin();
229  i != tracked.end(); ++i)
230  {
231  items.push_back(i->first);
232  }
233 }
234 
235 template<class S, class TTT, class R>
236 void ModuleAbstractTracked<S,TTT,R>::Modified()
237 {
238  trackingCount.Ref();
239 }
240 
241 template<class S, class TTT, class R>
242 int ModuleAbstractTracked<S,TTT,R>::GetTrackingCount() const
243 {
244  return trackingCount;
245 }
246 
247 template<class S, class TTT, class R>
248 void ModuleAbstractTracked<S,TTT,R>::CopyEntries(TrackingMap& map) const
249 {
250  map.insert(tracked.begin(), tracked.end());
251 }
252 
253 template<class S, class TTT, class R>
254 bool ModuleAbstractTracked<S,TTT,R>::CustomizerAddingFinal(S item, const T& custom)
255 {
256  US_UNUSED(Lock(this));
257  std::size_t addingSize = adding.size();
258  adding.remove(item);
259  if (addingSize != adding.size() && !closed)
260  {
261  /*
262  * if the item was not untracked during the customizer
263  * callback
264  */
265  if (TTT::IsValid(custom))
266  {
267  tracked[item] = custom;
268  Modified(); /* increment modification count */
269  this->NotifyAll(); /* notify any waiters */
270  }
271  return false;
272  }
273  else
274  {
275  return true;
276  }
277 }
278 
279 template<class S, class TTT, class R>
280 void ModuleAbstractTracked<S,TTT,R>::TrackAdding(S item, R related)
281 {
282  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding:" << item;
283  T object = TTT::DefaultValue();
284  bool becameUntracked = false;
285  /* Call customizer outside of synchronized region */
286  try
287  {
288  object = CustomizerAdding(item, related);
289  becameUntracked = this->CustomizerAddingFinal(item, object);
290  }
291  catch (...)
292  {
293  /*
294  * If the customizer throws an exception, it will
295  * propagate after the cleanup code.
296  */
297  this->CustomizerAddingFinal(item, object);
298  throw;
299  }
300 
301  /*
302  * The item became untracked during the customizer callback.
303  */
304  if (becameUntracked && TTT::IsValid(object))
305  {
306  US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding[removed]: " << item;
307  /* Call customizer outside of synchronized region */
308  CustomizerRemoved(item, related, object);
309  /*
310  * If the customizer throws an unchecked exception, it is safe to
311  * let it propagate
312  */
313  }
314 }
315 
316 US_END_NAMESPACE