1 |
//
|
2 |
// $Id: TAMOutput.cxx,v 1.1 2008/05/27 19:13:21 loizides Exp $
|
3 |
//
|
4 |
|
5 |
#include "TAMOutput.h"
|
6 |
|
7 |
|
8 |
#ifndef G__API_H
|
9 |
#include "Api.h"
|
10 |
#endif
|
11 |
#ifndef ROOT_Riostream
|
12 |
#include "Riostream.h"
|
13 |
#endif
|
14 |
#ifndef ROOT_RVersion
|
15 |
#include "RVersion.h"
|
16 |
#endif
|
17 |
#ifndef ROOT_TIterator
|
18 |
#include "TIterator.h"
|
19 |
#endif
|
20 |
#ifndef ROOT_TObjArray
|
21 |
#include "TObjArray.h"
|
22 |
#endif
|
23 |
#ifndef ROOT_TError
|
24 |
#include "TError.h"
|
25 |
#endif
|
26 |
#ifndef ROOT_TH1
|
27 |
#include "TH1.h"
|
28 |
#endif
|
29 |
#ifndef ROOT_TROOT
|
30 |
#include "TROOT.h"
|
31 |
#endif
|
32 |
#ifndef ROOT_TDataMember
|
33 |
#include "TDataMember.h"
|
34 |
#endif
|
35 |
#ifndef TAM_TAModule
|
36 |
#include "TAModule.h"
|
37 |
#endif
|
38 |
|
39 |
|
40 |
//////////////////////////////////////////////////////////////////////////
|
41 |
// //
|
42 |
// TAMOutput //
|
43 |
// //
|
44 |
// Stores the output objects of a module for use with the Proof //
|
45 |
// facility. This object is itself a list of all sub modules output //
|
46 |
// objects, so that whatever TAModule hierarchy exists is duplicated in //
|
47 |
// the TAMOutput hierarchy. Thus, only the tree of TAMOutput objects //
|
48 |
// needs to be streamed in to the master from the worker computers when //
|
49 |
// merging output objects in a Proof analsys, and not the complete //
|
50 |
// TAModule objects themselves. This is useful since an TAModule object //
|
51 |
// is in principal arbitrarily large, and only the list of output //
|
52 |
// objects needs to be merged. //
|
53 |
// //
|
54 |
// This class provides the functionality to merge the list of output //
|
55 |
// objects correctly throughout the hierarchy of TAMOutput objects. //
|
56 |
// //
|
57 |
// The existence of this class is hidden to classes inheritting from //
|
58 |
// TAModule. Such end-user modules need only add the desired output //
|
59 |
// objects (such as histograms) to their output list by calling //
|
60 |
// TAModule::AddOutput(TObject*&). //
|
61 |
// //
|
62 |
// Author : Corey Reed 07/20/2004 //
|
63 |
// //
|
64 |
//////////////////////////////////////////////////////////////////////////
|
65 |
|
66 |
ClassImp(TAMOutput)
|
67 |
ClassImp(TAMOutput::TAMModInspector)
|
68 |
ClassImp(TAMOutput::TAMModInspector::TAMModMember)
|
69 |
|
70 |
|
71 |
#if ROOT_VERSION_CODE < ROOT_VERSION(5,11,3)
|
72 |
#define R__ASSERT(e) \
|
73 |
if (!(e)) Fatal("", kAssertMsg, _QUOTE_(e), __LINE__, __FILE__)
|
74 |
#endif
|
75 |
|
76 |
|
77 |
//______________________________________________________________________________
|
78 |
TAMOutput::TAMModInspector::TAMModInspector() :
|
79 |
fOutputMembers(TCollection::kInitHashTableCapacity, 1)
|
80 |
{
|
81 |
// Default constructor.
|
82 |
|
83 |
fOutputMembers.SetOwner(kTRUE);
|
84 |
}
|
85 |
|
86 |
|
87 |
//______________________________________________________________________________
|
88 |
TAMOutput::TAMModInspector::~TAMModInspector()
|
89 |
{
|
90 |
// Destructor.
|
91 |
}
|
92 |
|
93 |
|
94 |
//______________________________________________________________________________
|
95 |
void TAMOutput::TAMModInspector::AddOutput(TObject* obj, const void* adr)
|
96 |
{
|
97 |
// Set the title of the TAMModMember for this object to the name of the obj.
|
98 |
|
99 |
TAMModMember* mem = FindModMemberWithAddr(adr);
|
100 |
if (mem!=0) {
|
101 |
mem->SetName(obj->GetName());
|
102 |
} // else output object is not (pointed to by) a member of the module
|
103 |
}
|
104 |
|
105 |
|
106 |
//______________________________________________________________________________
|
107 |
void TAMOutput::TAMModInspector::Inspect(TClass* cl, const Char_t* parent,
|
108 |
const Char_t* name, const void* addr)
|
109 |
{
|
110 |
// Set the address of the mod member to addr.
|
111 |
// If no mod member yet exists for this member, make it (but with no name).
|
112 |
|
113 |
if (cl->InheritsFrom(TAModule::Class())) {
|
114 |
TAMModMember* mem = FindModMemberWithMemberName(name);
|
115 |
if (mem==0) {
|
116 |
if ( (cl!=0) && (name!=0) && (addr!=0) ) {
|
117 |
TString fullname(parent);
|
118 |
fullname.Append(name);
|
119 |
fOutputMembers.Add(new TAMModMember(0, fullname.Data(),
|
120 |
const_cast<void*>(addr), cl));
|
121 |
} else {
|
122 |
::Error("TAMOutput::TAMModInspector::Inspect",
|
123 |
"Can not store TAMModMember with class at %p, "
|
124 |
"name=%s, addr=%p",
|
125 |
static_cast<void*>(cl),
|
126 |
name, static_cast<const void*>(addr));
|
127 |
}
|
128 |
} else {
|
129 |
mem->fAddr = const_cast<void*>(addr);
|
130 |
}
|
131 |
} // else don't bother; it can't point to an output object
|
132 |
}
|
133 |
|
134 |
|
135 |
//______________________________________________________________________________
|
136 |
void TAMOutput::TAMModInspector::RemoveOutput(TObject* obj)
|
137 |
{
|
138 |
// Remove the TAMModMember for this object.
|
139 |
|
140 |
TAMModMember* mem = dynamic_cast<TAMModMember*>(
|
141 |
fOutputMembers.FindObject(obj->GetName()));
|
142 |
if (mem!=0) {
|
143 |
fOutputMembers.Remove(mem);
|
144 |
}
|
145 |
}
|
146 |
|
147 |
|
148 |
//______________________________________________________________________________
|
149 |
TAMOutput::TAMModInspector::TAMModMember*
|
150 |
TAMOutput::TAMModInspector::FindModMemberWithAddr(const void* addr)
|
151 |
{
|
152 |
// Find the mod member that has the specified address
|
153 |
|
154 |
TIter nextmem(fOutputMembers.MakeIterator());
|
155 |
TAMModMember* mem=0;
|
156 |
while ( (mem = dynamic_cast<TAMModMember*>(nextmem())) ) {
|
157 |
if (mem->fAddr == addr) return mem;
|
158 |
}
|
159 |
return 0;
|
160 |
}
|
161 |
|
162 |
|
163 |
//______________________________________________________________________________
|
164 |
TAMOutput::TAMModInspector::TAMModMember*
|
165 |
TAMOutput::TAMModInspector::FindModMemberWithMemberName(const Char_t* mn)
|
166 |
{
|
167 |
// Find the mod member that has the specified member name.
|
168 |
|
169 |
TIter nextmem(fOutputMembers.MakeIterator());
|
170 |
TString memname(mn);
|
171 |
TAMModMember* mem=0;
|
172 |
while ( (mem = dynamic_cast<TAMModMember*>(nextmem())) ) {
|
173 |
if (memname.CompareTo(mem->GetTitle())==0) return mem;
|
174 |
}
|
175 |
return 0;
|
176 |
}
|
177 |
|
178 |
|
179 |
//______________________________________________________________________________
|
180 |
void TAMOutput::TAMModInspector::SetMemberAddrFor(TObject* obj,
|
181 |
const UInt_t verbose)
|
182 |
{
|
183 |
// Find the specified module's member for the specified object
|
184 |
// and make the member point to the specified object.
|
185 |
// If the member is not a pointer, does nothing.
|
186 |
|
187 |
if (obj!=0) {
|
188 |
TAMModMember* mem = dynamic_cast<TAMModMember*>(
|
189 |
fOutputMembers.FindObject(obj->GetName()));
|
190 |
if (mem!=0) {
|
191 |
// it's silly, but mem->fMClass comes from IsA(), which does
|
192 |
// not "load" the class, so the data member list is empty.
|
193 |
TClass* cl = TClass::GetClass(mem->fMClass->GetName());
|
194 |
if (cl!=0) {
|
195 |
// test if the module's member is actually a pointer to a class
|
196 |
// (as opposed to an array of pointers,
|
197 |
// an instance of the class, etc.)
|
198 |
TDataMember* dm = cl->GetDataMember(mem->GetTitle());
|
199 |
if (dm!=0) {
|
200 |
TString memberString(dm->GetTypeName());
|
201 |
memberString += "*";
|
202 |
if (memberString.CompareTo(dm->GetFullTypeName())==0) {
|
203 |
void*& modobj = *(static_cast<void**>(mem->fAddr));
|
204 |
if (modobj!=obj) {
|
205 |
if (modobj!=0) {
|
206 |
::Warning("TAMOutput::TAMModInspector::"
|
207 |
"SetMemberAddrFor",
|
208 |
"Module pointer [%s] is pointing to "
|
209 |
"non-zero address "
|
210 |
"%p. Setting it to point to "
|
211 |
"output object [%s] at %p. "
|
212 |
"Possible memory leak/stomp.",
|
213 |
mem->GetTitle(),
|
214 |
static_cast<void*>(modobj),
|
215 |
obj->GetName(),
|
216 |
static_cast<void*>(obj));
|
217 |
}
|
218 |
modobj = obj;
|
219 |
} // else it's already pointing to the right place
|
220 |
} else {
|
221 |
// not a pointer to a class
|
222 |
if (verbose>9) {
|
223 |
::Warning("TAMOutput::TAMModInspector::"
|
224 |
"SetMemberAddrFor",
|
225 |
"Module member [%s] is of type "
|
226 |
"[%s], not a pointer "
|
227 |
"to a class (inheriting from TObject). "
|
228 |
"Could not "
|
229 |
"automatically make this member "
|
230 |
"point to [%s] "
|
231 |
"from the output list.\n"
|
232 |
"Set verbosity below 10 to "
|
233 |
"remove this message.",
|
234 |
mem->GetTitle(), dm->GetFullTypeName(),
|
235 |
obj->GetName());
|
236 |
}
|
237 |
}
|
238 |
} else {
|
239 |
::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
|
240 |
"Could not get data member (%p) [%s] of module [%s]. "
|
241 |
"Could not set member address for object [%s].",
|
242 |
static_cast<void*>(dm),
|
243 |
mem->GetTitle(), mem->fMClass->GetName(),
|
244 |
obj->GetName());
|
245 |
}
|
246 |
} else {
|
247 |
::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
|
248 |
"No class info for the module. "
|
249 |
"Can not set member address for [%s].",
|
250 |
obj->GetName());
|
251 |
}
|
252 |
} // else output object is not (pointed to by) a member of the module
|
253 |
} else {
|
254 |
::Error("TAMOutput::TAMModInspector::SetMemberAddrFor",
|
255 |
"Can not set member address for null object.");
|
256 |
}
|
257 |
}
|
258 |
|
259 |
|
260 |
//______________________________________________________________________________
|
261 |
void TAMOutput::TAMModInspector::Streamer(TBuffer &R__b)
|
262 |
{
|
263 |
// Stream an object of class TAMOutput::TAMModInspector.
|
264 |
|
265 |
//This works around a msvc bug and should be harmless on other platforms
|
266 |
typedef TAMOutput::TAMModInspector thisClass;
|
267 |
UInt_t R__s, R__c;
|
268 |
if (R__b.IsReading()) {
|
269 |
Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
|
270 |
fOutputMembers.Streamer(R__b);
|
271 |
R__b.CheckByteCount(R__s, R__c, thisClass::IsA());
|
272 |
} else {
|
273 |
R__c = R__b.WriteVersion(thisClass::IsA(), kTRUE);
|
274 |
fOutputMembers.Streamer(R__b);
|
275 |
R__b.SetByteCount(R__c, kTRUE);
|
276 |
}
|
277 |
}
|
278 |
|
279 |
|
280 |
//______________________________________________________________________________
|
281 |
TAMOutput::TAMOutput() :
|
282 |
fMod(0)
|
283 |
{
|
284 |
// Default constructor.
|
285 |
|
286 |
SetOwner(kTRUE);
|
287 |
fOutput.SetOwner(kFALSE);
|
288 |
}
|
289 |
|
290 |
|
291 |
//______________________________________________________________________________
|
292 |
TAMOutput::TAMOutput(TAModule* mod) :
|
293 |
fMod(mod)
|
294 |
{
|
295 |
// Normal constructor.
|
296 |
|
297 |
SetOwner(kTRUE);
|
298 |
fOutput.SetOwner(kFALSE);
|
299 |
fCurOutput.SetOwner(kFALSE);
|
300 |
if (mod!=0) SetName(mod->GetName());
|
301 |
}
|
302 |
|
303 |
|
304 |
//______________________________________________________________________________
|
305 |
TAMOutput::~TAMOutput()
|
306 |
{
|
307 |
// Destructor.
|
308 |
}
|
309 |
|
310 |
|
311 |
//______________________________________________________________________________
|
312 |
void TAMOutput::Browse(TBrowser* b)
|
313 |
{
|
314 |
// Browse the output of this module
|
315 |
|
316 |
fOutput.Browse(b);
|
317 |
TList::Browse(b);
|
318 |
}
|
319 |
|
320 |
|
321 |
//______________________________________________________________________________
|
322 |
void TAMOutput::CallMerge(TObject* obj, TList& list)
|
323 |
{
|
324 |
// Uses CINT to call merge on 'obj' given a list of all the
|
325 |
// objects from the worker computers that correspond to 'obj'.
|
326 |
// If no merge function exists for 'obj', it simply adds all the
|
327 |
// objects in list to the output list of this module.
|
328 |
// To be called only by MergeOutput(TCollection*)
|
329 |
|
330 |
R__ASSERT(obj);
|
331 |
|
332 |
Long_t offset=0;
|
333 |
G__ClassInfo ci(obj->ClassName());
|
334 |
G__CallFunc cf;
|
335 |
|
336 |
if (ci.IsValid()) {
|
337 |
cf.SetFuncProto(&ci, "Merge", "TCollection*", &offset);
|
338 |
}
|
339 |
if (cf.IsValid()) {
|
340 |
cf.SetArg((Long_t)&list);
|
341 |
cf.Exec(obj);
|
342 |
} else {
|
343 |
// No Merge interface, return individual objects
|
344 |
TObject* obj=0;
|
345 |
while ( (obj = list.First()) ) {
|
346 |
fCurOutput.Add(obj);
|
347 |
list.Remove(obj);
|
348 |
}
|
349 |
}
|
350 |
}
|
351 |
|
352 |
|
353 |
//______________________________________________________________________________
|
354 |
void TAMOutput::CheckHistDir(TObject* obj)
|
355 |
{
|
356 |
// If obj is a histogram, set directory to null.
|
357 |
|
358 |
if (obj->InheritsFrom(TH1::Class())) {
|
359 |
TH1* hist = dynamic_cast<TH1*>(obj);
|
360 |
if (hist!=0) hist->SetDirectory(0);
|
361 |
}
|
362 |
}
|
363 |
|
364 |
|
365 |
//______________________________________________________________________________
|
366 |
void TAMOutput::DeleteIterators(vector<TIterator*>& iters) {
|
367 |
// Deletes each iterator in the vector.
|
368 |
|
369 |
vector<TIterator*>::const_iterator send = iters.end();
|
370 |
for (vector<TIterator*>::iterator siter = iters.begin();
|
371 |
siter!=send; siter++) {
|
372 |
delete (*siter);
|
373 |
}
|
374 |
}
|
375 |
|
376 |
|
377 |
//______________________________________________________________________________
|
378 |
TAMOutput* TAMOutput::FindModOutput(const TAModule* mod)
|
379 |
{
|
380 |
// Finds the TAMOutput object associated with the specified TAModule
|
381 |
// (either being this one, or one of its sub modules).
|
382 |
// Returns 0 if no such TAMOutput object is found.
|
383 |
|
384 |
if (fMod==mod) {
|
385 |
return this;
|
386 |
} else {
|
387 |
TIter nextModOutput(MakeIterator());
|
388 |
TAMOutput* out=0, * tout=0;
|
389 |
while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
|
390 |
tout = out->FindModOutput(mod);
|
391 |
if (tout!=0) return tout;
|
392 |
}
|
393 |
}
|
394 |
return 0;
|
395 |
}
|
396 |
|
397 |
|
398 |
//______________________________________________________________________________
|
399 |
TAMOutput* TAMOutput::FindModOutput(const Char_t* name)
|
400 |
{
|
401 |
// Finds the (first) TAMOutput object with the specified name
|
402 |
// (either being this one, or one of its sub modules)
|
403 |
// Returns 0 if no such TAMOutput object is found.
|
404 |
TString nm(name);
|
405 |
if (nm.CompareTo(GetName())==0) {
|
406 |
return this;
|
407 |
} else {
|
408 |
TIter nextModOutput(MakeIterator());
|
409 |
TAMOutput* out=0, * tout=0;
|
410 |
while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
|
411 |
tout = out->FindModOutput(name);
|
412 |
if (tout!=0) return tout;
|
413 |
}
|
414 |
}
|
415 |
return 0;
|
416 |
}
|
417 |
|
418 |
|
419 |
//______________________________________________________________________________
|
420 |
TObject* TAMOutput::FindOutput(const Char_t* obj)
|
421 |
{
|
422 |
// Finds the object with the specified name in the list of output objects
|
423 |
// of this module.
|
424 |
// First check the saved output, then check the output for this current
|
425 |
// processing.
|
426 |
|
427 |
TObject* fobj = fOutput.FindObject(obj);
|
428 |
if (fobj==0) {
|
429 |
fobj = fCurOutput.FindObject(obj);
|
430 |
}
|
431 |
return fobj;
|
432 |
}
|
433 |
|
434 |
|
435 |
//______________________________________________________________________________
|
436 |
TObject* TAMOutput::FindOutput(const TObject* obj)
|
437 |
{
|
438 |
// Finds the specified object in the list of output objects of this module.
|
439 |
// First check the saved output, then check the output for this current
|
440 |
// processing.
|
441 |
|
442 |
TObject* fobj = fOutput.FindObject(obj);
|
443 |
if (fobj==0) {
|
444 |
fobj = fCurOutput.FindObject(obj);
|
445 |
}
|
446 |
return fobj;
|
447 |
|
448 |
}
|
449 |
|
450 |
|
451 |
//______________________________________________________________________________
|
452 |
TObject* TAMOutput::FindOutput(const Char_t* module, const Char_t* obj) {
|
453 |
// Finds the specified object from the output of the specified module
|
454 |
// Note: "module" must be either this module, or a submodule of this module
|
455 |
// First check the saved output, then check the output for this current
|
456 |
// processing.
|
457 |
|
458 |
TAMOutput* outmod = FindModOutput(module);
|
459 |
if (outmod!=0) {
|
460 |
TObject* outp = outmod->FindOutput(obj);
|
461 |
if (outp==0) {
|
462 |
Warning("FindOutput",
|
463 |
"Could not find output named [%s] in module [%s].",
|
464 |
obj, outmod->GetName());
|
465 |
}
|
466 |
return outp;
|
467 |
} else {
|
468 |
Warning("FindOutput","Could not find (sub)module with name [%s].",
|
469 |
module);
|
470 |
}
|
471 |
return 0;
|
472 |
}
|
473 |
|
474 |
|
475 |
//______________________________________________________________________________
|
476 |
void TAMOutput::ls(Option_t* option) const
|
477 |
{
|
478 |
// List the output objects inside this module and its submodules.
|
479 |
|
480 |
TROOT::IndentLevel();
|
481 |
cout << "Output of " << GetName() << ":" << endl;
|
482 |
|
483 |
fOutput.ls(option);
|
484 |
|
485 |
TROOT::IncreaseDirLevel();
|
486 |
TList::ls(option);
|
487 |
TROOT::DecreaseDirLevel();
|
488 |
}
|
489 |
|
490 |
|
491 |
//______________________________________________________________________________
|
492 |
void TAMOutput::Merge(TCollection* list)
|
493 |
{
|
494 |
// Called by Proof after SlaveTerminate() and before Terminate()
|
495 |
// to merge the output objects from each worker ("slave") computer.
|
496 |
// First merge the actual output objects from this module, then
|
497 |
// recursively proceed through the sub modules to merge their objects.
|
498 |
|
499 |
// merge this module's output objects
|
500 |
MergeOutput(list);
|
501 |
|
502 |
// then merge its sub modules' objects:
|
503 |
if (!IsEmpty()) { // (if we have any sub modules)
|
504 |
TAMOutput* out=0, * tout=0;
|
505 |
// for each slave, get an iterator over sub modules
|
506 |
// can't use any TCollection since TIterators are not TObjects
|
507 |
vector<TIterator*> slaveIters;
|
508 |
TIter nextSlave(list);
|
509 |
while ( (tout = dynamic_cast<TAMOutput*>(nextSlave())) ) {
|
510 |
slaveIters.push_back(tout->MakeIterator());
|
511 |
}
|
512 |
|
513 |
// loop over sub modules
|
514 |
TIter nextModOutput(MakeIterator());
|
515 |
while ( (out = dynamic_cast<TAMOutput*>(nextModOutput())) ) {
|
516 |
// make a list of sub modules from each slave
|
517 |
TObjArray subList(list->GetSize());
|
518 |
|
519 |
vector<TIterator*>::const_iterator send = slaveIters.end();
|
520 |
for (vector<TIterator*>::iterator siter = slaveIters.begin();
|
521 |
siter!=send; siter++) {
|
522 |
// add the object corresponding to 'out' from each slave
|
523 |
subList.Add((*siter)->Next());
|
524 |
}
|
525 |
// merge the list of sub modules
|
526 |
out->Merge(&subList);
|
527 |
}
|
528 |
|
529 |
// cleanup
|
530 |
DeleteIterators(slaveIters);
|
531 |
}
|
532 |
|
533 |
}
|
534 |
|
535 |
|
536 |
//______________________________________________________________________________
|
537 |
void TAMOutput::MergeOutput(TCollection* list)
|
538 |
{
|
539 |
// Merges the actual output objects in fCurOutput given a list of
|
540 |
// all the TAMOutput objects from the worker computers that
|
541 |
// correspond to this one.
|
542 |
// To be called only by Merge(TCollection*)
|
543 |
|
544 |
if (!(fCurOutput.IsEmpty())) { // (if there are any output objects)
|
545 |
TAMOutput* tout=0;
|
546 |
// for each slave, get an iterator over the fCurOutput list
|
547 |
// can't use any TCollection since TIterators are not TObjects
|
548 |
vector<TIterator*> slaveIters;
|
549 |
TIter nextSlave(list);
|
550 |
while ( (tout = dynamic_cast<TAMOutput*>(nextSlave())) ) {
|
551 |
slaveIters.push_back(tout->GetCurOutputList()->MakeIterator());
|
552 |
}
|
553 |
|
554 |
// loop over fCurOutput
|
555 |
TIter nextOutputObj(fCurOutput.MakeIterator());
|
556 |
TObject* outObj=0;
|
557 |
while ( (outObj = nextOutputObj()) ) {
|
558 |
// make a list of 'outObj' from each slave
|
559 |
TList objsToMerge;
|
560 |
|
561 |
vector<TIterator*>::const_iterator send = slaveIters.end();
|
562 |
for (vector<TIterator*>::iterator siter = slaveIters.begin();
|
563 |
siter!=send; siter++) {
|
564 |
// add the object corresponding to 'outObj' from each slave
|
565 |
objsToMerge.AddLast((*siter)->Next());
|
566 |
}
|
567 |
// merge 'outObj'
|
568 |
CallMerge(outObj, objsToMerge);
|
569 |
}
|
570 |
|
571 |
// cleanup
|
572 |
DeleteIterators(slaveIters);
|
573 |
}
|
574 |
|
575 |
}
|
576 |
|
577 |
|
578 |
//______________________________________________________________________________
|
579 |
void TAMOutput::NullClassFor(void* adr, const Char_t* tid) const
|
580 |
{
|
581 |
// Print warning that the class for the pointer sent to AddOutput() is not
|
582 |
// in the ROOT class dictionary.
|
583 |
|
584 |
Error("AddOutput",
|
585 |
"(%s): Could not get class info for object at %p with typeid %s.",
|
586 |
GetName(), adr, tid);
|
587 |
}
|
588 |
|
589 |
|
590 |
//______________________________________________________________________________
|
591 |
void TAMOutput::NullObjInAddOutput() const
|
592 |
{
|
593 |
// Print warning that a null pointer was sent to AddOutput().
|
594 |
Error("AddOutput",
|
595 |
"(%s): Can not add null object to output.", GetName());
|
596 |
}
|
597 |
|
598 |
|
599 |
//______________________________________________________________________________
|
600 |
void TAMOutput::Print(Option_t *wildcard) const
|
601 |
{
|
602 |
// Print the output objects inside this module and its submodules.
|
603 |
|
604 |
TROOT::IndentLevel();
|
605 |
cout << "Output of " << GetName() << ":" << endl;
|
606 |
|
607 |
fOutput.Print(wildcard);
|
608 |
|
609 |
TROOT::IncreaseDirLevel();
|
610 |
TList::Print(wildcard);
|
611 |
TROOT::DecreaseDirLevel();
|
612 |
}
|
613 |
|
614 |
|
615 |
//______________________________________________________________________________
|
616 |
void TAMOutput::Print(Option_t* wildcard, Option_t* option) const
|
617 |
{
|
618 |
// Print the output objects inside this module and its submodules.
|
619 |
|
620 |
#if ROOT_VERSION_CODE > ROOT_VERSION(4,0,8)
|
621 |
cout << "Output of " << GetName() << ":" << endl;
|
622 |
fOutput.Print(wildcard,option);
|
623 |
TList::Print(wildcard,option);
|
624 |
#else
|
625 |
// backward compatible
|
626 |
Warning("Print","This version of Root does not handle wildcards.");
|
627 |
Print(option);
|
628 |
#endif
|
629 |
}
|
630 |
|
631 |
|
632 |
//______________________________________________________________________________
|
633 |
void TAMOutput::RemoveOutput(TObject* obj)
|
634 |
{
|
635 |
// Removes the object from the list of output objects of this module.
|
636 |
|
637 |
fInspector.RemoveOutput(obj);
|
638 |
fOutput.Remove(obj);
|
639 |
fCurOutput.Remove(obj);
|
640 |
}
|
641 |
|
642 |
|
643 |
//______________________________________________________________________________
|
644 |
void TAMOutput::SetAllOutputMembers(const Bool_t setAddresses) {
|
645 |
// Recursively set the module's output members.
|
646 |
// If setAddresses is true, make them point to the output objects.
|
647 |
|
648 |
SetOutputMembers(setAddresses);
|
649 |
|
650 |
TIter nextout(MakeIterator());
|
651 |
TAMOutput* out=0;
|
652 |
while ( (out = dynamic_cast<TAMOutput*>(nextout())) ) {
|
653 |
out->SetAllOutputMembers(setAddresses);
|
654 |
}
|
655 |
}
|
656 |
|
657 |
|
658 |
//______________________________________________________________________________
|
659 |
void TAMOutput::SetOutputMembers(const Bool_t setAddresses)
|
660 |
{
|
661 |
// Det the module's output members.
|
662 |
// If setAddresses is true, make them point to the output objects.
|
663 |
|
664 |
R__ASSERT(fMod!=0);
|
665 |
|
666 |
// first update the addresses of the members
|
667 |
Char_t parent[kParentStrLen];
|
668 |
memset(parent, 0, kParentStrLen * sizeof(Char_t));
|
669 |
fMod->ShowMembers(fInspector, parent);
|
670 |
|
671 |
if (setAddresses) {
|
672 |
// loop through output objects and set the corresponding members
|
673 |
TIter nextout(fCurOutput.MakeIterator());
|
674 |
TObject* obj=0;
|
675 |
while ( (obj = nextout()) ) {
|
676 |
fInspector.SetMemberAddrFor(obj, fMod->GetVerbosity());
|
677 |
}
|
678 |
}
|
679 |
}
|
680 |
|
681 |
|
682 |
//______________________________________________________________________________
|
683 |
void TAMOutput::StoreAllOutputObjs()
|
684 |
{
|
685 |
// Recursively set move output objects from fCutOutput to fOutput
|
686 |
// to be called after Merge, but before Terminate.
|
687 |
// To be called only by TAModule.
|
688 |
|
689 |
StoreOutputObjs();
|
690 |
|
691 |
TIter nextout(MakeIterator());
|
692 |
TAMOutput* out=0;
|
693 |
while ( (out = dynamic_cast<TAMOutput*>(nextout())) ) {
|
694 |
out->StoreAllOutputObjs();
|
695 |
}
|
696 |
}
|
697 |
|
698 |
|
699 |
//______________________________________________________________________________
|
700 |
void TAMOutput::StoreOutputObjs()
|
701 |
{
|
702 |
// Iterate over fCurOutput and move the objects to fOutput
|
703 |
// to be called after Merge, but before Terminate.
|
704 |
// To be called only by StoreAllOutputObjs.
|
705 |
|
706 |
if (fCurOutput.IsEmpty()==kFALSE) { // (if there are any output objects)
|
707 |
// loop over fCurOutput
|
708 |
TIter nextOutputObj(fCurOutput.MakeIterator());
|
709 |
TObject* outObj=0;
|
710 |
while ( (outObj = nextOutputObj()) ) {
|
711 |
fOutput.Add(outObj);
|
712 |
}
|
713 |
fCurOutput.Clear("nodelete");
|
714 |
}
|
715 |
}
|
716 |
|
717 |
|
718 |
//______________________________________________________________________________
|
719 |
void TAMOutput::WarnNameDuplicate(const TObject* obj) const
|
720 |
{
|
721 |
// Print warning that the output list already contains an object with
|
722 |
// the same name.
|
723 |
|
724 |
Warning("AddOutput",
|
725 |
"(%s): Output list already contains object with name [%s]. "
|
726 |
"Adding object at %p with duplicate name.",
|
727 |
GetName(),
|
728 |
(obj!=0) ? obj->GetName() : "",
|
729 |
static_cast<const void*>(obj));
|
730 |
}
|
731 |
|
732 |
|
733 |
#if ROOT_VERSION_CODE > ROOT_VERSION(4,0,8)
|
734 |
//______________________________________________________________________________
|
735 |
Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize)
|
736 |
{
|
737 |
// For this (newer) root version, put the code in the const function.
|
738 |
// Wow this is ugly.. but it's backward compatible!
|
739 |
|
740 |
return (static_cast<const TAMOutput*>(this))->Write(name,option,bsize);
|
741 |
}
|
742 |
|
743 |
Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize) const
|
744 |
#else
|
745 |
//______________________________________________________________________________
|
746 |
Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize) const
|
747 |
{
|
748 |
// For older root, put the code in the non-const function (so TList::Write
|
749 |
// can be called).
|
750 |
// Wow this is ugly.. but it's backward compatible!
|
751 |
|
752 |
return (const_cast<TAMOutput*>(this))->Write(name,option,bsize);
|
753 |
}
|
754 |
|
755 |
//______________________________________________________________________________
|
756 |
Int_t TAMOutput::Write(const char* name, Int_t option, Int_t bsize)
|
757 |
#endif
|
758 |
{
|
759 |
// Write all output objects.
|
760 |
// Default behavior is to go through this module and all sub modules and
|
761 |
// write all the output objects, flattening the module hierarchy.
|
762 |
// If the 'TObject::kSingleKey' option is specified, the TAMOutput
|
763 |
// objects themselves will be written, thus preserving the module hierarchy.
|
764 |
|
765 |
if ( (option & TObject::kSingleKey) ) {
|
766 |
// here, the TList write will work just fine since it will actually
|
767 |
// call the streamer on the module output objects
|
768 |
// (through TObject::Write)
|
769 |
return TList::Write(name, option, bsize);
|
770 |
} else {
|
771 |
// flatten the module hierarchy and dump all output objects to the file
|
772 |
Int_t nbytes = 0;
|
773 |
fOutput.Write(name, option, bsize);
|
774 |
TIter nextMod(MakeIterator());
|
775 |
TObject* obj=0;
|
776 |
while ( (obj = nextMod()) ) {
|
777 |
nbytes += obj->Write(name, option, bsize);
|
778 |
}
|
779 |
return nbytes;
|
780 |
}
|
781 |
}
|
782 |
|