exceptionmanager.cpp

Go to the documentation of this file.
00001 /*
00002         Description: Support for recursive C++ exception handling
00003                         compatible with Qt qApp->processEvents()
00004 
00005                         See exception_manager.txt for details.
00006 
00007         Author: Marco Costalba (C) 2005-2006
00008 
00009         Copyright: See COPYING file that comes with this distribution
00010 
00011 */
00012 #include "exceptionmanager.h"
00013 
00014 ExceptionManager::ExceptionManager() {
00015 
00016         excpId = regionId = currentRegionId = 1;
00017         descriptions.append("we start from 1");
00018 }
00019 
00020 void ExceptionManager::init(int* excp, const QString& desc) {
00021 
00022         *excp = excpId++;
00023         descriptions.append(desc);
00024 }
00025 
00026 const QString ExceptionManager::desc(int excpId) {
00027 
00028         return descriptions[excpId];
00029 }
00030 
00031 bool ExceptionManager::isMatch(int value, int excp, const QString& context) {
00032 
00033         bool match = (value == excp);
00034         if (match) {
00035                 QString info("Caught exception \'" + descriptions[excp] +
00036                              "\' while in " + context);
00037                 qDebug(info);
00038         }
00039         return match;
00040 }
00041 
00042 void ExceptionManager::add(int excpId, bool verbose) {
00043 // add a new exception in currentThrowableSet
00044 
00045         // are prepended so to use a for loop starting
00046         // from begin to find the latest. Exceptions are
00047         // always added/removed from both totalThrowableSet
00048         // and regionThrowableSet
00049         totalThrowableSet.prepend(Exception(excpId, verbose));
00050         regionThrowableSet.prepend(Exception(excpId, verbose));
00051 }
00052 
00053 void ExceptionManager::remove(int excpId) {
00054 // removes ONE exception in totalThrowableSet and ONE in regionThrowableSet.
00055 // if add and remove calls are correctly nested the removed
00056 // excp should be the first in both throwable sets
00057 
00058         if (totalThrowableSet.isEmpty() || regionThrowableSet.isEmpty()) {
00059                 qDebug("ASSERT in remove: removing %i from an empty set", excpId);
00060                 return;
00061         }
00062         // remove from region.
00063         SetIt itReg(regionThrowableSet.begin());
00064         if ((*itReg).excpId != excpId) {
00065                 qDebug("ASSERT in remove: %i is not the first in list", excpId);
00066                 return;
00067         }
00068         regionThrowableSet.remove(itReg);
00069 
00070         // remove from total.
00071         SetIt itTot(totalThrowableSet.begin());
00072         if ((*itTot).excpId != excpId) {
00073                 qDebug("ASSERT in remove: %i is not the first in list", excpId);
00074                 return;
00075         }
00076         totalThrowableSet.remove(itTot);
00077 }
00078 
00079 ExceptionManager::SetIt ExceptionManager::findExcp(ThrowableSet& ts,
00080                 const SetIt& startIt, int excpId) {
00081 
00082         SetIt it(startIt);
00083         for ( ; it != ts.end(); ++it)
00084                 if ((*it).excpId == excpId)
00085                         break;
00086         return it;
00087 }
00088 
00089 void ExceptionManager::setRaisedFlag(ThrowableSet& ts, int excpId) {
00090 
00091         SetIt it(findExcp(ts, ts.begin(), excpId));
00092         while (it != ts.end()) {
00093                 (*it).isRaised = true;
00094                 it = findExcp(ts, ++it, excpId);
00095         }
00096 }
00097 
00098 void ExceptionManager::raise(int excpId) {
00099 
00100         if (totalThrowableSet.isEmpty())
00101                 return;
00102 
00103         // check totalThrowableSet to find if excpId is throwable
00104         SetIt it = findExcp(totalThrowableSet, totalThrowableSet.begin(), excpId);
00105         if (it == totalThrowableSet.end())
00106                 return;
00107 
00108         // we have found an exception. Set raised flag in regionThrowableSet
00109         setRaisedFlag(regionThrowableSet, excpId);
00110 
00111         // then set the flag in all regions throwableSetList
00112         QMap<int, ThrowableSet>::iterator itList(throwableSetMap.begin());
00113         while (itList != throwableSetMap.end()) {
00114                 setRaisedFlag(*itList, excpId);
00115                 ++itList;
00116         }
00117 }
00118 
00119 int ExceptionManager::saveThrowableSet() {
00120 // here we save regionThrowableSet _and_ update the region.
00121 // regionThrowableSet is saved with the current region index.
00122 // then current region is changed to a new and never used index
00123 
00124         int oldCurrentRegionId = currentRegionId;
00125         throwableSetMap.insert(currentRegionId, regionThrowableSet);
00126         currentRegionId = ++regionId;
00127 
00128         // we use this call to trigger a region boundary crossing
00129         // so we have to clear the new region throwables. We still
00130         // have totalThrowableSet to catch any request.
00131         regionThrowableSet.clear();
00132 
00133         return oldCurrentRegionId;
00134 }
00135 
00136 void ExceptionManager::restoreThrowableSet(int regionId) {
00137 
00138         if (!throwableSetMap.contains(regionId)) {
00139                 qDebug("ASSERT in restoreThrowableSet: region %i not found", regionId);
00140                 return;
00141         }
00142         regionThrowableSet = throwableSetMap[regionId];
00143         throwableSetMap.remove(regionId);
00144 }
00145 
00146 bool ExceptionManager::isPending(int excpId) {
00147 
00148         // check in ALL regions if an exception request is pending
00149         QMap<int, ThrowableSet>::const_iterator itList(throwableSetMap.constBegin());
00150         while (itList != throwableSetMap.constEnd()) {
00151 
00152                 ThrowableSet::const_iterator it((*itList).constBegin());
00153                 for ( ; it != (*itList).constEnd(); ++it)
00154                         if ((*it).isRaised && (*it).excpId == excpId)
00155                                 return true;
00156                 ++itList;
00157         }
00158         return false;
00159 }
00160 
00161 void ExceptionManager::throwPending() {
00162 
00163         if (regionThrowableSet.isEmpty())
00164                 return;
00165 
00166         ThrowableSet::const_iterator it(regionThrowableSet.constBegin());
00167         for ( ; it != regionThrowableSet.constEnd(); ++it)
00168                 if ((*it).isRaised)
00169                         break;
00170 
00171         if (it == regionThrowableSet.constEnd())
00172                 return;
00173 
00174         int excpToThrow = (*it).excpId;
00175         if ((*it).verbose)
00176                 qDebug("Thrown exception \'%s\'", desc(excpToThrow).latin1());
00177 
00178         throw excpToThrow;
00179 }

Generated on Fri Dec 7 21:57:37 2007 for QGit by  doxygen 1.5.3