00001 // @(#)root/base:$Id: TObject.cxx 36061 2010-10-04 16:05:51Z pcanal $ 00002 // Author: Rene Brun 26/12/94 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // // 00014 // TObject // 00015 // // 00016 // Mother of all ROOT objects. // 00017 // // 00018 // The TObject class provides default behaviour and protocol for all // 00019 // objects in the ROOT system. It provides protocol for object I/O, // 00020 // error handling, sorting, inspection, printing, drawing, etc. // 00021 // Every object which inherits from TObject can be stored in the // 00022 // ROOT collection classes. // 00023 // TObject's bits can be used as flags, bits 0 - 13 and 24-31 are // 00024 // reserved as global bits while bits 14 - 23 can be used in different // 00025 // class hierarchies (watch out for overlaps). // 00026 // // 00027 ////////////////////////////////////////////////////////////////////////// 00028 00029 #include <string.h> 00030 #if !defined(WIN32) && !defined(__MWERKS__) && !defined(R__SOLARIS) 00031 #include <strings.h> 00032 #endif 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 00036 #include "Varargs.h" 00037 #include "Riostream.h" 00038 #include "TObject.h" 00039 #include "TClass.h" 00040 #include "TGuiFactory.h" 00041 #include "TMethod.h" 00042 #include "TROOT.h" 00043 #include "TError.h" 00044 #include "TObjectTable.h" 00045 #include "TVirtualPad.h" 00046 #include "TInterpreter.h" 00047 #include "TMemberInspector.h" 00048 #include "TObjString.h" 00049 #include "TRefTable.h" 00050 #include "TProcessID.h" 00051 00052 class TDumpMembers : public TMemberInspector { 00053 // Implemented in TClass.cxx 00054 public: 00055 TDumpMembers() { } 00056 void Inspect(TClass *cl, const char *parent, const char *name, const void *addr); 00057 }; 00058 00059 Long_t TObject::fgDtorOnly = 0; 00060 Bool_t TObject::fgObjectStat = kTRUE; 00061 00062 ClassImp(TObject) 00063 00064 //______________________________________________________________________________ 00065 TObject::TObject() : fUniqueID(0), fBits(kNotDeleted) 00066 { 00067 // TObject constructor. It sets the two data words of TObject to their 00068 // initial values. The unique ID is set to 0 and the status word is 00069 // set depending if the object is created on the stack or allocated 00070 // on the heap. Depending on the ROOT environment variable "Root.MemStat" 00071 // (see TEnv) the object is added to the global TObjectTable for 00072 // bookkeeping. 00073 00074 if (TStorage::IsOnHeap(this)) 00075 fBits |= kIsOnHeap; 00076 00077 if (fgObjectStat) TObjectTable::AddObj(this); 00078 } 00079 00080 //______________________________________________________________________________ 00081 TObject::TObject(const TObject &obj) 00082 { 00083 // TObject copy ctor. 00084 00085 fUniqueID = obj.fUniqueID; // when really unique don't copy 00086 fBits = obj.fBits; 00087 00088 if (TStorage::IsOnHeap(this)) 00089 fBits |= kIsOnHeap; 00090 else 00091 fBits &= ~kIsOnHeap; 00092 00093 fBits &= ~kIsReferenced; 00094 fBits &= ~kCanDelete; 00095 00096 if (fgObjectStat) TObjectTable::AddObj(this); 00097 } 00098 00099 //______________________________________________________________________________ 00100 TObject& TObject::operator=(const TObject &rhs) 00101 { 00102 // TObject assignment operator. 00103 00104 if (this != &rhs) { 00105 fUniqueID = rhs.fUniqueID; // when really unique don't copy 00106 if (IsOnHeap()) { // test uses fBits so don't move next line 00107 fBits = rhs.fBits; 00108 fBits |= kIsOnHeap; 00109 } else { 00110 fBits = rhs.fBits; 00111 fBits &= ~kIsOnHeap; 00112 } 00113 fBits &= ~kIsReferenced; 00114 fBits &= ~kCanDelete; 00115 } 00116 return *this; 00117 } 00118 00119 //______________________________________________________________________________ 00120 void TObject::Copy(TObject &obj) const 00121 { 00122 // Copy this to obj. 00123 00124 obj.fUniqueID = fUniqueID; // when really unique don't copy 00125 if (obj.IsOnHeap()) { // test uses fBits so don't move next line 00126 obj.fBits = fBits; 00127 obj.fBits |= kIsOnHeap; 00128 } else { 00129 obj.fBits = fBits; 00130 obj.fBits &= ~kIsOnHeap; 00131 } 00132 obj.fBits &= ~kIsReferenced; 00133 obj.fBits &= ~kCanDelete; 00134 } 00135 00136 //______________________________________________________________________________ 00137 TObject::~TObject() 00138 { 00139 // TObject destructor. Removes object from all canvases and object browsers 00140 // if observer bit is on and remove from the global object table. 00141 00142 // if (!TestBit(kNotDeleted)) 00143 // Fatal("~TObject", "object deleted twice"); 00144 00145 if (gROOT) { 00146 if (gROOT->MustClean()) { 00147 if (gROOT == this) return; 00148 if (TestBit(kMustCleanup)) { 00149 gROOT->GetListOfCleanups()->RecursiveRemove(this); 00150 } 00151 } 00152 } 00153 00154 fBits &= ~kNotDeleted; 00155 00156 if (fgObjectStat && gObjectTable) gObjectTable->Remove(this); 00157 } 00158 00159 //______________________________________________________________________________ 00160 void TObject::AppendPad(Option_t *option) 00161 { 00162 // Append graphics object to current pad. In case no current pad is set 00163 // yet, create a default canvas with the name "c1". 00164 00165 if (!gPad) { 00166 gROOT->MakeDefCanvas(); 00167 } 00168 if (!gPad->IsEditable()) return; 00169 SetBit(kMustCleanup); 00170 gPad->GetListOfPrimitives()->Add(this,option); 00171 gPad->Modified(kTRUE); 00172 } 00173 00174 //______________________________________________________________________________ 00175 void TObject::Browse(TBrowser *b) 00176 { 00177 // Browse object. May be overridden for another default action 00178 00179 //Inspect(); 00180 TClass::AutoBrowse(this,b); 00181 } 00182 00183 //______________________________________________________________________________ 00184 const char *TObject::ClassName() const 00185 { 00186 // Returns name of class to which the object belongs. 00187 00188 return IsA()->GetName(); 00189 } 00190 00191 //______________________________________________________________________________ 00192 TObject *TObject::Clone(const char *) const 00193 { 00194 // Make a clone of an object using the Streamer facility. 00195 // If the object derives from TNamed, this function is called 00196 // by TNamed::Clone. TNamed::Clone uses the optional argument to set 00197 // a new name to the newly created object. 00198 // 00199 // If the object class has a DirectoryAutoAdd function, it will be 00200 // called at the end of the function with the parameter gDirectory. 00201 // This usually means that the object will be appended to the current 00202 // ROOT directory. 00203 00204 if (gDirectory) return gDirectory->CloneObject(this); 00205 else return 0; 00206 } 00207 00208 //______________________________________________________________________________ 00209 Int_t TObject::Compare(const TObject *) const 00210 { 00211 // Compare abstract method. Must be overridden if a class wants to be able 00212 // to compare itself with other objects. Must return -1 if this is smaller 00213 // than obj, 0 if objects are equal and 1 if this is larger than obj. 00214 00215 AbstractMethod("Compare"); 00216 return 0; 00217 } 00218 00219 //______________________________________________________________________________ 00220 void TObject::Delete(Option_t *) 00221 { 00222 // Delete this object. Typically called as a command via the interpreter. 00223 // Normally use "delete" operator when object has been allocated on the heap. 00224 00225 if (IsOnHeap()) { 00226 // Delete object from CINT symbol table so it can not be used anymore. 00227 // CINT object are always on the heap. 00228 gInterpreter->DeleteGlobal(this); 00229 00230 delete this; 00231 } 00232 } 00233 00234 00235 //______________________________________________________________________________ 00236 Int_t TObject::DistancetoPrimitive(Int_t, Int_t) 00237 { 00238 // Computes distance from point (px,py) to the object. 00239 // This member function must be implemented for each graphics primitive. 00240 // This default function returns a big number (999999). 00241 00242 // AbstractMethod("DistancetoPrimitive"); 00243 return 999999; 00244 } 00245 00246 //______________________________________________________________________________ 00247 void TObject::Draw(Option_t *option) 00248 { 00249 // Default Draw method for all objects 00250 00251 AppendPad(option); 00252 } 00253 00254 //______________________________________________________________________________ 00255 void TObject::DrawClass() const 00256 { 00257 // Draw class inheritance tree of the class to which this object belongs. 00258 // If a class B inherits from a class A, description of B is drawn 00259 // on the right side of description of A. 00260 // Member functions overridden by B are shown in class A with a blue line 00261 // crossing-out the corresponding member function. 00262 // The following picture is the class inheritance tree of class TPaveLabel: 00263 //Begin_Html 00264 /* 00265 <img src="gif/drawclass.gif"> 00266 */ 00267 //End_Html 00268 00269 IsA()->Draw(); 00270 } 00271 00272 //______________________________________________________________________________ 00273 TObject *TObject::DrawClone(Option_t *option) const 00274 { 00275 // Draw a clone of this object in the current pad 00276 00277 TVirtualPad *pad = gROOT->GetSelectedPad(); 00278 TVirtualPad *padsav = gPad; 00279 if (pad) pad->cd(); 00280 00281 TObject *newobj = Clone(); 00282 if (!newobj) return 0; 00283 if (pad) { 00284 if (strlen(option)) pad->GetListOfPrimitives()->Add(newobj,option); 00285 else pad->GetListOfPrimitives()->Add(newobj,GetDrawOption()); 00286 pad->Modified(kTRUE); 00287 pad->Update(); 00288 if (padsav) padsav->cd(); 00289 return newobj; 00290 } 00291 if (strlen(option)) newobj->Draw(option); 00292 else newobj->Draw(GetDrawOption()); 00293 if (padsav) padsav->cd(); 00294 00295 return newobj; 00296 } 00297 00298 //______________________________________________________________________________ 00299 void TObject::Dump() const 00300 { 00301 // Dump contents of object on stdout. 00302 // Using the information in the object dictionary (class TClass) 00303 // each data member is interpreted. 00304 // If a data member is a pointer, the pointer value is printed 00305 // 00306 // The following output is the Dump of a TArrow object: 00307 // fAngle 0 Arrow opening angle (degrees) 00308 // fArrowSize 0.2 Arrow Size 00309 // fOption.*fData 00310 // fX1 0.1 X of 1st point 00311 // fY1 0.15 Y of 1st point 00312 // fX2 0.67 X of 2nd point 00313 // fY2 0.83 Y of 2nd point 00314 // fUniqueID 0 object unique identifier 00315 // fBits 50331648 bit field status word 00316 // fLineColor 1 line color 00317 // fLineStyle 1 line style 00318 // fLineWidth 1 line width 00319 // fFillColor 19 fill area color 00320 // fFillStyle 1001 fill area style 00321 00322 if (sizeof(this) == 4) 00323 Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",(Long_t)this,GetName(),ClassName()); 00324 else 00325 Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",(Long_t)this,GetName(),ClassName()); 00326 00327 TDumpMembers dm; 00328 ((TObject*)this)->ShowMembers(dm); 00329 } 00330 00331 //______________________________________________________________________________ 00332 void TObject::Execute(const char *method, const char *params, Int_t *error) 00333 { 00334 // Execute method on this object with the given parameter string, e.g. 00335 // "3.14,1,\"text\"". 00336 00337 if (!IsA()) return; 00338 00339 Bool_t must_cleanup = TestBit(kMustCleanup); 00340 00341 gInterpreter->Execute(this, IsA(), method, params, error); 00342 00343 if (gPad && must_cleanup) gPad->Modified(); 00344 } 00345 00346 //______________________________________________________________________________ 00347 void TObject::Execute(TMethod *method, TObjArray *params, Int_t *error) 00348 { 00349 // Execute method on this object with parameters stored in the TObjArray. 00350 // The TObjArray should contain an argv vector like: 00351 // 00352 // argv[0] ... argv[n] = the list of TObjString parameters 00353 00354 if (!IsA()) return; 00355 00356 Bool_t must_cleanup = TestBit(kMustCleanup); 00357 00358 gInterpreter->Execute(this, IsA(), method, params, error); 00359 00360 if (gPad && must_cleanup) gPad->Modified(); 00361 } 00362 00363 00364 //______________________________________________________________________________ 00365 void TObject::ExecuteEvent(Int_t, Int_t, Int_t) 00366 { 00367 // Execute action corresponding to an event at (px,py). This method 00368 // must be overridden if an object can react to graphics events. 00369 00370 // AbstractMethod("ExecuteEvent"); 00371 } 00372 00373 //______________________________________________________________________________ 00374 TObject *TObject::FindObject(const char *) const 00375 { 00376 // Must be redefined in derived classes. 00377 // This function is typycally used with TCollections, but can also be used 00378 // to find an object by name inside this object. 00379 00380 return 0; 00381 } 00382 00383 //______________________________________________________________________________ 00384 TObject *TObject::FindObject(const TObject *) const 00385 { 00386 // Must be redefined in derived classes. 00387 // This function is typycally used with TCollections, but can also be used 00388 // to find an object inside this object. 00389 00390 return 0; 00391 } 00392 00393 //______________________________________________________________________________ 00394 Option_t *TObject::GetDrawOption() const 00395 { 00396 // Get option used by the graphics system to draw this object. 00397 // Note that before calling object.GetDrawOption(), you must 00398 // have called object.Draw(..) before in the current pad. 00399 00400 if (!gPad) return ""; 00401 00402 TListIter next(gPad->GetListOfPrimitives()); 00403 TObject *obj; 00404 while ((obj = next())) { 00405 if (obj == this) return next.GetOption(); 00406 } 00407 return ""; 00408 } 00409 00410 //______________________________________________________________________________ 00411 const char *TObject::GetName() const 00412 { 00413 // Returns name of object. This default method returns the class name. 00414 // Classes that give objects a name should override this method. 00415 00416 return IsA()->GetName(); 00417 } 00418 00419 //______________________________________________________________________________ 00420 const char *TObject::GetIconName() const 00421 { 00422 // Returns mime type name of object. Used by the TBrowser (via TGMimeTypes 00423 // class). Override for class of which you would like to have different 00424 // icons for objects of the same class. 00425 00426 return 0; 00427 } 00428 00429 //______________________________________________________________________________ 00430 UInt_t TObject::GetUniqueID() const 00431 { 00432 // Return the unique object id. 00433 00434 return fUniqueID; 00435 } 00436 00437 //______________________________________________________________________________ 00438 char *TObject::GetObjectInfo(Int_t px, Int_t py) const 00439 { 00440 // Returns string containing info about the object at position (px,py). 00441 // This method is typically overridden by classes of which the objects 00442 // can report peculiarities for different positions. 00443 // Returned string will be re-used (lock in MT environment). 00444 00445 if (!gPad) return (char*)""; 00446 static char info[64]; 00447 Float_t x = gPad->AbsPixeltoX(px); 00448 Float_t y = gPad->AbsPixeltoY(py); 00449 snprintf(info,64,"x=%g, y=%g",gPad->PadtoX(x),gPad->PadtoY(y)); 00450 return info; 00451 } 00452 00453 //______________________________________________________________________________ 00454 const char *TObject::GetTitle() const 00455 { 00456 // Returns title of object. This default method returns the class title 00457 // (i.e. description). Classes that give objects a title should override 00458 // this method. 00459 00460 return IsA()->GetTitle(); 00461 } 00462 00463 00464 //______________________________________________________________________________ 00465 Bool_t TObject::HandleTimer(TTimer *) 00466 { 00467 // Execute action in response of a timer timing out. This method 00468 // must be overridden if an object has to react to timers. 00469 00470 return kFALSE; 00471 } 00472 00473 //______________________________________________________________________________ 00474 ULong_t TObject::Hash() const 00475 { 00476 // Return hash value for this object. 00477 00478 //return (ULong_t) this >> 2; 00479 const void *ptr = this; 00480 return TString::Hash(&ptr, sizeof(void*)); 00481 } 00482 00483 //______________________________________________________________________________ 00484 Bool_t TObject::InheritsFrom(const char *classname) const 00485 { 00486 // Returns kTRUE if object inherits from class "classname". 00487 00488 return IsA()->InheritsFrom(classname); 00489 } 00490 00491 //______________________________________________________________________________ 00492 Bool_t TObject::InheritsFrom(const TClass *cl) const 00493 { 00494 // Returns kTRUE if object inherits from TClass cl. 00495 00496 return IsA()->InheritsFrom(cl); 00497 } 00498 00499 //______________________________________________________________________________ 00500 void TObject::Inspect() const 00501 { 00502 // Dump contents of this object in a graphics canvas. 00503 // Same action as Dump but in a graphical form. 00504 // In addition pointers to other objects can be followed. 00505 // 00506 // The following picture is the Inspect of a histogram object: 00507 //Begin_Html 00508 /* 00509 <img src="gif/hpxinspect.gif"> 00510 */ 00511 //End_Html 00512 00513 gGuiFactory->CreateInspectorImp(this, 400, 200); 00514 } 00515 00516 //______________________________________________________________________________ 00517 Bool_t TObject::IsFolder() const 00518 { 00519 // Returns kTRUE in case object contains browsable objects (like containers 00520 // or lists of other objects). 00521 00522 return kFALSE; 00523 } 00524 00525 //______________________________________________________________________________ 00526 Bool_t TObject::IsEqual(const TObject *obj) const 00527 { 00528 // Default equal comparison (objects are equal if they have the same 00529 // address in memory). More complicated classes might want to override 00530 // this function. 00531 00532 return obj == this; 00533 } 00534 00535 //______________________________________________________________________________ 00536 void TObject::ls(Option_t *) const 00537 { 00538 // The ls function lists the contents of a class on stdout. Ls output 00539 // is typically much less verbose then Dump(). 00540 00541 TROOT::IndentLevel(); 00542 cout <<"OBJ: " << IsA()->GetName() << "\t" << GetName() << "\t" << GetTitle() << " : " 00543 << Int_t(TestBit(kCanDelete)) <<" at: "<<this<< endl; 00544 } 00545 00546 //______________________________________________________________________________ 00547 Bool_t TObject::Notify() 00548 { 00549 // This method must be overridden to handle object notifcation. 00550 00551 return kFALSE; 00552 } 00553 00554 //______________________________________________________________________________ 00555 void TObject::Paint(Option_t *) 00556 { 00557 // This method must be overridden if a class wants to paint itself. 00558 // The difference between Paint() and Draw() is that when a object 00559 // draws itself it is added to the display list of the pad in 00560 // which it is drawn (and automatically redrawn whenever the pad is 00561 // redrawn). While paint just draws the object without adding it to 00562 // the pad display list. 00563 00564 // AbstractMethod("Paint"); 00565 } 00566 00567 //______________________________________________________________________________ 00568 void TObject::Pop() 00569 { 00570 // Pop on object drawn in a pad to the top of the display list. I.e. it 00571 // will be drawn last and on top of all other primitives. 00572 00573 if (!gPad) return; 00574 00575 if (this == gPad->GetListOfPrimitives()->Last()) return; 00576 00577 TListIter next(gPad->GetListOfPrimitives()); 00578 TObject *obj; 00579 while ((obj = next())) 00580 if (obj == this) { 00581 char *opt = StrDup(next.GetOption()); 00582 gPad->GetListOfPrimitives()->Remove((TObject*)this); 00583 gPad->GetListOfPrimitives()->AddLast(this, opt); 00584 gPad->Modified(); 00585 delete [] opt; 00586 return; 00587 } 00588 } 00589 00590 //______________________________________________________________________________ 00591 void TObject::Print(Option_t *) const 00592 { 00593 // This method must be overridden when a class wants to print itself. 00594 00595 cout <<"OBJ: " << IsA()->GetName() << "\t" << GetName() << "\t" << GetTitle() << endl; 00596 } 00597 00598 //______________________________________________________________________________ 00599 Int_t TObject::Read(const char *name) 00600 { 00601 // Read contents of object with specified name from the current directory. 00602 // First the key with the given name is searched in the current directory, 00603 // next the key buffer is deserialized into the object. 00604 // The object must have been created before via the default constructor. 00605 // See TObject::Write(). 00606 00607 if (gDirectory) return gDirectory->ReadTObject(this,name); 00608 else return 0; 00609 } 00610 00611 //______________________________________________________________________________ 00612 void TObject::RecursiveRemove(TObject *) 00613 { 00614 // Recursively remove this object from a list. Typically implemented 00615 // by classes that can contain mulitple references to a same object. 00616 00617 } 00618 00619 00620 //______________________________________________________________________________ 00621 void TObject::SaveAs(const char *filename, Option_t *option) const 00622 { 00623 // Save this object in the file specified by filename. 00624 // if (filename contains ".root" the object is saved in filename (root binary file) 00625 // if (filename contains ".xml" the object is saved in filename (xml ascii file) 00626 // otherwise the object is written to filename as a CINT/C++ script. 00627 // The C++ code to rebuild this object is generated via SavePrimitive(). 00628 // The option parameter is passed to SavePrimitive. By default it is 00629 // en empty string. It can be used to specify the Draw option 00630 // in the code generated by SavePrimitive. 00631 // The function is available via the object context menu. 00632 00633 //==============Save object as a root file=============================== 00634 if (filename && strstr(filename,".root")) { 00635 if (gDirectory) gDirectory->SaveObjectAs(this,filename,""); 00636 return; 00637 } 00638 00639 //==============Save object as a XML file================================ 00640 if (filename && strstr(filename,".xml")) { 00641 if (gDirectory) gDirectory->SaveObjectAs(this,filename,""); 00642 return; 00643 } 00644 00645 //==============Save as a C++ CINT file================================ 00646 char *fname = 0; 00647 if (filename && strlen(filename) > 0) { 00648 fname = (char*)filename; 00649 } else { 00650 fname = Form("%s.C", GetName()); 00651 } 00652 ofstream out; 00653 out.open(fname, ios::out); 00654 if (!out.good ()) { 00655 Error("SaveAs", "cannot open file: %s", fname); 00656 return; 00657 } 00658 out <<"{"<<endl; 00659 out <<"//========= Macro generated from object: "<<GetName()<<"/"<<GetTitle()<<endl; 00660 out <<"//========= by ROOT version"<<gROOT->GetVersion()<<endl; 00661 ((TObject*)this)->SavePrimitive(out,option); 00662 out <<"}"<<endl; 00663 out.close(); 00664 Info("SaveAs", "C++ Macro file: %s has been generated", fname); 00665 } 00666 00667 //______________________________________________________________________________ 00668 void TObject::SavePrimitive(ostream &out, Option_t * /*= ""*/) 00669 { 00670 // Save a primitive as a C++ statement(s) on output stream "out". 00671 00672 out << "//Primitive: " << GetName() << "/" << GetTitle() 00673 <<". You must implement " << ClassName() << "::SavePrimitive" << endl; 00674 } 00675 00676 //______________________________________________________________________________ 00677 void TObject::SetDrawOption(Option_t *option) 00678 { 00679 // Set drawing option for object. This option only affects 00680 // the drawing style and is stored in the option field of the 00681 // TObjOptLink supporting a TPad's primitive list (TList). 00682 // Note that it does not make sense to call object.SetDrawOption(option) 00683 // before having called object.Draw(). 00684 00685 if (!gPad || !option) return; 00686 00687 TListIter next(gPad->GetListOfPrimitives()); 00688 delete gPad->FindObject("Tframe"); 00689 TObject *obj; 00690 while ((obj = next())) 00691 if (obj == this) { 00692 next.SetOption(option); 00693 return; 00694 } 00695 } 00696 00697 //______________________________________________________________________________ 00698 void TObject::SetBit(UInt_t f, Bool_t set) 00699 { 00700 // Set or unset the user status bits as specified in f. 00701 00702 if (set) 00703 SetBit(f); 00704 else 00705 ResetBit(f); 00706 } 00707 00708 //______________________________________________________________________________ 00709 void TObject::SetUniqueID(UInt_t uid) 00710 { 00711 // Set the unique object id. 00712 00713 fUniqueID = uid; 00714 } 00715 00716 //______________________________________________________________________________ 00717 void TObject::UseCurrentStyle() 00718 { 00719 // Set current style settings in this object 00720 // This function is called when either TCanvas::UseCurrentStyle 00721 // or TROOT::ForceStyle have been invoked. 00722 } 00723 00724 //______________________________________________________________________________ 00725 Int_t TObject::Write(const char *name, Int_t option, Int_t bufsize) const 00726 { 00727 // Write this object to the current directory. 00728 // The data structure corresponding to this object is serialized. 00729 // The corresponding buffer is written to the current directory 00730 // with an associated key with name "name". 00731 // 00732 // Writing an object to a file involves the following steps: 00733 // 00734 // -Creation of a support TKey object in the current directory. 00735 // The TKey object creates a TBuffer object. 00736 // 00737 // -The TBuffer object is filled via the class::Streamer function. 00738 // 00739 // -If the file is compressed (default) a second buffer is created to 00740 // hold the compressed buffer. 00741 // 00742 // -Reservation of the corresponding space in the file by looking 00743 // in the TFree list of free blocks of the file. 00744 // 00745 // -The buffer is written to the file. 00746 // 00747 // Bufsize can be given to force a given buffer size to write this object. 00748 // By default, the buffersize will be taken from the average buffer size 00749 // of all objects written to the current file so far. 00750 // 00751 // If a name is specified, it will be the name of the key. 00752 // If name is not given, the name of the key will be the name as returned 00753 // by GetName(). 00754 // 00755 // The option can be a combination of: 00756 // kSingleKey, kOverwrite or kWriteDelete 00757 // Using the kOverwrite option a previous key with the same name is 00758 // overwritten. The previous key is deleted before writing the new object. 00759 // Using the kWriteDelete option a previous key with the same name is 00760 // deleted only after the new object has been written. This option 00761 // is safer than kOverwrite but it is slower. 00762 // The kSingleKey option is only used by TCollection::Write() to write 00763 // a container with a single key instead of each object in the container 00764 // with its own key. 00765 // 00766 // An object is read from the file into memory via TKey::Read() or 00767 // via TObject::Read(). 00768 // 00769 // The function returns the total number of bytes written to the file. 00770 // It returns 0 if the object cannot be written. 00771 00772 TString opt = ""; 00773 if (option & kSingleKey) opt += "SingleKey"; 00774 if (option & kOverwrite) opt += "OverWrite"; 00775 if (option & kWriteDelete) opt += "WriteDelete"; 00776 00777 if (gDirectory) return gDirectory->WriteTObject(this,name,opt.Data(),bufsize); 00778 else { 00779 const char *objname = "no name specified"; 00780 if (name) objname = name; 00781 else objname = GetName(); 00782 Error("Write","The current directory (gDirectory) is null. The object (%s) has not been written.",objname); 00783 return 0; 00784 } 00785 } 00786 00787 //______________________________________________________________________________ 00788 Int_t TObject::Write(const char *name, Int_t option, Int_t bufsize) 00789 { 00790 // Write this object to the current directory. For more see the 00791 // const version of this method. 00792 00793 return ((const TObject*)this)->Write(name, option, bufsize); 00794 } 00795 00796 //______________________________________________________________________________ 00797 void TObject::Streamer(TBuffer &R__b) 00798 { 00799 // Stream an object of class TObject. 00800 00801 if (IsA()->CanIgnoreTObjectStreamer()) return; 00802 UShort_t pidf; 00803 if (R__b.IsReading()) { 00804 R__b.SkipVersion(); // Version_t R__v = R__b.ReadVersion(); if (R__v) { } 00805 R__b >> fUniqueID; 00806 R__b >> fBits; 00807 fBits |= kIsOnHeap; // by definition de-serialized object is on heap 00808 if (TestBit(kIsReferenced)) { 00809 //if the object is referenced, we must read its old address 00810 //and store it in the ProcessID map in gROOT 00811 R__b >> pidf; 00812 pidf += R__b.GetPidOffset(); 00813 TProcessID *pid = R__b.ReadProcessID(pidf); 00814 if (pid) { 00815 UInt_t gpid = pid->GetUniqueID(); 00816 if (gpid>=0xff) { 00817 fUniqueID = fUniqueID | 0xff000000; 00818 } else { 00819 fUniqueID = ( fUniqueID & 0xffffff) + (gpid<<24); 00820 } 00821 pid->PutObjectWithID(this); 00822 } 00823 } 00824 } else { 00825 R__b.WriteVersion(TObject::IsA()); 00826 if (!TestBit(kIsReferenced)) { 00827 R__b << fUniqueID; 00828 R__b << fBits; 00829 } else { 00830 //if the object is referenced, we must save its address/file_pid 00831 UInt_t uid = fUniqueID & 0xffffff; 00832 R__b << uid; 00833 R__b << fBits; 00834 TProcessID *pid = TProcessID::GetProcessWithUID(fUniqueID,this); 00835 //add uid to the TRefTable if there is one 00836 TRefTable *table = TRefTable::GetRefTable(); 00837 if(table) table->Add(uid, pid); 00838 pidf = R__b.WriteProcessID(pid); 00839 R__b << pidf; 00840 } 00841 } 00842 } 00843 00844 //______________________________________________________________________________ 00845 00846 //---- error handling ---------------------------------------------------------- 00847 00848 //______________________________________________________________________________ 00849 void TObject::DoError(int level, const char *location, const char *fmt, va_list va) const 00850 { 00851 // Interface to ErrorHandler (protected). 00852 00853 const char *classname = "UnknownClass"; 00854 if (TROOT::Initialized()) 00855 classname = ClassName(); 00856 00857 ::ErrorHandler(level, Form("%s::%s", classname, location), fmt, va); 00858 } 00859 00860 //______________________________________________________________________________ 00861 void TObject::Info(const char *location, const char *va_(fmt), ...) const 00862 { 00863 // Issue info message. Use "location" to specify the method where the 00864 // warning occured. Accepts standard printf formatting arguments. 00865 00866 va_list ap; 00867 va_start(ap, va_(fmt)); 00868 DoError(kInfo, location, va_(fmt), ap); 00869 va_end(ap); 00870 } 00871 00872 //______________________________________________________________________________ 00873 void TObject::Warning(const char *location, const char *va_(fmt), ...) const 00874 { 00875 // Issue warning message. Use "location" to specify the method where the 00876 // warning occured. Accepts standard printf formatting arguments. 00877 00878 va_list ap; 00879 va_start(ap, va_(fmt)); 00880 DoError(kWarning, location, va_(fmt), ap); 00881 va_end(ap); 00882 if (TROOT::Initialized()) 00883 gROOT->Message(1001, this); 00884 } 00885 00886 //______________________________________________________________________________ 00887 void TObject::Error(const char *location, const char *va_(fmt), ...) const 00888 { 00889 // Issue error message. Use "location" to specify the method where the 00890 // error occured. Accepts standard printf formatting arguments. 00891 00892 va_list ap; 00893 va_start(ap, va_(fmt)); 00894 DoError(kError, location, va_(fmt), ap); 00895 va_end(ap); 00896 if (TROOT::Initialized()) 00897 gROOT->Message(1002, this); 00898 } 00899 00900 //______________________________________________________________________________ 00901 void TObject::SysError(const char *location, const char *va_(fmt), ...) const 00902 { 00903 // Issue system error message. Use "location" to specify the method where 00904 // the system error occured. Accepts standard printf formatting arguments. 00905 00906 va_list ap; 00907 va_start(ap, va_(fmt)); 00908 DoError(kSysError, location, va_(fmt), ap); 00909 va_end(ap); 00910 if (TROOT::Initialized()) 00911 gROOT->Message(1003, this); 00912 } 00913 00914 //______________________________________________________________________________ 00915 void TObject::Fatal(const char *location, const char *va_(fmt), ...) const 00916 { 00917 // Issue fatal error message. Use "location" to specify the method where the 00918 // fatal error occured. Accepts standard printf formatting arguments. 00919 00920 va_list ap; 00921 va_start(ap, va_(fmt)); 00922 DoError(kFatal, location, va_(fmt), ap); 00923 va_end(ap); 00924 if (TROOT::Initialized()) 00925 gROOT->Message(1004, this); 00926 } 00927 00928 //______________________________________________________________________________ 00929 void TObject::AbstractMethod(const char *method) const 00930 { 00931 // Use this method to implement an "abstract" method that you don't 00932 // want to leave purely abstract. 00933 00934 Warning(method, "this method must be overridden!"); 00935 } 00936 00937 //______________________________________________________________________________ 00938 void TObject::MayNotUse(const char *method) const 00939 { 00940 // Use this method to signal that a method (defined in a base class) 00941 // may not be called in a derived class (in principle against good 00942 // design since a child class should not provide less functionality 00943 // than its parent, however, sometimes it is necessary). 00944 00945 Warning(method, "may not use this method"); 00946 } 00947 00948 00949 //----------------- Static data members access --------------------------------- 00950 00951 //______________________________________________________________________________ 00952 Bool_t TObject::GetObjectStat() 00953 { 00954 // Get status of object stat flag. 00955 00956 return fgObjectStat; 00957 } 00958 //______________________________________________________________________________ 00959 void TObject::SetObjectStat(Bool_t stat) 00960 { 00961 // Turn on/off tracking of objects in the TObjectTable. 00962 00963 fgObjectStat = stat; 00964 } 00965 00966 //______________________________________________________________________________ 00967 Long_t TObject::GetDtorOnly() 00968 { 00969 //return destructor only flag 00970 return fgDtorOnly; 00971 } 00972 00973 //______________________________________________________________________________ 00974 void TObject::SetDtorOnly(void *obj) 00975 { 00976 //set destructor only flag 00977 fgDtorOnly = (Long_t) obj; 00978 } 00979 00980 //______________________________________________________________________________ 00981 void TObject::operator delete(void *ptr) 00982 { 00983 //operator delete 00984 if ((Long_t) ptr != fgDtorOnly) 00985 TStorage::ObjectDealloc(ptr); 00986 else 00987 fgDtorOnly = 0; 00988 } 00989 00990 //______________________________________________________________________________ 00991 void TObject::operator delete[](void *ptr) 00992 { 00993 //operator delete [] 00994 if ((Long_t) ptr != fgDtorOnly) 00995 TStorage::ObjectDealloc(ptr); 00996 else 00997 fgDtorOnly = 0; 00998 } 00999 01000 #ifdef R__PLACEMENTDELETE 01001 //______________________________________________________________________________ 01002 void TObject::operator delete(void *ptr, void *vp) 01003 { 01004 // Only called by placement new when throwing an exception. 01005 01006 TStorage::ObjectDealloc(ptr, vp); 01007 } 01008 01009 //______________________________________________________________________________ 01010 void TObject::operator delete[](void *ptr, void *vp) 01011 { 01012 // Only called by placement new[] when throwing an exception. 01013 01014 TStorage::ObjectDealloc(ptr, vp); 01015 } 01016 #endif