OpenASIP  2.0
SafePointer.icc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file SafePointer.icc
26  *
27  * Inline and template functions of the SafePointer class.
28  *
29  * @author Pekka Jääskeläinen 2003 (pjaaskel-no.spam-cs.tut.fi)
30  * @note reviewed 29 Aug 2003 by rm, ml, ac, tr
31  *
32  * @note rating: yellow
33  */
34 #include <set>
35 #include <algorithm>
36 
37 #include "SafePointable.hh"
38 #include "AssocTools.hh"
39 #include "MapTools.hh"
40 #include "Application.hh"
41 #include "Conversion.hh"
42 
43 namespace TPEF {
44 namespace ReferenceManager {
45 
46 ///////////////////////////////////////////////////////////////////////////////
47 // SafePointerList
48 ///////////////////////////////////////////////////////////////////////////////
49 
50 /**
51  * Returns the object all SafePointers in the list are pointing to.
52  *
53  * @return The pointer to the object all SafePointers in the list
54  * are pointing to.
55  *
56  */
57 inline
58 SafePointable*
59 SafePointerList::reference() const {
60  return reference_;
61 }
62 
63 /**
64  * Returns the count of SafePointers in the list.
65  *
66  * @return Count of SafePointers in the list.
67  */
68 inline
69 SafePointerList::LengthType
70 SafePointerList::length() const {
71  return list_.size();
72 }
73 
74 /**
75  * Returns first element from the list.
76  *
77  * @return First from the list.
78  */
79 inline
80 SafePointer*
81 SafePointerList::front() const {
82  return list_.front();
83 }
84 
85 
86 ///////////////////////////////////////////////////////////////////////////////
87 // SafePointer
88 ///////////////////////////////////////////////////////////////////////////////
89 
90 /**
91  * Returns the pointer to the referenced object (can be NULL if unresolved).
92  *
93  * @return Pointer to the object (can be NULL).
94  */
95 inline
96 SafePointable*
97 SafePointer::pointer() const {
98  return object_;
99 }
100 
101 /**
102  * Sets the pointer to the real referenced object.
103  *
104  * @param object Pointer to the object.
105  */
106 inline
107 void
108 SafePointer::setPointer(SafePointable* object) {
109  object_ = object;
110 }
111 
112 #ifndef NDEBUG
113 
114 /**
115  * Creates pointer with debug data.
116  *
117  * See SafePointer constructors for more information of
118  * possible ObjTypes.
119  *
120  * @param obj ReferenceKey or SafePointable pointer.
121  * @param file File where pointer is created.
122  * @param line Line where pointer is created.
123  * @return Pointer to created the pointer.
124  */
125 template <typename ObjType>
126 SafePointer*
127 SafePointer::debugCreate(ObjType obj, const char *file, int line) {
128  std::stringstream debugMsg;
129  debugMsg << file << " at line: " << line;
130  SafePointer *pointer = new SafePointer(obj);
131  pointer->setDebugString(debugMsg.str());
132  return pointer;
133 }
134 
135 #endif
136 
137 /**
138  * Creates pointer without debug data.
139  *
140  * See SafePointer constructors for more information of
141  * possible ObjTypes.
142  *
143  * @param obj ReferenceKey or SafePointable pointer.
144  * @return Pointer to created the pointer.
145  */
146 template <typename ObjType>
147 SafePointer*
148 SafePointer::genericCreate(ObjType obj) {
149  return new SafePointer(obj);
150 }
151 
152 /**
153  * Template function, allows registering SafePointers with different
154  * key types.
155  *
156  * @param key Key to use while registering the reference.
157  * @param destinationMap Map to update the reference to.
158  * @param newSafePointer The SafePointer to register.
159  */
160 template <typename KeyType, typename MapType>
161 void
162 SafePointer::genericRegisterPointer(
163  const KeyType& key,
164  MapType& destinationMap,
165  SafePointer* newSafePointer) {
166 
167  SafePointerList* pointerList = NULL;
168 
169  if (!MapTools::containsKey(destinationMap, key)) {
170  pointerList = new ReferenceManager::SafePointerList();
171  destinationMap[key] = pointerList;
172  } else {
173  typename MapType::iterator oldList = destinationMap.find(key);
174  pointerList = (*oldList).second;
175  }
176 
177  if (pointerList->reference() == NULL &&
178  newSafePointer->pointer() != NULL) {
179  pointerList->setReference(newSafePointer->pointer());
180  }
181 
182  pointerList->append(newSafePointer);
183  (*aliveSafePointers_).insert(newSafePointer);
184 }
185 
186 
187 /**
188  * Template function, registers connection between an object and a key.
189  *
190  * @param key Key to use while registering the connection.
191  * @param keyMap Map where to update the connection in.
192  * @param obj The object reference to set the key to point to.
193  * @exception KeyAlreadyExists If entry with given key already exists.
194  * @exception ObjectAlreadyRegistered If key was already connected.
195  */
196 template <typename KeyType, typename MapType>
197 void
198 SafePointer::genericAddObjectReference(
199  const KeyType& key, MapType& keyMap, const SafePointable* obj) {
200  assert(obj != NULL);
201 
202  typename MapType::iterator oldKeyListPos = keyMap.find(key);
203  typename ReferenceMap::iterator oldRefListPos = (*referenceMap_).find(obj);
204 
205  bool oldKeyListFound = oldKeyListPos != keyMap.end();
206  bool oldRefListFound = oldRefListPos != (*referenceMap_).end();
207 
208  SafePointerList* oldKeyList = NULL;
209  if (oldKeyListFound) {
210  oldKeyList = (*oldKeyListPos).second;
211  }
212 
213  SafePointerList* oldRefList = NULL;
214  if (oldRefListFound) {
215  oldRefList = (*oldRefListPos).second;
216  }
217 
218  SafePointerList* mergedList = NULL;
219 
220  bool tryingToChangeReference = (oldKeyList != NULL &&
221  oldKeyList->reference() != NULL &&
222  oldKeyList->reference() != obj);
223 
224  bool tryingToReregister = (oldKeyListFound && oldRefListFound &&
225  oldKeyList == oldRefList);
226 
227  if (tryingToChangeReference || tryingToReregister) {
228  // key already registered, this is an error condition
229  // we don't allow changing the reference at this point
230  throw KeyAlreadyExists(__FILE__, __LINE__,
231  "SafePointer::"
232  "genericAddObjectReference()",
233  "Multiple references for a key.");
234 
235  }
236 
237  if (oldKeyListFound && oldRefListFound) {
238 
239  // combine old SafePointer list in reference map to the list in
240  // keyMap
241  assert(oldKeyList != NULL);
242  assert(oldRefList != NULL);
243 
244  oldRefList->append(oldKeyList);
245  mergedList = oldRefList;
246  delete oldKeyList;
247  oldKeyList = NULL;
248 
249  } else {
250  if (oldKeyListFound) {
251  mergedList = oldKeyList;
252  } else if (oldRefListFound) {
253  mergedList = oldRefList;
254  } else {
255  // create empty list to maintain the link between the key and obj
256  mergedList = new SafePointerList();
257  }
258  }
259  assert(mergedList != NULL);
260 
261  keyMap[key] = mergedList;
262  (*referenceMap_)[obj] = mergedList;
263 
264  mergedList->setReference(obj);
265 }
266 
267 /**
268  * Template function, returns the key of given type for given object.
269  *
270  * Function contains internal cache that is cleared every time when the
271  * keytables are. Cache speeds up significantly reading of a.out files
272  * and writing of TPEF.
273  *
274  * @param obj Object to look the key for.
275  * @param sourceMap Map where to look the key for.
276  * @return Key for the object.
277  * @exception KeyNotFound If key cannot be found for the object.
278  */
279 template <typename KeyType, typename MapType>
280 KeyType
281 SafePointer::genericKeyFor(const SafePointable* obj, MapType& sourceMap) {
282  if (!MapTools::containsKey(*referenceMap_, obj)) {
283  throw KeyNotFound(__FILE__, __LINE__,
284  "SafePointer::genericKeyFor()",
285  "Object not in reference table.");
286  }
287 
288  KeyForCacheKey cacheKey(obj, &sourceMap);
289 
290  // add stuff of requested map to cache if necessary
291  if (!MapTools::containsKey(*keyForCache_, cacheKey)) {
292 
293  // add resolved source map elements to cache
294  typename MapType::const_iterator i = sourceMap.begin();
295 
296  while (i != sourceMap.end()) {
297  SafePointerList *spList = (*i).second;
298 
299  if (spList != NULL &&
300  spList->reference() != NULL) {
301 
302  KeyForCacheKey addKey(spList->reference(), &sourceMap);
303  (*keyForCache_)[addKey] = &(*i).first;
304 
305  // keys are connected to the object with the SafePointerList
306  // SafePointerList* theList =
307  // MapTools::valueForKey<SafePointerList*>(*referenceMap_,obj);
308  // MapTools::keyForValue<KeyType>(sourceMap, theList);
309  }
310 
311  i++;
312  }
313  }
314 
315  const KeyType *returnKey =
316  dynamic_cast<const KeyType*>(
317  MapTools::valueForKey<const ReferenceKey*>(*keyForCache_, cacheKey));
318 
319  return *returnKey;
320 }
321 
322 /**
323  * Returns true if the map has unresolved references, that is SafePointers
324  * that are pointing to NULL.
325  *
326  * @param mapToCheck The map to look in.
327  * @param unresolvedKey If there was unresolvedReferences pointer to key.
328  * @return True if map has unresolved references.
329  */
330 template <typename MapType>
331 bool
332 SafePointer::unresolvedReferences(const MapType& mapToCheck,
333  const ReferenceKey **unresolvedKey) {
334 
335  for (typename MapType::const_iterator i = mapToCheck.begin();
336  i != mapToCheck.end(); i++) {
337 
338  SafePointerList* listToCheck = (*i).second;
339 
340  if (listToCheck != NULL && listToCheck->length() > 0) {
341  // reference to pointer was not allowed,
342  // so this is not very beautiful
343  *unresolvedKey = &((*i).first);
344  return (listToCheck->reference() == NULL);
345  }
346  }
347 
348  return false;
349 }
350 
351 /**
352  * Helper function which deletes old SafePointer (if defined) and returns
353  * a new one pointing to given object.
354  *
355  * Replaces one reference to new one (by creating new SafePointer, but do
356  * not change references else where.
357  *
358  * @param old The old SafePointer.
359  * @param obj The object to set the new SafePointer to point to.
360  * @return The new SafePointer.
361  */
362 inline const SafePointer*
363 SafePointer::replaceReference(const SafePointer* old, SafePointable* obj) {
364 
365  assert(old != NULL);
366  if (old != &null) {
367  delete old;
368  old = NULL;
369  }
370 
371  if (obj != NULL) {
372  return new SafePointer(obj);
373  } else {
374  return &null;
375  }
376 }
377 
378 /**
379  * Replaces all references to oldObj to referer newObj.
380  *
381  * After this function call there will be no references to oldObj.
382  *
383  * @param oldObj The old SafePointable object.
384  * @param newObj The new SafePointable object.
385  */
386 inline void
387 SafePointer::replaceAllReferences(SafePointable *newObj, SafePointable* oldObj) {
388  SafePointerList* listToModify =
389  MapTools::valueForKey<SafePointerList*>(*referenceMap_, oldObj);
390 
391  assert(listToModify != NULL);
392 
393  (*referenceMap_)[newObj] = listToModify;
394 
395  listToModify->setReference(newObj);
396 
397  referenceMap_->erase(oldObj);
398 }
399 
400 
401 /**
402  * Safely cleans up key map's SafePointerLists.
403  *
404  * Adds lists that can be deleted safely (lists that are not found in
405  * the reference map) to the given set.
406  *
407  * @param sourceMap Map to clean.
408  * @param listsToDelete Set to add lists that are not found in reference map.
409  */
410 template <typename MapType>
411 void
412 SafePointer::safelyCleanupKeyTable(
413  MapType& sourceMap,
414  std::set<SafePointerList*>& listsToDelete) {
415 
416  for (typename MapType::iterator i = sourceMap.begin();
417  i != sourceMap.end(); i++) {
418 
419  SafePointerList* listToCheck = (*i).second;
420  assert(listToCheck != NULL);
421 
422  SafePointable* obj = listToCheck->reference();
423 
424  if (obj == NULL || !MapTools::containsKey(*referenceMap_, obj)) {
425 
426  listsToDelete.insert(listToCheck);
427  listToCheck->cleanup();
428  }
429 
430  }
431  sourceMap.clear();
432 }
433 
434 } // namespace ReferenceManager
435 
436 }