OpenASIP 2.2
Loading...
Searching...
No Matches
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
43namespace TPEF {
44namespace 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 */
57inline
58SafePointable*
59SafePointerList::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 */
68inline
69SafePointerList::LengthType
70SafePointerList::length() const {
71 return list_.size();
72}
73
74/**
75 * Returns first element from the list.
76 *
77 * @return First from the list.
78 */
79inline
80SafePointer*
81SafePointerList::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 */
95inline
96SafePointable*
97SafePointer::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 */
106inline
107void
108SafePointer::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 */
125template <typename ObjType>
126SafePointer*
127SafePointer::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 */
146template <typename ObjType>
147SafePointer*
148SafePointer::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 */
160template <typename KeyType, typename MapType>
161void
162SafePointer::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 */
196template <typename KeyType, typename MapType>
197void
198SafePointer::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 */
279template <typename KeyType, typename MapType>
280KeyType
281SafePointer::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 */
330template <typename MapType>
331bool
332SafePointer::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 */
362inline const SafePointer*
363SafePointer::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 */
386inline void
387SafePointer::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 */
410template <typename MapType>
411void
412SafePointer::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}