1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
|
Existing ZMexception mechanism:
Say ZMxA is a child of ZMxB. The coder would say:
ZMxCompleteDefinition (ZMxA, ZMxB)
ZMxInfo<ZMxB> ZMxA::information ("ZMxA", ...);
ZMxCompleteDefinition (ZMxA, ZMxB) expands to
Class ZMxA : public ZMxB {
public:
ZMxA(string mssg, ZMxSeverityLevel lever = EndOfSeverity) :
ZMxB (msg,level)
{ init (level); } ;
static ZMexceptInfo<ZMxB> information;
ZMexceptionWrappers;
virtual ZMexception* copy () {return new ZMxA(*this); };
ZMexceptionWrappers expands to a large bunch of static method declaratoins
and definitions, a few virtual trivial methods, and the nontrivial method init:
static void setHandler(const ZMhandler& newHandler) {
information.setHandler(newHandler) }
...
virtual string id() {
return information._id; };
virtual void init(ZMxSeverityLevel level) {
information._count++;
_myCount = information._count();
if (level==EndOfSeverity) {_mySeverity=information.severity;}
else {_mySeverity=level;}
}
Let's try to understand _mySeverity and _myCount:
Both are variables declared when the ZMexception class is declared;
therefore, they are individual per instance of ZMx.
Let's try to understand information._count:
In the definition of ZMxA we have an information data member, which is a
***static*** ZMexceptInfo<ZMxB>. In ZMexception.icc, the following data
members are initialized:
_id, _messagePreamble, _severity, _logger, _handler (all from args)
AND
count(0), _previousHandler(0), _previousLogger(0)
So count does start as 0.
How does push/pop work out? It doen't yet.
OK, what do we want in information?
Have
string _id
string _messagePreamble,
ZMxSL _severity
Want:
facilityNumber -- normally from parent
facilityName -- normally from parent
Mnemonic = _id
Name (should be same as class name) = _messagePreamble
severity,
number
exceptionNumber is a method returning
Severity (4bits) Facility (12 bits) Number (16 bits)
How to inherit from parent?
Obvious: In ZMexceptIfno<Parent> constructor, init to Parent::facilityName
That means a top of a facility must contain an additional line or argument
to the constructor.
Sequence when ZMthrow (ZMxA) happens
1 - ZMexcept(Except, ...)
2 - x.log()
Declared in ZMexception
Defined in Boilerplate
x.information.classLog(x)
3 - x.information.classLog(ZMexception *that)
declared in ZMexceptInfo<Parent>
defined in ZMexception.icc
if _logger==NULL (which it starts out as)
return classParentLog (that)
classParentLog would return Parent::information.classLog(*x)
Now we come to _logger->log(*x)
4 - _logger is typically ZMlSimple (which we will just call ZMlog()) in
ZMlogger.cc. The log() method there just writes to an ofstream or whatever.
5 - ZMerrno.write(x);
6 - result = x.handle();
x.handle() is declared in ZMexception
Defined in Boilerplate
7 - x.information.classHandle(ZMxA *x)
declared in ZMexceptInfo<Parent>
defined in ZMexception.icc
if _handler==NULL (which it starts out as)
return classParentHandle (that)
classParentHandle would return Parent::information.classHandle(*x)
By the way, if you run out after PArent, you go to the action zmxThrow
which is defined in ZMhandler.h as part of an enum.
Now we come to _handler->execute(*x)
8 - handler may do stuff (the supplied ones don't) and will return a ZMxAction.
9 - The interesting case is ZMxParent, because now we are back in classHandle
at the point where the parent's handler is called.
Here is the way to cope with need for identifying exceptions:
1) MURMUR (G.O.) Agreed that no need to generate cross-program murmur id number.
2) FACILITY-S-MNEMONIC is unique and meaningful.
3) Therefore, only thing necessary is for the USER DURING THE PROGRAM to be
able to ask two things:
Is this exception a ZMxWhichever?
Is this exception descended from ZMxWhichever?
4) Using type_id for the first and dynamic_cast for the second would be possible
but this is not yet here.
5) Instead we define the following methods in ZMexception:
bool isExactly (ZMxexception x)
bool isAncestorOf (ZMxexception x)
In the future these may be implemented via type_id and dynamic_cast
6) For the benefit of current implementation, the syntax we give the user is
if (ZMxA::isExactly x)
if (ZMxA::isAncestorOf x)
rather than if (x.isExactly(ZMxA)) which tries to pass a class as an
argument. This means we have an isAncestorOf method rather than a
isDescendantOf method.
7) To implement this now:
a) We define a class ZMexceptionIdentifier
int exceptionID $$$
static int maxAssigned (which we start at 0)
int nextID () {return ++exceptionID;}
b) The ZMexceptInfo<P> class contains static ZMexceptionIdentifier eid;
c) The macro for defining
c) Where we initialize ZMexceptInfo we also do
eid.exceptionID = eid.nextID();
We may have to do this by having a constructor for
ZMexceptionIdentifier or something.
d) in ZMexception we have a potentially non-virtual method
bool isExactly (ZMxexception &x)
which for now merely compares eid.exceptionID with x.eid.excptionID
and which ultimately becomes if (type_id(this) == type_id(x))
Actually, when you call something like ZMxA::isExactly(x)
can the isExactly method use this? If not, what can we
do to use type_id, if anything?
e) in ZMexception we have a virtual method
bool isAncestorOf (ZMxexception &x)
which in the top of tree exception also merely compares
eid.exceptionID with x.eid.excptionID.
f) The bool isAncestorOf (ZMxexception &x) in other exceptions (thus
in the standard definition would do:
?????????????????
bool isAncestorOf (ZMxexception x)
which at that point both
The constructor for a
$$$ Note that we really don't need facilty and
problemNumber to be distinct since we now only
check for
b) ErrorIdentifier
each
This implies that the top of a the overall tree must be different than its
descendants, particularly in how isDescendedFrom() works. We already have
the overall top different anyway.
Proposed layout of ZMexceptions in HepTuple:
General statements about exceptions:
Each ZOOM exception is an object of some class, inheriting off some ZMexception
parent (except for ZMxTop which is the anscestor of all exceptions), and has
some FaciltyName and some ExceptionName. We should also perhaps add a
Mnemonic, intended as a short string as in RMS-E-NOTFOUND for the RMS
facility issuing an E severity error because a file was not found in some
manner.
The name of the class (which should match the ExceptoinName, should generally
reflect the name of the method which threw the exeption and/or the class which
that method is part of.
- - -
It is tempting to say that Where applicable we should declare the exception
in the public area of the class whose methods might throw it; then the
name will automatically reflect that class.
For example, the ZMexception class for an exception encountered during
the accumulate() method of HepHist1D might be HepHist1D::ZMxAccumlate.
The name would then be "HepHist1D::ZMxaccumlate", and its mnemonic might be
"ACCUMULATE".
WE DO NOT DO THIS for the following reason: It is desirable that the list of
all ZMx exception types appear contiguously in a commonly seen header such as
the facility's overall .h file. Burying the exception classes inside
individual classes obscures some of the the information and accessibility we
want the user to have.
- - -
With this in mind, here is how I propose to layout exceptions thrown by
HepTuple (HepTuple exceptions):
* All HepTuple exceptions have their Facility as "HEPTUPLE" (by murmur
convention, facility names and mnemonics are upper case).
* Every HepTuple exception class is declared in HepTuple.h
* HepTuple exception classes are defined -- and their static data members
initialized -- in the .cc file corresponding to the class whose methods throw
them. If several classes throw one type of excpetion, we will define it
in the file for the class it is most closely connected with.
* There is a topmost HepTuple exception defined in HepObj.cc (in most
packages, where the name of the package does not conflict with the
name of a class, it would be in packageName.cc).
declaration is in HepTuple.h --
class ZMxHepTuple : public ZMxTop {
public:
ZMxHepTuple(.....);
virtual ZMxHeptuple* copy () {.....};
static ZMexceptInfo<ZMxTop> information;
MexceptionWrappers;
}
statics in HepObj.cc --
ZMxHeptuple::information.facility = "HEPTUPLE";
ZMxHeptuple::information.mnemonic = "HEPTUPLE";
ZMxHeptuple::information.name = "ZMxHepTuple";
ZMxHeptuple::information.severity = ZMxSeverityProblem;
Things will inherit off this, but will HepTuple routines will probably
not ZMthrow this one directly, except where "impossible" circumstances are
checked for and we don't think it worthwhile to declare a specific class.
* Other exceptions will be declared in HepTuple.h
public area in the appropriate class,
or (if thrown from a variety of classes at global scope in HepTuple.h).
We should NOT assign a unique exception class to each possible way an
exception can be throw.
One given method might throw one or maybe a couple of possible types of
exception objects. Several methods might share the ability to throw one type of
exception.
* The message going with each line of code ZMthrow-ing a HepTuple exception
should be unique, even though the same class might be thrown from many places.
|