ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TAM/src/TAMOutput.cxx
Revision: 1.2
Committed: Sat Sep 27 06:03:36 2008 UTC (16 years, 7 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_006, Mit_005, Mit_004
Changes since 1.1: +3 -2 lines
Log Message:
Rehash in THashTables.

File Contents

# Content
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