1 /*=============================================================================
3 Library: CppMicroServices
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics
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
12 http://www.apache.org/licenses/LICENSE-2.0
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.
20 =============================================================================*/
22 #include <usUtils_p.h>
27 template<class S, class TTT, class R>
28 const bool ModuleAbstractTracked<S,TTT,R>::DEBUG_OUTPUT = false;
30 template<class S, class TTT, class R>
31 ModuleAbstractTracked<S,TTT,R>::ModuleAbstractTracked()
36 template<class S, class TTT, class R>
37 ModuleAbstractTracked<S,TTT,R>::~ModuleAbstractTracked()
42 template<class S, class TTT, class R>
43 void ModuleAbstractTracked<S,TTT,R>::SetInitial(const std::vector<S>& initiallist)
45 std::copy(initiallist.begin(), initiallist.end(), std::back_inserter(initial));
49 for(typename std::list<S>::const_iterator item = initial.begin();
50 item != initial.end(); ++item)
52 US_DEBUG << "ModuleAbstractTracked::setInitial: " << (*item);
57 template<class S, class TTT, class R>
58 void ModuleAbstractTracked<S,TTT,R>::TrackInitial()
64 US_UNUSED(Lock(this));
65 if (closed || (initial.size() == 0))
68 * if there are no more initial items
70 return; /* we are done */
73 * move the first item from the initial list to the adding list
74 * within this synchronized block.
76 item = initial.front();
78 if (TTT::IsValid(tracked[item]))
80 /* if we are already tracking this item */
81 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already tracked]: " << item;
82 continue; /* skip this item */
84 if (std::find(adding.begin(), adding.end(), item) != adding.end())
87 * if this item is already in the process of being added.
89 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already adding]: " << item;
90 continue; /* skip this item */
92 adding.push_back(item);
94 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial: " << item;
95 TrackAdding(item, R());
97 * Begin tracking it. We call trackAdding
98 * since we have already put the item in the
104 template<class S, class TTT, class R>
105 void ModuleAbstractTracked<S,TTT,R>::Close()
110 template<class S, class TTT, class R>
111 void ModuleAbstractTracked<S,TTT,R>::Track(S item, R related)
113 T object = TTT::DefaultValue();
115 US_UNUSED(Lock(this));
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())
125 /* if this item is already in the process of being added. */
126 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[already adding]: " << item;
129 adding.push_back(item); /* mark this item is being added */
132 { /* we are currently tracking this item */
133 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[modified]: " << item;
134 Modified(); /* increment modification count */
138 if (!TTT::IsValid(object))
139 { /* we are not tracking the item */
140 TrackAdding(item, related);
144 /* Call customizer outside of synchronized region */
145 CustomizerModified(item, related, object);
147 * If the customizer throws an unchecked exception, it is safe to
153 template<class S, class TTT, class R>
154 void ModuleAbstractTracked<S,TTT,R>::Untrack(S item, R related)
156 T object = TTT::DefaultValue();
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
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
171 std::size_t addingSize = adding.size();
173 if (addingSize != adding.size())
174 { /* if the item is in the process of
177 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[being added]: " << item;
179 * in case the item is untracked while in the process of
183 object = tracked[item];
185 * must remove from tracker before
186 * calling customizer callback
189 if (!TTT::IsValid(object))
190 { /* are we actually tracking the item */
193 Modified(); /* increment modification count */
195 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[removed]: " << item;
196 /* Call customizer outside of synchronized region */
197 CustomizerRemoved(item, related, object);
199 * If the customizer throws an unchecked exception, it is safe to let it
204 template<class S, class TTT, class R>
205 std::size_t ModuleAbstractTracked<S,TTT,R>::Size() const
207 return tracked.size();
210 template<class S, class TTT, class R>
211 bool ModuleAbstractTracked<S,TTT,R>::IsEmpty() const
213 return tracked.empty();
216 template<class S, class TTT, class R>
217 typename ModuleAbstractTracked<S,TTT,R>::T
218 ModuleAbstractTracked<S,TTT,R>::GetCustomizedObject(S item) const
220 typename TrackingMap::const_iterator i = tracked.find(item);
221 if (i != tracked.end()) return i->second;
225 template<class S, class TTT, class R>
226 void ModuleAbstractTracked<S,TTT,R>::GetTracked(std::vector<S>& items) const
228 for (typename TrackingMap::const_iterator i = tracked.begin();
229 i != tracked.end(); ++i)
231 items.push_back(i->first);
235 template<class S, class TTT, class R>
236 void ModuleAbstractTracked<S,TTT,R>::Modified()
241 template<class S, class TTT, class R>
242 int ModuleAbstractTracked<S,TTT,R>::GetTrackingCount() const
244 return trackingCount;
247 template<class S, class TTT, class R>
248 void ModuleAbstractTracked<S,TTT,R>::CopyEntries(TrackingMap& map) const
250 map.insert(tracked.begin(), tracked.end());
253 template<class S, class TTT, class R>
254 bool ModuleAbstractTracked<S,TTT,R>::CustomizerAddingFinal(S item, const T& custom)
256 US_UNUSED(Lock(this));
257 std::size_t addingSize = adding.size();
259 if (addingSize != adding.size() && !closed)
262 * if the item was not untracked during the customizer
265 if (TTT::IsValid(custom))
267 tracked[item] = custom;
268 Modified(); /* increment modification count */
269 this->NotifyAll(); /* notify any waiters */
279 template<class S, class TTT, class R>
280 void ModuleAbstractTracked<S,TTT,R>::TrackAdding(S item, R related)
282 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding:" << item;
283 T object = TTT::DefaultValue();
284 bool becameUntracked = false;
285 /* Call customizer outside of synchronized region */
288 object = CustomizerAdding(item, related);
289 becameUntracked = this->CustomizerAddingFinal(item, object);
294 * If the customizer throws an exception, it will
295 * propagate after the cleanup code.
297 this->CustomizerAddingFinal(item, object);
302 * The item became untracked during the customizer callback.
304 if (becameUntracked && TTT::IsValid(object))
306 US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding[removed]: " << item;
307 /* Call customizer outside of synchronized region */
308 CustomizerRemoved(item, related, object);
310 * If the customizer throws an unchecked exception, it is safe to