Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TObject.h
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Rene Brun 26/12/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TObject
13 #define ROOT_TObject
14 
15 
16 #include "RConfigure.h"
17 #include "Rtypes.h"
18 #include "TStorage.h"
19 #include "TVersionCheck.h"
20 
21 #include <stdarg.h>
22 #include <string>
23 #include <iosfwd>
24 
25 #ifdef WIN32
26 #undef RemoveDirectory
27 #endif
28 
29 class TList;
30 class TBrowser;
31 class TBuffer;
32 class TObjArray;
33 class TMethod;
34 class TTimer;
35 
36 
37 class TObject {
38 
39 private:
40  UInt_t fUniqueID; ///< object unique identifier
41  UInt_t fBits; ///< bit field status word
42 
43  static Long_t fgDtorOnly; ///< object for which to call dtor only (i.e. no delete)
44  static Bool_t fgObjectStat; ///< if true keep track of objects in TObjectTable
45 
46  static void AddToTObjectTable(TObject *);
47 
48 protected:
49  void MakeZombie() { fBits |= kZombie; }
50  virtual void DoError(int level, const char *location, const char *fmt, va_list va) const;
51 
52 public:
53  //----- Global bits (can be set for any object and should not be reused).
54  //----- Bits 0 - 13 are reserved as global bits. Bits 14 - 23 can be used
55  //----- in different class hierarchies (make sure there is no overlap in
56  //----- any given hierarchy).
57  enum EStatusBits {
58  kCanDelete = BIT(0), ///< if object in a list can be deleted
59  // 2 is taken by TDataMember
60  kMustCleanup = BIT(3), ///< if object destructor must call RecursiveRemove()
61  kIsReferenced = BIT(4), ///< if object is referenced by a TRef or TRefArray
62  kHasUUID = BIT(5), ///< if object has a TUUID (its fUniqueID=UUIDNumber)
63  kCannotPick = BIT(6), ///< if object in a pad cannot be picked
64  // 7 is taken by TAxis and TClass.
65  kNoContextMenu = BIT(8), ///< if object does not want context menu
66  // 9, 10 are taken by TH1, TF1, TAxis and a few others
67  // 12 is taken by TAxis
68  kInvalidObject = BIT(13) ///< if object ctor succeeded but object should not be used
69  };
70 
71  enum EDeprecatedStatusBits {
72  kObjInCanvas = BIT(3) ///< for backward compatibility only, use kMustCleanup
73  };
74 
75  //----- Private bits, clients can only test but not change them
76  enum {
77  kIsOnHeap = 0x01000000, ///< object is on heap
78  kNotDeleted = 0x02000000, ///< object has not been deleted
79  kZombie = 0x04000000, ///< object ctor failed
80  kInconsistent = 0x08000000, ///< class overload Hash but does call RecursiveRemove in destructor
81  // kCheckedHash = 0x10000000, ///< CheckedHash has check for the consistency of Hash/RecursiveRemove
82  kBitMask = 0x00ffffff
83  };
84 
85  //----- Write() options
86  enum {
87  kSingleKey = BIT(0), ///< write collection with single key
88  kOverwrite = BIT(1), ///< overwrite existing object with same name
89  kWriteDelete = BIT(2) ///< write object, then delete previous key with same name
90  };
91 
92  TObject();
93  TObject(const TObject &object);
94  TObject &operator=(const TObject &rhs);
95  virtual ~TObject();
96 
97  virtual void AppendPad(Option_t *option="");
98  virtual void Browse(TBrowser *b);
99  virtual const char *ClassName() const;
100  virtual void Clear(Option_t * /*option*/ ="") { }
101  ULong_t CheckedHash(); // Not virtual
102  virtual TObject *Clone(const char *newname="") const;
103  virtual Int_t Compare(const TObject *obj) const;
104  virtual void Copy(TObject &object) const;
105  virtual void Delete(Option_t *option=""); // *MENU*
106  virtual Int_t DistancetoPrimitive(Int_t px, Int_t py);
107  virtual void Draw(Option_t *option="");
108  virtual void DrawClass() const; // *MENU*
109  virtual TObject *DrawClone(Option_t *option="") const; // *MENU*
110  virtual void Dump() const; // *MENU*
111  virtual void Execute(const char *method, const char *params, Int_t *error=0);
112  virtual void Execute(TMethod *method, TObjArray *params, Int_t *error=0);
113  virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py);
114  virtual TObject *FindObject(const char *name) const;
115  virtual TObject *FindObject(const TObject *obj) const;
116  virtual Option_t *GetDrawOption() const;
117  virtual UInt_t GetUniqueID() const;
118  virtual const char *GetName() const;
119  virtual const char *GetIconName() const;
120  virtual Option_t *GetOption() const { return ""; }
121  virtual char *GetObjectInfo(Int_t px, Int_t py) const;
122  virtual const char *GetTitle() const;
123  virtual Bool_t HandleTimer(TTimer *timer);
124  Bool_t HasInconsistentHash() const;
125  virtual ULong_t Hash() const;
126  virtual Bool_t InheritsFrom(const char *classname) const;
127  virtual Bool_t InheritsFrom(const TClass *cl) const;
128  virtual void Inspect() const; // *MENU*
129  virtual Bool_t IsFolder() const;
130  virtual Bool_t IsEqual(const TObject *obj) const;
131  virtual Bool_t IsSortable() const { return kFALSE; }
132 
133  R__ALWAYS_INLINE Bool_t IsOnHeap() const { return TestBit(kIsOnHeap); }
134  R__ALWAYS_INLINE Bool_t IsZombie() const { return TestBit(kZombie); }
135 
136  virtual Bool_t Notify();
137  virtual void ls(Option_t *option="") const;
138  virtual void Paint(Option_t *option="");
139  virtual void Pop();
140  virtual void Print(Option_t *option="") const;
141  virtual Int_t Read(const char *name);
142  virtual void RecursiveRemove(TObject *obj);
143  virtual void SaveAs(const char *filename="",Option_t *option="") const; // *MENU*
144  virtual void SavePrimitive(std::ostream &out, Option_t *option = "");
145  virtual void SetDrawOption(Option_t *option=""); // *MENU*
146  virtual void SetUniqueID(UInt_t uid);
147  virtual void UseCurrentStyle();
148  virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0);
149  virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0) const;
150 
151  //----- operators
152  void *operator new(size_t sz) { return TStorage::ObjectAlloc(sz); }
153  void *operator new[](size_t sz) { return TStorage::ObjectAllocArray(sz); }
154  void *operator new(size_t sz, void *vp) { return TStorage::ObjectAlloc(sz, vp); }
155  void *operator new[](size_t sz, void *vp) { return TStorage::ObjectAlloc(sz, vp); }
156  void operator delete(void *ptr);
157  void operator delete[](void *ptr);
158 #ifdef R__SIZEDDELETE
159  // Sized deallocation.
160  void operator delete(void*, size_t);
161  void operator delete[](void*, size_t);
162 #endif
163 #ifdef R__PLACEMENTDELETE
164  void operator delete(void *ptr, void *vp);
165  void operator delete[](void *ptr, void *vp);
166 #endif
167 
168  //----- bit manipulation
169  void SetBit(UInt_t f, Bool_t set);
170  void SetBit(UInt_t f) { fBits |= f & kBitMask; }
171  void ResetBit(UInt_t f) { fBits &= ~(f & kBitMask); }
172  R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const { return (Bool_t) ((fBits & f) != 0); }
173  Int_t TestBits(UInt_t f) const { return (Int_t) (fBits & f); }
174  void InvertBit(UInt_t f) { fBits ^= f & kBitMask; }
175 
176  //---- error handling
177  virtual void Info(const char *method, const char *msgfmt, ...) const
178 #if defined(__GNUC__) && !defined(__CINT__)
179  __attribute__((format(printf, 3, 4))) /* 1 is the this pointer */
180 #endif
181  ;
182  virtual void Warning(const char *method, const char *msgfmt, ...) const
183 #if defined(__GNUC__) && !defined(__CINT__)
184  __attribute__((format(printf, 3, 4))) /* 1 is the this pointer */
185 #endif
186  ;
187  virtual void Error(const char *method, const char *msgfmt, ...) const
188 #if defined(__GNUC__) && !defined(__CINT__)
189  __attribute__((format(printf, 3, 4))) /* 1 is the this pointer */
190 #endif
191  ;
192  virtual void SysError(const char *method, const char *msgfmt, ...) const
193 #if defined(__GNUC__) && !defined(__CINT__)
194  __attribute__((format(printf, 3, 4))) /* 1 is the this pointer */
195 #endif
196  ;
197  virtual void Fatal(const char *method, const char *msgfmt, ...) const
198 #if defined(__GNUC__) && !defined(__CINT__)
199  __attribute__((format(printf, 3, 4))) /* 1 is the this pointer */
200 #endif
201  ;
202 
203  void AbstractMethod(const char *method) const;
204  void MayNotUse(const char *method) const;
205  void Obsolete(const char *method, const char *asOfVers, const char *removedFromVers) const;
206 
207  //---- static functions
208  static Long_t GetDtorOnly();
209  static void SetDtorOnly(void *obj);
210  static Bool_t GetObjectStat();
211  static void SetObjectStat(Bool_t stat);
212 
213  friend class TClonesArray; // needs to reset kNotDeleted in fBits
214 
215  ClassDef(TObject,1) //Basic ROOT object
216 };
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 /// TObject constructor. It sets the two data words of TObject to their
220 /// initial values. The unique ID is set to 0 and the status word is
221 /// set depending if the object is created on the stack or allocated
222 /// on the heap. Depending on the ROOT environment variable "Root.MemStat"
223 /// (see TEnv) the object is added to the global TObjectTable for
224 /// bookkeeping.
225 
226 inline TObject::TObject() : fBits(kNotDeleted) // Need to leave fUniqueID unset
227 {
228  // This will be reported by valgrind as uninitialized memory reads for
229  // object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
230  TStorage::UpdateIsOnHeap(fUniqueID, fBits);
231 
232  fUniqueID = 0;
233 
234 #ifdef R__WIN32
235  if (R__unlikely(GetObjectStat())) TObject::AddToTObjectTable(this);
236 #else
237  if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
238 #endif
239 }
240 
241 ////////////////////////////////////////////////////////////////////////////////
242 /// TObject copy ctor.
243 
244 inline TObject::TObject(const TObject &obj)
245 {
246  fBits = obj.fBits;
247 
248  // This will be reported by valgrind as uninitialized memory reads for
249  // object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
250  TStorage::UpdateIsOnHeap(fUniqueID, fBits);
251 
252  fBits &= ~kIsReferenced;
253  fBits &= ~kCanDelete;
254 
255  // Set only after used in above call
256  fUniqueID = obj.fUniqueID; // when really unique don't copy
257 
258 #ifdef R__WIN32
259  if (R__unlikely(GetObjectStat())) TObject::AddToTObjectTable(this);
260 #else
261  if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
262 #endif
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// TObject assignment operator.
267 
268 inline TObject &TObject::operator=(const TObject &rhs)
269 {
270  if (R__likely(this != &rhs)) {
271  fUniqueID = rhs.fUniqueID; // when really unique don't copy
272  if (IsOnHeap()) { // test uses fBits so don't move next line
273  fBits = rhs.fBits;
274  fBits |= kIsOnHeap;
275  } else {
276  fBits = rhs.fBits;
277  fBits &= ~kIsOnHeap;
278  }
279  fBits &= ~kIsReferenced;
280  fBits &= ~kCanDelete;
281  }
282  return *this;
283 }
284 
285 
286 ////////////////////////////////////////////////////////////////////////////////
287 /// @brief Check and record whether this class has a consistent
288 /// Hash/RecursiveRemove setup (*) and then return the regular Hash value for
289 /// this object. The intent is for this routine to be called instead of directly
290 /// calling the function Hash during "insert" operations. See TObject::HasInconsistenTObjectHash();
291 ///
292 /// (*) The setup is consistent when all classes in the class hierarchy that overload
293 /// TObject::Hash do call ROOT::CallRecursiveRemoveIfNeeded in their destructor.
294 /// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
295 
296 inline ULong_t TObject::CheckedHash()
297 {
298  // Testing and recording whether we already called HasInconstistentTObjectHash
299  // for this object could save some cpu cycles in some circuntances (at the cost
300  // of reserving yet another bit).
301  // For each insert (CheckedHash is called only for insert in THashList/THashTable), it
302  // cost one memory fetch, one arithmetic operation and one branching.
303  // This save a virtual function call which itself contains a static variable memory
304  // fetch, a branching (of whether the static was already set or not).
305  // Given that a virtual function call is essentially 2 memory fetches (virtual table
306  // location and then content), one arithmetic operation and one function call/jump),
307  // we guess-estimate that the version recording-then-testing-prior-check would start
308  // saving cpu cycle when each object is inserted in average 1.5 times in a THashList/THashTable.
309 
310  // if ( !fBits & kCheckedHash) {
311  if (!CheckTObjectHashConsistency())
312  fBits |= kInconsistent;
313  // fBits &= kChecked;
314  //}
315  return Hash();
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// @brief Return true is the type of this object is *known* to have an
320 /// inconsistent setup for Hash and RecursiveRemove (i.e. missing call to
321 /// RecursiveRemove in destructor).
322 ///
323 /// Note: Since the consistency is only tested for during inserts, this
324 /// routine will return true for object that have never been inserted
325 /// whether or not they have a consistent setup. This has no negative
326 /// side-effect as searching for the object with the right or wrong
327 /// Hash will always yield a not-found answer (Since anyway no hash
328 /// can be guaranteed unique, there is always a check)
329 
330 inline Bool_t TObject::HasInconsistentHash() const
331 {
332  return fBits & kInconsistent;
333 }
334 
335 // Global bits (can be set for any object and should not be reused).
336 // Only here for backward compatibility reasons.
337 // For detailed description see TObject::EStatusBits above.
338 enum EObjBits {
339  kCanDelete = TObject::kCanDelete,
340  kMustCleanup = TObject::kMustCleanup,
341  kObjInCanvas = TObject::kObjInCanvas,
342  kIsReferenced = TObject::kIsReferenced,
343  kHasUUID = TObject::kHasUUID,
344  kCannotPick = TObject::kCannotPick,
345  kNoContextMenu = TObject::kNoContextMenu,
346  kInvalidObject = TObject::kInvalidObject
347 };
348 
349 namespace cling {
350  std::string printValue(TObject *val);
351 }
352 
353 #endif