Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:46:23

0001 // @(#)root/base:$Id$
0002 // Author: Rene Brun   26/12/94
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TObject
0013 #define ROOT_TObject
0014 
0015 
0016 // #include "RConfigure.h"  // included via Rtypes.h
0017 #include "Rtypes.h"
0018 #include "TStorage.h"
0019 #include "TVersionCheck.h"
0020 
0021 #include <stdarg.h>
0022 #include <string>
0023 #include <iosfwd>
0024 
0025 #ifdef WIN32
0026 #undef RemoveDirectory
0027 #endif
0028 
0029 class TList;
0030 class TBrowser;
0031 class TBuffer;
0032 class TObjArray;
0033 class TMethod;
0034 class TTimer;
0035 
0036 namespace ROOT {
0037 namespace Internal {
0038    bool DeleteChangesMemoryImpl();
0039 }}
0040 
0041 class TObject {
0042 
0043 private:
0044    UInt_t         fUniqueID;   ///< object unique identifier
0045    UInt_t         fBits;       ///< bit field status word
0046 
0047    static Longptr_t fgDtorOnly;    ///< object for which to call dtor only (i.e. no delete)
0048    static Bool_t    fgObjectStat;  ///< if true keep track of objects in TObjectTable
0049 
0050    static void AddToTObjectTable(TObject *);
0051 
0052 protected:
0053    void MakeZombie() { fBits |= kZombie; }
0054    virtual void DoError(int level, const char *location, const char *fmt, va_list va) const;
0055 
0056 public:
0057    //----- Global bits (can be set for any object and should not be reused).
0058    //----- Bits 0 - 13 are reserved as global bits. Bits 14 - 23 can be used
0059    //----- in different class hierarchies (make sure there is no overlap in
0060    //----- any given hierarchy).
0061    enum EStatusBits {
0062       kCanDelete        = BIT(0),   ///< if object in a list can be deleted
0063       // 2 is taken by TDataMember
0064       kMustCleanup      = BIT(3),   ///< if object destructor must call RecursiveRemove()
0065       kIsReferenced     = BIT(4),   ///< if object is referenced by a TRef or TRefArray
0066       kHasUUID          = BIT(5),   ///< if object has a TUUID (its fUniqueID=UUIDNumber)
0067       kCannotPick       = BIT(6),   ///< if object in a pad cannot be picked
0068       // 7 is taken by TAxis and TClass.
0069       kNoContextMenu    = BIT(8),   ///< if object does not want context menu
0070       // 9, 10 are taken by TH1, TF1, TAxis and a few others
0071       // 12 is taken by TAxis
0072       kInvalidObject    = BIT(13)   ///< if object ctor succeeded but object should not be used
0073    };
0074 
0075    enum EDeprecatedStatusBits {
0076       kObjInCanvas      = BIT(3)   ///< for backward compatibility only, use kMustCleanup
0077    };
0078 
0079    //----- Private bits, clients can only test but not change them
0080    enum {
0081       kIsOnHeap      = 0x01000000,    ///< object is on heap
0082       kNotDeleted    = 0x02000000,    ///< object has not been deleted
0083       kZombie        = 0x04000000,    ///< object ctor failed
0084       kInconsistent  = 0x08000000,    ///< class overload Hash but does call RecursiveRemove in destructor
0085   //  kCheckedHash   = 0x10000000,    ///< CheckedHash has check for the consistency of Hash/RecursiveRemove
0086       kBitMask       = 0x00ffffff
0087    };
0088 
0089    //----- Write() options
0090    enum {
0091       kSingleKey     = BIT(0),        ///< write collection with single key
0092       kOverwrite     = BIT(1),        ///< overwrite existing object with same name
0093       kWriteDelete   = BIT(2),        ///< write object, then delete previous key with same name
0094    };
0095 
0096 protected:
0097    enum { // DeprectatedWriteOptions
0098       ///< Used to request that the class specific implementation of `TObject::Write`
0099       ///< just prepare the objects to be ready to be written but do not actually write
0100       ///< them into the TBuffer. This is just for example by TBufferMerger to request
0101       ///< that the TTree inside the file calls `TTree::FlushBaskets` (outside of the merging lock)
0102       ///< and TBufferMerger will later ask for the write (inside the merging lock).
0103       ///< To take advantage of this feature the class needs to overload `TObject::Write`
0104       ///< and use this enum value accordingly.  (See `TTree::Write` and `TObject::Write`)
0105       ///< Do not use, this feature will be migrate to the Merge function (See TClass and TTree::Merge)
0106       kOnlyPrepStep  = BIT(3)
0107    };
0108 
0109 public:
0110 
0111    TObject();
0112    TObject(const TObject &object);
0113    TObject &operator=(const TObject &rhs);
0114    virtual ~TObject();
0115 
0116    virtual void        AppendPad(Option_t *option="");
0117    virtual void        Browse(TBrowser *b);
0118    virtual const char *ClassName() const;
0119    virtual void        Clear(Option_t * /*option*/ ="") { }
0120            ULong_t     CheckedHash(); // Not virtual
0121    virtual TObject    *Clone(const char *newname="") const;
0122    virtual Int_t       Compare(const TObject *obj) const;
0123    virtual void        Copy(TObject &object) const;
0124    virtual void        Delete(Option_t *option=""); // *MENU*
0125    virtual Int_t       DistancetoPrimitive(Int_t px, Int_t py);
0126    virtual void        Draw(Option_t *option="");
0127    virtual void        DrawClass() const; // *MENU*
0128    virtual TObject    *DrawClone(Option_t *option="") const; // *MENU*
0129    virtual void        Dump() const; // *MENU*
0130    virtual void        Execute(const char *method,  const char *params, Int_t *error = nullptr);
0131    virtual void        Execute(TMethod *method, TObjArray *params, Int_t *error = nullptr);
0132    virtual void        ExecuteEvent(Int_t event, Int_t px, Int_t py);
0133    virtual TObject    *FindObject(const char *name) const;
0134    virtual TObject    *FindObject(const TObject *obj) const;
0135    virtual Option_t   *GetDrawOption() const;
0136    virtual UInt_t      GetUniqueID() const;
0137    virtual const char *GetName() const;
0138    virtual const char *GetIconName() const;
0139    virtual Option_t   *GetOption() const { return ""; }
0140    virtual char       *GetObjectInfo(Int_t px, Int_t py) const;
0141    virtual const char *GetTitle() const;
0142    virtual Bool_t      HandleTimer(TTimer *timer);
0143            Bool_t      HasInconsistentHash() const;
0144    virtual ULong_t     Hash() const;
0145    virtual Bool_t      InheritsFrom(const char *classname) const;
0146    virtual Bool_t      InheritsFrom(const TClass *cl) const;
0147    virtual void        Inspect() const; // *MENU*
0148    virtual Bool_t      IsFolder() const;
0149    virtual Bool_t      IsEqual(const TObject *obj) const;
0150    virtual Bool_t      IsSortable() const { return kFALSE; }
0151 
0152    R__ALWAYS_INLINE Bool_t IsOnHeap() const { return TestBit(kIsOnHeap); }
0153    R__ALWAYS_INLINE Bool_t IsZombie() const { return TestBit(kZombie); }
0154 
0155    virtual Bool_t      Notify();
0156    virtual void        ls(Option_t *option="") const;
0157    virtual void        Paint(Option_t *option="");
0158    virtual void        Pop();
0159    virtual void        Print(Option_t *option="") const;
0160    virtual Int_t       Read(const char *name);
0161    virtual void        RecursiveRemove(TObject *obj);
0162    virtual void        SaveAs(const char *filename="",Option_t *option="") const; // *MENU*
0163    virtual void        SavePrimitive(std::ostream &out, Option_t *option = "");
0164    virtual void        SetDrawOption(Option_t *option="");  // *MENU*
0165    virtual void        SetUniqueID(UInt_t uid);
0166    virtual void        UseCurrentStyle();
0167    virtual Int_t       Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0);
0168    virtual Int_t       Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) const;
0169 
0170    /// IsDestructed
0171    ///
0172    /// \note This function must be non-virtual as it can be used on destructed (but
0173    /// not yet modified) memory.  This is used for example in TClonesArray to record
0174    /// the element that have been destructed but not deleted and thus are ready for
0175    /// re-use (by operator new with placement).
0176    ///
0177    /// \return true if this object's destructor has been run.
0178    Bool_t IsDestructed() const { return !TestBit(kNotDeleted); }
0179 
0180    //----- operators
0181    void    *operator new(size_t sz) { return TStorage::ObjectAlloc(sz); }
0182    void    *operator new[](size_t sz) { return TStorage::ObjectAllocArray(sz); }
0183    void    *operator new(size_t sz, void *vp) { return TStorage::ObjectAlloc(sz, vp); }
0184    void    *operator new[](size_t sz, void *vp) { return TStorage::ObjectAlloc(sz, vp); }
0185    void     operator delete(void *ptr);
0186    void     operator delete[](void *ptr);
0187 #ifdef R__SIZEDDELETE
0188    // Sized deallocation.
0189    void     operator delete(void*, size_t);
0190    void     operator delete[](void*, size_t);
0191 #endif
0192    void     operator delete(void *ptr, void *vp);
0193    void     operator delete[](void *ptr, void *vp);
0194 
0195    //----- bit manipulation
0196    void     SetBit(UInt_t f, Bool_t set);
0197    void     SetBit(UInt_t f) { fBits |= f & kBitMask; }
0198    void     ResetBit(UInt_t f) { fBits &= ~(f & kBitMask); }
0199    R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const { return (Bool_t) ((fBits & f) != 0); }
0200    Int_t    TestBits(UInt_t f) const { return (Int_t) (fBits & f); }
0201    void     InvertBit(UInt_t f) { fBits ^= f & kBitMask; }
0202 
0203    //---- error handling
0204    virtual void     Info(const char *method, const char *msgfmt, ...) const
0205 #if defined(__GNUC__)
0206    __attribute__((format(printf, 3, 4)))   /* 1 is the this pointer */
0207 #endif
0208    ;
0209    virtual void     Warning(const char *method, const char *msgfmt, ...) const
0210 #if defined(__GNUC__)
0211    __attribute__((format(printf, 3, 4)))   /* 1 is the this pointer */
0212 #endif
0213    ;
0214    virtual void     Error(const char *method, const char *msgfmt, ...) const
0215 #if defined(__GNUC__)
0216    __attribute__((format(printf, 3, 4)))   /* 1 is the this pointer */
0217 #endif
0218    ;
0219    virtual void     SysError(const char *method, const char *msgfmt, ...) const
0220 #if defined(__GNUC__)
0221    __attribute__((format(printf, 3, 4)))   /* 1 is the this pointer */
0222 #endif
0223    ;
0224    virtual void     Fatal(const char *method, const char *msgfmt, ...) const
0225 #if defined(__GNUC__)
0226    __attribute__((format(printf, 3, 4)))   /* 1 is the this pointer */
0227 #endif
0228    ;
0229 
0230    void     AbstractMethod(const char *method) const;
0231    void     MayNotUse(const char *method) const;
0232    void     Obsolete(const char *method, const char *asOfVers, const char *removedFromVers) const;
0233 
0234    //---- static functions
0235    static Longptr_t GetDtorOnly();
0236    static void      SetDtorOnly(void *obj);
0237    static Bool_t    GetObjectStat();
0238    static void      SetObjectStat(Bool_t stat);
0239 
0240    friend class TClonesArray; // needs to reset kNotDeleted in fBits
0241    friend bool ROOT::Internal::DeleteChangesMemoryImpl();
0242 
0243    ClassDef(TObject,1)  //Basic ROOT object
0244 };
0245 
0246 ////////////////////////////////////////////////////////////////////////////////
0247 /// TObject constructor. It sets the two data words of TObject to their
0248 /// initial values. The unique ID is set to 0 and the status word is
0249 /// set depending if the object is created on the stack or allocated
0250 /// on the heap. Depending on the ROOT environment variable "Root.ObjStat"
0251 /// (see TEnv) the object is added to the global TObjectTable for
0252 /// bookkeeping.
0253 
0254 inline TObject::TObject() : fBits(kNotDeleted) // Need to leave fUniqueID unset
0255 {
0256    // This will be reported by valgrind as uninitialized memory reads for
0257    // object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
0258    TStorage::UpdateIsOnHeap(fUniqueID, fBits);
0259 
0260    fUniqueID = 0;
0261 
0262 #ifdef R__WIN32
0263    if (R__unlikely(GetObjectStat())) TObject::AddToTObjectTable(this);
0264 #else
0265    if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
0266 #endif
0267 }
0268 
0269 ////////////////////////////////////////////////////////////////////////////////
0270 /// TObject copy ctor.
0271 
0272 inline TObject::TObject(const TObject &obj)
0273 {
0274    fBits = obj.fBits;
0275 
0276    // This will be reported by valgrind as uninitialized memory reads for
0277    // object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
0278    TStorage::UpdateIsOnHeap(fUniqueID, fBits);
0279 
0280    fBits &= ~kIsReferenced;
0281    fBits &= ~kCanDelete;
0282 
0283    // Set only after used in above call
0284    fUniqueID = obj.fUniqueID; // when really unique don't copy
0285 
0286 #ifdef R__WIN32
0287    if (R__unlikely(GetObjectStat())) TObject::AddToTObjectTable(this);
0288 #else
0289    if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
0290 #endif
0291 }
0292 
0293 ////////////////////////////////////////////////////////////////////////////////
0294 /// TObject assignment operator.
0295 
0296 inline TObject &TObject::operator=(const TObject &rhs)
0297 {
0298    if (R__likely(this != &rhs)) {
0299       fUniqueID = rhs.fUniqueID; // when really unique don't copy
0300       if (IsOnHeap()) {          // test uses fBits so don't move next line
0301          fBits = rhs.fBits;
0302          fBits |= kIsOnHeap;
0303       } else {
0304          fBits = rhs.fBits;
0305          fBits &= ~kIsOnHeap;
0306       }
0307       fBits &= ~kIsReferenced;
0308       fBits &= ~kCanDelete;
0309    }
0310    return *this;
0311 }
0312 
0313 
0314 ////////////////////////////////////////////////////////////////////////////////
0315 /// @brief Check and record whether this class has a consistent
0316 /// Hash/RecursiveRemove setup (*) and then return the regular Hash value for
0317 /// this object. The intent is for this routine to be called instead of directly
0318 /// calling the function Hash during "insert" operations.  See TObject::HasInconsistenTObjectHash();
0319 ///
0320 /// (*) The setup is consistent when all classes in the class hierarchy that overload
0321 /// TObject::Hash do call ROOT::CallRecursiveRemoveIfNeeded in their destructor.
0322 /// i.e. it is safe to call the Hash virtual function during the RecursiveRemove operation.
0323 
0324 inline ULong_t TObject::CheckedHash()
0325 {
0326    // Testing and recording whether we already called HasInconstistentTObjectHash
0327    // for this object could save some cpu cycles in some circuntances (at the cost
0328    // of reserving yet another bit).
0329    // For each insert (CheckedHash is called only for insert in THashList/THashTable), it
0330    // cost one memory fetch, one arithmetic operation and one branching.
0331    // This save a virtual function call which itself contains a static variable memory
0332    // fetch, a branching (of whether the static was already set or not).
0333    // Given that a virtual function call is essentially 2 memory fetches (virtual table
0334    // location and then content), one arithmetic operation and one function call/jump),
0335    // we guess-estimate that the version recording-then-testing-prior-check would start
0336    // saving cpu cycle when each object is inserted in average 1.5 times in a THashList/THashTable.
0337 
0338    // if ( !fBits & kCheckedHash) {
0339    if (!CheckTObjectHashConsistency())
0340       fBits |= kInconsistent;
0341    //   fBits &= kChecked;
0342    //}
0343    return Hash();
0344 }
0345 
0346 ////////////////////////////////////////////////////////////////////////////////
0347 /// @brief Return true is the type of this object is *known* to have an
0348 /// inconsistent setup for Hash and RecursiveRemove (i.e. missing call to
0349 /// RecursiveRemove in destructor).
0350 ///
0351 /// Note: Since the consistency is only tested for during inserts, this
0352 /// routine will return true for object that have never been inserted
0353 /// whether or not they have a consistent setup.  This has no negative
0354 /// side-effect as searching for the object with the right or wrong
0355 /// Hash will always yield a not-found answer (Since anyway no hash
0356 /// can be guaranteed unique, there is always a check)
0357 
0358 inline Bool_t TObject::HasInconsistentHash() const
0359 {
0360    return fBits & kInconsistent;
0361 }
0362 
0363 // Global bits (can be set for any object and should not be reused).
0364 // Only here for backward compatibility reasons.
0365 // For detailed description see TObject::EStatusBits above.
0366 enum EObjBits {
0367    kCanDelete        = TObject::kCanDelete,
0368    kMustCleanup      = TObject::kMustCleanup,
0369    kObjInCanvas      = TObject::kObjInCanvas,
0370    kIsReferenced     = TObject::kIsReferenced,
0371    kHasUUID          = TObject::kHasUUID,
0372    kCannotPick       = TObject::kCannotPick,
0373    kNoContextMenu    = TObject::kNoContextMenu,
0374    kInvalidObject    = TObject::kInvalidObject
0375 };
0376 
0377 namespace cling {
0378    std::string printValue(TObject *val);
0379 }
0380 
0381 namespace ROOT {
0382 
0383 namespace Internal {
0384    bool DeleteChangesMemory();
0385 } // Internal
0386 
0387 namespace Detail {
0388 
0389 
0390 /// @brief Check if the TObject's memory has been deleted.
0391 /// @warning This should be only used for error mitigation as the answer is only
0392 ///    sometimes correct.  It actually just checks whether the object has been
0393 ///    deleted, so this will falsely return true for an object that has
0394 ///    been destructed but its memory has not been deleted.  This will return an
0395 ///    undefined value if the memory is re-used between the deletion and the check.
0396 ///    i.e.  This is useful to prevent a segmentation fault in case where the problem
0397 ///    can be detected when the deletion and the usage are 'close-by'
0398 /// @warning In enviroment where delete taints (changes) the memory, this function
0399 ///    always returns false as the marker left by ~TObject will be overwritten.
0400 /// @param obj The memory to check
0401 /// @return true if the object has been destructed and it can be inferred that it has been deleted
0402 R__ALWAYS_INLINE bool HasBeenDeleted(const TObject *obj) {
0403    return !ROOT::Internal::DeleteChangesMemory() && obj->IsDestructed();
0404 }
0405 
0406 }} // ROOT::Details
0407 
0408 #endif