2 Copyright (c) 2002-2009 Tampere University.
4 This file is part of TTA-Based Codesign Environment (TCE).
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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.
25 * @file SafePointer.icc
27 * Inline and template functions of the SafePointer class.
29 * @author Pekka Jääskeläinen 2003 (pjaaskel-no.spam-cs.tut.fi)
30 * @note reviewed 29 Aug 2003 by rm, ml, ac, tr
32 * @note rating: yellow
37 #include "SafePointable.hh"
38 #include "AssocTools.hh"
39 #include "MapTools.hh"
40 #include "Application.hh"
41 #include "Conversion.hh"
44 namespace ReferenceManager {
46 ///////////////////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////////////////
51 * Returns the object all SafePointers in the list are pointing to.
53 * @return The pointer to the object all SafePointers in the list
59 SafePointerList::reference() const {
64 * Returns the count of SafePointers in the list.
66 * @return Count of SafePointers in the list.
69 SafePointerList::LengthType
70 SafePointerList::length() const {
75 * Returns first element from the list.
77 * @return First from the list.
81 SafePointerList::front() const {
86 ///////////////////////////////////////////////////////////////////////////////
88 ///////////////////////////////////////////////////////////////////////////////
91 * Returns the pointer to the referenced object (can be NULL if unresolved).
93 * @return Pointer to the object (can be NULL).
97 SafePointer::pointer() const {
102 * Sets the pointer to the real referenced object.
104 * @param object Pointer to the object.
108 SafePointer::setPointer(SafePointable* object) {
115 * Creates pointer with debug data.
117 * See SafePointer constructors for more information of
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.
125 template <typename ObjType>
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());
138 * Creates pointer without debug data.
140 * See SafePointer constructors for more information of
143 * @param obj ReferenceKey or SafePointable pointer.
144 * @return Pointer to created the pointer.
146 template <typename ObjType>
148 SafePointer::genericCreate(ObjType obj) {
149 return new SafePointer(obj);
153 * Template function, allows registering SafePointers with different
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.
160 template <typename KeyType, typename MapType>
162 SafePointer::genericRegisterPointer(
164 MapType& destinationMap,
165 SafePointer* newSafePointer) {
167 SafePointerList* pointerList = NULL;
169 if (!MapTools::containsKey(destinationMap, key)) {
170 pointerList = new ReferenceManager::SafePointerList();
171 destinationMap[key] = pointerList;
173 typename MapType::iterator oldList = destinationMap.find(key);
174 pointerList = (*oldList).second;
177 if (pointerList->reference() == NULL &&
178 newSafePointer->pointer() != NULL) {
179 pointerList->setReference(newSafePointer->pointer());
182 pointerList->append(newSafePointer);
183 (*aliveSafePointers_).insert(newSafePointer);
188 * Template function, registers connection between an object and a key.
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.
196 template <typename KeyType, typename MapType>
198 SafePointer::genericAddObjectReference(
199 const KeyType& key, MapType& keyMap, const SafePointable* obj) {
202 typename MapType::iterator oldKeyListPos = keyMap.find(key);
203 typename ReferenceMap::iterator oldRefListPos = (*referenceMap_).find(obj);
205 bool oldKeyListFound = oldKeyListPos != keyMap.end();
206 bool oldRefListFound = oldRefListPos != (*referenceMap_).end();
208 SafePointerList* oldKeyList = NULL;
209 if (oldKeyListFound) {
210 oldKeyList = (*oldKeyListPos).second;
213 SafePointerList* oldRefList = NULL;
214 if (oldRefListFound) {
215 oldRefList = (*oldRefListPos).second;
218 SafePointerList* mergedList = NULL;
220 bool tryingToChangeReference = (oldKeyList != NULL &&
221 oldKeyList->reference() != NULL &&
222 oldKeyList->reference() != obj);
224 bool tryingToReregister = (oldKeyListFound && oldRefListFound &&
225 oldKeyList == oldRefList);
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__,
232 "genericAddObjectReference()",
233 "Multiple references for a key.");
237 if (oldKeyListFound && oldRefListFound) {
239 // combine old SafePointer list in reference map to the list in
241 assert(oldKeyList != NULL);
242 assert(oldRefList != NULL);
244 oldRefList->append(oldKeyList);
245 mergedList = oldRefList;
250 if (oldKeyListFound) {
251 mergedList = oldKeyList;
252 } else if (oldRefListFound) {
253 mergedList = oldRefList;
255 // create empty list to maintain the link between the key and obj
256 mergedList = new SafePointerList();
259 assert(mergedList != NULL);
261 keyMap[key] = mergedList;
262 (*referenceMap_)[obj] = mergedList;
264 mergedList->setReference(obj);
268 * Template function, returns the key of given type for given object.
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.
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.
279 template <typename KeyType, typename MapType>
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.");
288 KeyForCacheKey cacheKey(obj, &sourceMap);
290 // add stuff of requested map to cache if necessary
291 if (!MapTools::containsKey(*keyForCache_, cacheKey)) {
293 // add resolved source map elements to cache
294 typename MapType::const_iterator i = sourceMap.begin();
296 while (i != sourceMap.end()) {
297 SafePointerList *spList = (*i).second;
299 if (spList != NULL &&
300 spList->reference() != NULL) {
302 KeyForCacheKey addKey(spList->reference(), &sourceMap);
303 (*keyForCache_)[addKey] = &(*i).first;
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);
315 const KeyType *returnKey =
316 dynamic_cast<const KeyType*>(
317 MapTools::valueForKey<const ReferenceKey*>(*keyForCache_, cacheKey));
323 * Returns true if the map has unresolved references, that is SafePointers
324 * that are pointing to NULL.
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.
330 template <typename MapType>
332 SafePointer::unresolvedReferences(const MapType& mapToCheck,
333 const ReferenceKey **unresolvedKey) {
335 for (typename MapType::const_iterator i = mapToCheck.begin();
336 i != mapToCheck.end(); i++) {
338 SafePointerList* listToCheck = (*i).second;
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);
352 * Helper function which deletes old SafePointer (if defined) and returns
353 * a new one pointing to given object.
355 * Replaces one reference to new one (by creating new SafePointer, but do
356 * not change references else where.
358 * @param old The old SafePointer.
359 * @param obj The object to set the new SafePointer to point to.
360 * @return The new SafePointer.
362 inline const SafePointer*
363 SafePointer::replaceReference(const SafePointer* old, SafePointable* obj) {
372 return new SafePointer(obj);
379 * Replaces all references to oldObj to referer newObj.
381 * After this function call there will be no references to oldObj.
383 * @param oldObj The old SafePointable object.
384 * @param newObj The new SafePointable object.
387 SafePointer::replaceAllReferences(SafePointable *newObj, SafePointable* oldObj) {
388 SafePointerList* listToModify =
389 MapTools::valueForKey<SafePointerList*>(*referenceMap_, oldObj);
391 assert(listToModify != NULL);
393 (*referenceMap_)[newObj] = listToModify;
395 listToModify->setReference(newObj);
397 referenceMap_->erase(oldObj);
402 * Safely cleans up key map's SafePointerLists.
404 * Adds lists that can be deleted safely (lists that are not found in
405 * the reference map) to the given set.
407 * @param sourceMap Map to clean.
408 * @param listsToDelete Set to add lists that are not found in reference map.
410 template <typename MapType>
412 SafePointer::safelyCleanupKeyTable(
414 std::set<SafePointerList*>& listsToDelete) {
416 for (typename MapType::iterator i = sourceMap.begin();
417 i != sourceMap.end(); i++) {
419 SafePointerList* listToCheck = (*i).second;
420 assert(listToCheck != NULL);
422 SafePointable* obj = listToCheck->reference();
424 if (obj == NULL || !MapTools::containsKey(*referenceMap_, obj)) {
426 listsToDelete.insert(listToCheck);
427 listToCheck->cleanup();
434 } // namespace ReferenceManager