Skip to content

Faster default/copy construction of TObjects #482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions core/base/inc/TObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class TObject {
static Long_t fgDtorOnly; ///< object for which to call dtor only (i.e. no delete)
static Bool_t fgObjectStat; ///< if true keep track of objects in TObjectTable

static void AddToTObjectTable(TObject *);

protected:
void MakeZombie() { fBits |= kZombie; }
virtual void DoError(int level, const char *location, const char *fmt, va_list va) const;
Expand Down Expand Up @@ -200,6 +202,68 @@ class TObject {
ClassDef(TObject,1) //Basic ROOT object
};

////////////////////////////////////////////////////////////////////////////////
/// TObject constructor. It sets the two data words of TObject to their
/// initial values. The unique ID is set to 0 and the status word is
/// set depending if the object is created on the stack or allocated
/// on the heap. Depending on the ROOT environment variable "Root.MemStat"
/// (see TEnv) the object is added to the global TObjectTable for
/// bookkeeping.

inline TObject::TObject() : fBits(kNotDeleted) // Need to leave FUniqueID unset
{
// This will be reported by valgrind as uninitialized memory reads for
// object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
if (TStorage::FilledByObjectAlloc(&fUniqueID)) fBits |= kIsOnHeap;

fUniqueID = 0;

if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
}

////////////////////////////////////////////////////////////////////////////////
/// TObject copy ctor.

inline TObject::TObject(const TObject &obj)
{
fBits = obj.fBits;

// This will be reported by valgrind as uninitialized memory reads for
// object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
if (TStorage::FilledByObjectAlloc(&fUniqueID))
fBits |= kIsOnHeap;
else
fBits &= ~kIsOnHeap;

fBits &= ~kIsReferenced;
fBits &= ~kCanDelete;

// Set only after used in above call
fUniqueID = obj.fUniqueID; // when really unique don't copy

if (R__unlikely(fgObjectStat)) TObject::AddToTObjectTable(this);
}

////////////////////////////////////////////////////////////////////////////////
/// TObject assignment operator.

inline TObject &TObject::operator=(const TObject &rhs)
{
if (R__likely(this != &rhs)) {
fUniqueID = rhs.fUniqueID; // when really unique don't copy
if (IsOnHeap()) { // test uses fBits so don't move next line
fBits = rhs.fBits;
fBits |= kIsOnHeap;
} else {
fBits = rhs.fBits;
fBits &= ~kIsOnHeap;
}
fBits &= ~kIsReferenced;
fBits &= ~kCanDelete;
}
return *this;
}

// Global bits (can be set for any object and should not be reused).
// Only here for backward compatibility reasons.
// For detailed description see TObject::EStatusBits above.
Expand Down
73 changes: 10 additions & 63 deletions core/base/src/TObject.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -54,69 +54,6 @@ Bool_t TObject::fgObjectStat = kTRUE;

ClassImp(TObject)

////////////////////////////////////////////////////////////////////////////////
/// TObject constructor. It sets the two data words of TObject to their
/// initial values. The unique ID is set to 0 and the status word is
/// set depending if the object is created on the stack or allocated
/// on the heap. Depending on the ROOT environment variable "Root.MemStat"
/// (see TEnv) the object is added to the global TObjectTable for
/// bookkeeping.

TObject::TObject() : fBits(kNotDeleted) //Need to leave FUniqueID unset
{
// This will be reported by valgrind as uninitialized memory reads for
// object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
if (TStorage::FilledByObjectAlloc(&fUniqueID))
fBits |= kIsOnHeap;

fUniqueID = 0;

if (fgObjectStat) TObjectTable::AddObj(this);
}

////////////////////////////////////////////////////////////////////////////////
/// TObject copy ctor.

TObject::TObject(const TObject &obj)
{
fBits = obj.fBits;

// This will be reported by valgrind as uninitialized memory reads for
// object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
if (TStorage::FilledByObjectAlloc(&fUniqueID))
fBits |= kIsOnHeap;
else
fBits &= ~kIsOnHeap;

fBits &= ~kIsReferenced;
fBits &= ~kCanDelete;

//Set only after used in above call
fUniqueID = obj.fUniqueID; // when really unique don't copy

if (fgObjectStat) TObjectTable::AddObj(this);
}

////////////////////////////////////////////////////////////////////////////////
/// TObject assignment operator.

TObject& TObject::operator=(const TObject &rhs)
{
if (this != &rhs) {
fUniqueID = rhs.fUniqueID; // when really unique don't copy
if (IsOnHeap()) { // test uses fBits so don't move next line
fBits = rhs.fBits;
fBits |= kIsOnHeap;
} else {
fBits = rhs.fBits;
fBits &= ~kIsOnHeap;
}
fBits &= ~kIsReferenced;
fBits &= ~kCanDelete;
}
return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Copy this to obj.

Expand Down Expand Up @@ -158,6 +95,16 @@ TObject::~TObject()
if (fgObjectStat && gObjectTable) gObjectTable->RemoveQuietly(this);
}

////////////////////////////////////////////////////////////////////////////////
/// Private helper function which will dispatch to
/// TObjectTable::AddObj.
/// Included here to avoid circular dependency between header files.

void TObject::AddToTObjectTable(TObject *op)
{
TObjectTable::AddObj(op);
}

////////////////////////////////////////////////////////////////////////////////
/// Append graphics object to current pad. In case no current pad is set
/// yet, create a default canvas with the name "c1".
Expand Down