OpenASIP 2.2
Loading...
Searching...
No Matches
SafePointer.cc
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.cc
26 *
27 * Implementation 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
35#include <set>
36using std::set;
37
38#include <cassert>
39#include <iterator>
40#include <sstream>
41
42using std::insert_iterator;
43
44#include <algorithm>
45using std::copy;
46
47#include "SafePointer.hh"
48#include "Section.hh"
49#include "Conversion.hh"
50#include "MapTools.hh"
51#include "AssocTools.hh"
52
53namespace TPEF {
54namespace ReferenceManager {
55
56// static member variable initialization
57// These need to be pointers to be able to call SafePointer::cleanup()
58// safely from ~Binary() (which can be from global objects aswell).
59// Otherwise these globals can be freed before the global Binary is
60// causing invalid free() calls.
65
68
69// These are constructed to heap to make sure they are not
70// destructed before any global or static object.
73
74//////////////////////////////////////////////////////////////////////////////
75// SafePointerList
76/////////////////////////////////////////////////////////////////////////////
77
78/**
79 * Constructor.
80 *
81 */
83}
84
85/**
86 * Copy constructor.
87 *
88 */
90 reference_(aList.reference_) {
91
92 for (SafePointerListType::iterator i = aList.list_.begin();
93 i != aList.list_.end(); i++) {
94
95 list_.push_back(*i);
96 }
97}
98
99/**
100 * Destructor.
101 *
102 */
105
106/**
107 * Sets the object all SafePointers in the list are pointing to.
108 *
109 * @param obj The pointer to the object all SafePointers in the list
110 * should be pointing to.
111 */
112void
114
115 reference_ = const_cast<SafePointable*>(obj);
116
117 for (SafePointerListType::iterator i = list_.begin();
118 i != list_.end(); i++) {
119 if (SafePointer::isAlive((*i))) {
120 (*i)->setPointer(reference_);
121 }
122 }
123}
124
125/**
126 * Appends a new SafePointer at the end of the list and sets it's reference
127 * to the reference of the list.
128 *
129 * @param newSafePointer The SafePointer to add.
130 */
131void
133
134 newSafePointer->setPointer(reference());
135 list_.push_back(newSafePointer);
136}
137
138/**
139 * Appends another SafePointerList at the end of the list and sets it's
140 * reference to the reference of the list.
141 *
142 * @param anotherSafePointerList The SafePointerList to add.
143 */
144void
145SafePointerList::append(SafePointerList* anotherSafePointerList) {
146
147 if (anotherSafePointerList == NULL) {
148 return;
149 }
150 anotherSafePointerList->setReference(reference());
151
152 insert_iterator<SafePointerListType> ii(list_,
153 list_.end());
154
155 copy(anotherSafePointerList->list_.begin(),
156 anotherSafePointerList->list_.end(), ii);
157
158}
159
160/**
161 * Sets all SafePointers in the list NULL and clears the list.
162 */
163void
165 setReference(NULL);
166 list_.clear();
167}
168
169/**
170 * Removes all dead (deleted) SafePointers from the list.
171 */
172void
174
175
176 for (SafePointerListType::iterator i = list_.begin();
177 i != list_.end();) {
178 if (!SafePointer::isAlive((*i))) {
179 i = list_.erase(i);
180 } else {
181 ++i;
182 }
183 }
184}
185
186
187//////////////////////////////////////////////////////////////////////////////
188// SafePointer
189//////////////////////////////////////////////////////////////////////////////
190
191const SafePointer
192SafePointer::null(static_cast<SafePointable*>(NULL));
193
194/**
195 * Construct a SafePointer using SectionIndexKey.
196 *
197 * @param key Key to use while requesting the reference.
198 */
200 object_(NULL) {
201
203}
204
205/**
206 * Construct a SafePointer using SectionOffsetKey.
207 *
208 * @param key Key to use while requesting the reference.
209 */
211 object_(NULL) {
212
214}
215
216/**
217 * Construct a SafePointer using FileOffsetKey.
218 *
219 * @param key Key to use while requesting the reference.
220 */
222 object_(NULL) {
223
225}
226
227/**
228 * Construct a SafePointer using section reference.
229 *
230 * @param key Key object to use while requesting the reference.
231 */
233 object_(NULL) {
234
236}
237
238/**
239 * Construct a SafePointer using object reference.
240 *
241 * @param object Object to use while requesting the reference.
242 */
244 object_(object) {
245
246 if (object != NULL) {
248 }
249}
250
251/**
252 * Destructor.
253 *
254 * Informs of deletion of itself to the reference manager.
255 */
259
260/**
261 * Check if SafePointer is alive, that is it's not deleted yet.
262 *
263 * @param pointerToCheck The pointer to check.
264 * @return True if SafePointer is alive.
265 */
266bool
268
269 return
270 (pointerToCheck != NULL &&
272}
273
274/**
275 * Check if object is referenced, that is reference manager is managing
276 * SafePointers that point to that object.
277 *
278 * @param object Object to check.
279 * @return True if object is referenced.
280 */
281bool
283
284 if (!MapTools::containsKey(*referenceMap_, object)) {
285 return false;
286 }
287
288 SafePointerList* theList = (*referenceMap_)[object];
289 theList->cleanupDead();
290
291 return (theList->length() > 0);
292}
293
294
295/**
296 * Inform of a connection between a SectionIndexKey and an object.
297 *
298 * Connects given key with object and sets possible old SafePointers
299 * connected with the key to point to this object.
300 *
301 * @param key Key that the object is connected to.
302 * @param obj Pointer to the connected object.
303 * @exception KeyAlreadyExists If entry with given key already exists.
304 */
305void
309
310/**
311 * Inform of a connection between a SectionOffsetKey and an object.
312 *
313 * Connects given key with object and sets possible old SafePointers
314 * connected with the key to point to this object.
315 *
316 * @param key Key that the object is connected to.
317 * @param obj Pointer to the connected object.
318 * @exception KeyAlreadyExists If entry with given key already exists.
319 */
320void
325
326/**
327 * Inform of a connection between a FileOffsetKey and an object.
328 *
329 * Connects given key with object and sets possible old SafePointers
330 * connected with the key to point to this object.
331 *
332 * @param key Key that the object is connected to.
333 * @param obj Pointer to the connected object.
334 * @exception KeyAlreadyExists If entry with given key already exists.
335 */
336void
340
341/**
342 * Inform of a connection between a SectionKey and an object.
343 *
344 * Connects given key with object and sets possible old SafePointers
345 * connected with the key to point to this object.
346 *
347 * @param key Key that the object is connected to.
348 * @param obj Pointer to the connected object.
349 * @exception KeyAlreadyExists If entry with given key already exists.
350 */
351void
355
356/**
357 *
358 * Returns the SectionIndexKey connected to given object.
359 *
360 * @return The key.
361 * @param obj Object to look the key for.
362 * @exception KeyNotFound If the key cannot be found for the object.
363 *
364 */
367 return genericKeyFor<SectionIndexKey>(obj, *sectionIndexMap_);
368}
369
370/**
371 *
372 * Returns the SectionOffsetKey connected to given object.
373 *
374 * @return The key.
375 * @param obj Object to look the key for.
376 * @exception KeyNotFound If the key cannot be found for the object.
377 *
378 */
381 return genericKeyFor<SectionOffsetKey>(obj, *sectionOffsetMap_);
382}
383
384/**
385 *
386 * Returns the FileOffsetKey connected to given object.
387 *
388 * @return The key.
389 * @param obj Object to look the key for.
390 * @exception KeyNotFound If the key cannot be found for the object.
391 *
392 */
395 return genericKeyFor<FileOffsetKey>(obj, *fileOffsetMap_);
396}
397
398/**
399 *
400 * Returns the SectionKey connected to given object.
401 *
402 * @return The key.
403 * @param obj Object to look the key for.
404 * @exception KeyNotFound If the key cannot be found for the object.
405 *
406 */
409 return genericKeyFor<SectionKey>(obj, *sectionMap_);
410}
411
412/**
413 * Inform of deletion of an object.
414 *
415 * All SafePointers that are pointing to the deleted object are set
416 * to NULL and the object's entry is removed from the ReferenceMap.
417 *
418 * @param obj Deleted object.
419 */
420void
422
424 return;
425 }
426
427 SafePointerList *listOfObj = (*referenceMap_)[obj];
428
429 assert(listOfObj != NULL);
430 listOfObj->cleanup();
431
432 // if the safe pointer list we just cleaned up is not referenced in any
433 // map anymore, it can be deleted safely
434
435 // TODO: for hashmap implementation this will take *very* long time
436 // so fix this before change typedefs in SafePointer.hh
437 if (!MapTools::containsValue(*sectionMap_, listOfObj) &&
441 delete listOfObj;
442 }
443
444 referenceMap_->erase(obj);
445}
446
447/**
448 * Inform of deletion of a SafePointer.
449 *
450 * Removes SafePointer from the list of alive SafePointers.
451 *
452 * @param safePointer The deleted SafePointer.
453 */
454void
456
457 // the null safe pointer is an exception, it shouldn't be never deleted
458 if (safePointer == &null) {
459 return;
460 }
461
462 unsigned int pointersFound = 0;
463 pointersFound = (*aliveSafePointers_).erase(safePointer);
464 assert(pointersFound == 1);
465}
466
467/**
468 * Tries to resolve unresolved references.
469 *
470 * Unreselved references are tried to be resolved by requesting a chunk with
471 * the section's chunk() method the reference points to. Chunks mean
472 * practically offset in the section and the size of the referenced data.
473 * If there's an unresolved reference to an offset in a section that can
474 * be chunked (section contains raw data), then we can create new elements
475 * using chunk() 'on demand'.
476 *
477 * @exception UnresolvedReference If unresolvable references are found.
478 */
479void
481 // try to resolve references in sectionOffsetMap
482 for (SectionOffsetMap::iterator i = sectionOffsetMap_->begin();
483 i != sectionOffsetMap_->end(); i++) {
484
485 SectionOffsetKey key = (*i).first;
486
487 SafePointerList* l = (*i).second;
488 assert(l != NULL);
489 SafePointable* object = l->reference();
490
491 // if reference is resolved continue
492 if (MapTools::containsKey(*referenceMap_, object)) {
493 continue;
494 }
495
496 // there is no section with the identification code of the section
497 // offset key
499 *sectionMap_, SectionKey(key.sectionId()))) {
500 std::stringstream errorMessage;
501 errorMessage << "Cannot find section with identification code "
502 << key.sectionId() << " in the section map.";
503
504#ifndef NDEBUG
505 errorMessage << " SafePointer created in : "
506 << l->front()->debugString();
507#endif
508
510 __FILE__, __LINE__, __func__, errorMessage.str());
511 }
512
513 // try to get the pointer to the section to request chunk from
514 SafePointerList* pointersToSection =
515 (*sectionMap_)[SectionKey(key.sectionId())];
516
517 assert(pointersToSection != NULL);
518
519 Section* theSection =
520 dynamic_cast<Section*>(pointersToSection->reference());
521
522 if (theSection == NULL) {
523 std::stringstream errorMessage;
524 errorMessage << "Can't get section of reference pointed "
525 << "by SectionOffsetKey.";
526
527#ifndef NDEBUG
528 errorMessage << " SafePointer created in : "
529 << l->front()->debugString();
530#endif
531
533 __FILE__, __LINE__, __func__, errorMessage.str());
534 }
535
536 SafePointable* chunk = NULL;
537 try {
538 chunk =
539 static_cast<SafePointable*>(theSection->chunk(key.offset()));
540
541 } catch (const NotChunkable& e) {
542 // Probably there is some section that should be referred by
543 // section offsets but, while reading that section all necessary
544 // keys has not been stored.
545 std::stringstream errorMessage;
546 errorMessage << "Can't resolve section offset, because there"
547 << " no object stored stored for key sectionId: "
548 << key.sectionId() << " offset: " << key.offset();
549#ifndef NDEBUG
550 errorMessage << " SafePointer created in : "
551 << l->front()->debugString();
552#endif
553 throw UnresolvedReference(__FILE__,
554 __LINE__,
555 "SafePointer::resolve()",
556 errorMessage.str());
557 }
558
559 assert(chunk != NULL);
560 addObjectReference(key, chunk);
561 }
562
563 // check if key maps still contain unresolved references and
564 // give propriate error messages.
565 std::stringstream errorMessage;
566 const ReferenceKey *unresolvedKey = NULL;
567 SafePointer *firstUnresolvedPointerOfList = NULL;
568
569 if (unresolvedReferences(*sectionMap_, &unresolvedKey)) {
570 const SectionKey *sectionKey =
571 dynamic_cast<const SectionKey*>(unresolvedKey);
572
573 errorMessage << "with section keys. Requested identification code: "
574 << sectionKey->sectionId() << std::endl;
575
576 // get first of unresolved pointers in safe pointer list
577 firstUnresolvedPointerOfList =
578 (*sectionMap_->find(*sectionKey)).second->front();
579 }
580
581 if (unresolvedReferences(*sectionIndexMap_, &unresolvedKey)) {
582 const SectionIndexKey *indexKey =
583 dynamic_cast<const SectionIndexKey*>(unresolvedKey);
584
585 errorMessage << "Problem with section index keys. "
586 << "Requested section identification code: "
587 << static_cast<int>(indexKey->sectionId())
588 << " index: "
589 << indexKey->index() << std::endl;
590
591 firstUnresolvedPointerOfList =
592 (*sectionIndexMap_->find(*indexKey)).second->front();
593 }
594
595 if (unresolvedReferences(*sectionOffsetMap_, &unresolvedKey)) {
596
597 const SectionOffsetKey *sectionOffsetKey =
598 dynamic_cast<const SectionOffsetKey*>(unresolvedKey);
599
600 errorMessage << "Problem with section offset keys. "
601 << "Requested section identification code: "
602 << static_cast<int>(sectionOffsetKey->sectionId())
603 << " offset: "
604 << sectionOffsetKey->offset() << std::endl;
605
606 firstUnresolvedPointerOfList =
607 (*sectionOffsetMap_->find(*sectionOffsetKey)).second->front();
608 }
609
610 if (unresolvedReferences(*fileOffsetMap_, &unresolvedKey)) {
611 const FileOffsetKey *fileOffsetKey =
612 dynamic_cast<const FileOffsetKey*>(unresolvedKey);
613
614 errorMessage << "Problem with file offset keys. "
615 << "Requested section identification code: "
616 << fileOffsetKey->fileOffset() << std::endl;
617
618 firstUnresolvedPointerOfList =
619 (*fileOffsetMap_->find(*fileOffsetKey)).second->front();
620 }
621
622 if (errorMessage.str() != "") {
623
624#ifndef NDEBUG
625 assert(firstUnresolvedPointerOfList != NULL);
626 errorMessage << " SafePointer created in : "
627 << firstUnresolvedPointerOfList->debugString();
628#endif
630 __FILE__, __LINE__, __func__, errorMessage.str());
631 }
632}
633
634/**
635 * Deletes all entries in all key maps, doesn't clean the ReferenceMap.
636 *
637 * Deletes also the SafePointer lists found in the maps if they are not found
638 * in the reference map. Does not delete SafePointers. This can be called
639 * to free some needless resources after the object model of binary file is
640 * fully constructed, and resolve() is called without an exception.
641 *
642 */
643void
645
646 set<SafePointerList*> listsToDelete;
649 safelyCleanupKeyTable(*fileOffsetMap_, listsToDelete);
650 safelyCleanupKeyTable(*sectionMap_, listsToDelete);
651
652 AssocTools::deleteAllItems(listsToDelete);
653
654 // clear keyForCache...
655 keyForCache_->clear();
656}
657
658/**
659 * Frees all dynamically allocated memory consumed in reference managing.
660 *
661 * Deletes all entires in all maps, safe pointer lists in them and all
662 * alive safe pointers. This method should be called in the destructor of
663 * Binary or in the end of the program.
664 *
665 */
666void
672
673// Debugging methods.......
674
675#ifndef NDEBUG
676#ifndef DOXYGEN_SHOULD_SKIP_THIS
677
678// functions for testing
679const SectionIndexMap*
680SafePointer::SIMap() {
681 return sectionIndexMap_;
682}
683
684const SafePointerList*
685SafePointer::SIMapAt(SectionIndexKey k) {
686 // make sure we don't change the map
688 return (*sectionIndexMap_)[k];
689 }
690 return NULL;
691}
692
693const SectionOffsetMap*
694SafePointer::SOMap() {
695 return sectionOffsetMap_;
696}
697
698const SafePointerList*
699SafePointer::SOMapAt(SectionOffsetKey k) {
700 // make sure we don't change the map
702 return (*sectionOffsetMap_)[k];
703 }
704 return NULL;
705}
706
707const FileOffsetMap*
708SafePointer::FOMap() {
709
710 return fileOffsetMap_;
711}
712
713const SafePointerList*
714SafePointer::FOMapAt(FileOffsetKey k) {
715 // make sure we don't change the map
717 return (*fileOffsetMap_)[k];
718 }
719 return NULL;
720}
721
722const ReferenceMap*
723SafePointer::RMap() {
724 return referenceMap_;
725}
726
727const SafePointerList*
728SafePointer::RMapAt(SafePointable* k) {
729 // make sure we don't change the map
731 return (*referenceMap_)[k];
732 }
733 return NULL;
734}
735
736const SectionMap*
737SafePointer::SMap() {
738 return sectionMap_;
739}
740
741const SafePointerList*
742SafePointer::SMapAt(SectionKey k) {
743 // make sure we don't change the map
745 return (*sectionMap_)[k];
746 }
747 return NULL;
748}
749
750void
751SafePointer::setDebugString(std::string aString) {
752 debugString_ = aString;
753}
754
755std::string
756SafePointer::debugString() const {
757 return debugString_;
758}
759
760// end of test methods
761#endif
762#endif
763
764} // namespace ReferenceManager
765
766}
#define __func__
#define assert(condition)
static void deleteAllItems(ContainerType &aMap)
static bool containsKey(const ContainerType &aContainer, const KeyType &aKey)
static void deleteAllValues(MapType &aMap)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
static bool containsValue(const MapType &aMap, const ValueType &aValue)
void append(SafePointer *newSafePointer)
SafePointable * reference_
Object that SafePointers in this list are pointing to.
void setReference(const SafePointable *obj)
SafePointerListType list_
Container for SafePointers.
static void safelyCleanupKeyTable(MapType &sourceMap, std::set< SafePointerList * > &listsToDelete)
void genericRegisterPointer(const KeyType &key, MapType &destinationMap, SafePointer *newSafePointer)
static bool isAlive(SafePointer *pointerToCheck)
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
static SectionOffsetMap * sectionOffsetMap_
Map of SafePointers that are requested using SectionOffsetKeys.
static const SafePointer null
The default SafePointer that is used in null references.
static FileOffsetMap * fileOffsetMap_
Map of SafePointers that are requested using FileOffsetKeys.
static FileOffsetKey fileOffsetKeyFor(const SafePointable *obj)
static SectionOffsetKey sectionOffsetKeyFor(const SafePointable *obj)
void setPointer(SafePointable *object)
static void notifyDeleted(const SafePointable *obj)
static bool unresolvedReferences(const MapType &mapToCheck, const ReferenceKey **unresolvedKey)
static SafePointerSet * aliveSafePointers_
Set that cointains all alive (not deleted) SafePointers for extra safety.
static SectionIndexKey sectionIndexKeyFor(const SafePointable *obj)
static SectionKey sectionKeyFor(const SafePointable *obj)
static void genericAddObjectReference(const KeyType &key, MapType &destinationMap, const SafePointable *obj)
static SectionMap * sectionMap_
Map of SafePointers that are requested using SectionKeys.
static ReferenceMap * referenceMap_
Map of SafePointers that have resolved references.
static SectionIndexMap * sectionIndexMap_
Map of SafePointers that are requested using SectionIndexKeys.
std::map< KeyForCacheKey, const ReferenceKey * > KeyForCacheMap
static bool isReferenced(const SafePointable *object)
static KeyForCacheMap * keyForCache_
Map for cache.
virtual Chunk * chunk(SectionOffset offset) const
Definition Section.cc:169
std::map< SectionKey, SafePointerList * > SectionMap
Map for SafePointers that are requested using SectionKeys.
std::map< SectionIndexKey, SafePointerList * > SectionIndexMap
Map for SafePointers that are requested using SectionIndexKeys.
std::map< SectionOffsetKey, SafePointerList * > SectionOffsetMap
Map for SafePointers that are requested using SectionOffsetKeys.
std::map< const SafePointable *, SafePointerList * > ReferenceMap
Map for resolved references, that is SafePointers that are pointing to the created object.
std::map< FileOffsetKey, SafePointerList * > FileOffsetMap
Map for SafePointers that are requested using FileOffsetKeys.
std::set< SafePointer * > SafePointerSet
Unordered set of SafePointers.