Skip to content
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

Thread-safe interaction with all enum lists #56

Closed
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
5 changes: 3 additions & 2 deletions core/base/src/TROOT.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
#include "TInterpreter.h"
#include "TListOfTypes.h"
#include "TListOfDataMembers.h"
#include "TListOfEnums.h"
#include "TListOfEnumsWithLock.h"
#include "TListOfFunctions.h"
#include "TListOfFunctionTemplates.h"
#include "TFunctionTemplate.h"
Expand Down Expand Up @@ -1367,8 +1367,9 @@ TObject *TROOT::GetGeometry(const char *name) const
//______________________________________________________________________________
TCollection *TROOT::GetListOfEnums()
{
R__LOCKGUARD2(gROOTMutex);
if(!fEnums) {
fEnums = new TListOfEnums(0);
fEnums = new TListOfEnumsWithLock(0);
}
return fEnums;
}
Expand Down
2 changes: 2 additions & 0 deletions core/meta/inc/LinkDef.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
#pragma link C++ class TListOfFunctionTemplates+;
#pragma link C++ class TListOfDataMembers-;
#pragma link C++ class TListOfEnums+;
#pragma link C++ class TListOfEnumsWithLock+;
#pragma link C++ class TListOfEnumsWithLockIter;
//for new protoclasses
#pragma link C++ class std::vector<TDataMember * >+;
#pragma link C++ class std::vector<TProtoClass::TProtoRealData >+;
Expand Down
3 changes: 2 additions & 1 deletion core/meta/inc/TInterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class TInterpreterValue;
class TMethod;
class TObjArray;
class TEnum;
class TListOfEnums;

R__EXTERN TVirtualMutex *gInterpreterMutex;

Expand Down Expand Up @@ -245,7 +246,7 @@ class TInterpreter : public TNamed {
virtual DeclId_t GetEnum(TClass *cl, const char *name) const = 0;
virtual TEnum* CreateEnum(void *VD, TClass *cl) const = 0;
virtual void UpdateEnumConstants(TEnum* enumObj, TClass* cl) const = 0;
virtual void LoadEnums(TClass* cl) const = 0;
virtual void LoadEnums(TListOfEnums& cl) const = 0;
virtual DeclId_t GetFunction(ClassInfo_t *cl, const char *funcname) = 0;
virtual DeclId_t GetFunctionWithPrototype(ClassInfo_t *cl, const char* method, const char* proto, Bool_t objectIsConst = kFALSE, ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch) = 0;
virtual DeclId_t GetFunctionWithValues(ClassInfo_t *cl, const char* method, const char* params, Bool_t objectIsConst = kFALSE) = 0;
Expand Down
61 changes: 33 additions & 28 deletions core/meta/inc/TListOfEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class TEnum;
class TListOfEnums : public THashList
{
private:
friend class TCling;
friend class TClass;
friend class TProtoClass;

typedef TDictionary::DeclId_t DeclId_t;
TClass *fClass; //! Context of this list. Not owned.

Expand All @@ -44,44 +48,45 @@ class TListOfEnums : public THashList
Bool_t fIsLoaded; //! Mark whether Load was executed.
ULong64_t fLastLoadMarker; //! Represent interpreter state when we last did a full load.

TListOfEnums(const TListOfEnums&); // not implemented
TListOfEnums& operator=(const TListOfEnums&); // not implemented
TListOfEnums(const TListOfEnums&) = delete;
TListOfEnums& operator=(const TListOfEnums&) = delete;

void MapObject(TObject *obj);
void UnmapObject(TObject *obj);

public:
void Load();
void Unload();
void Unload(TEnum *e);
void SetClass(TClass* cl) { fClass = cl; }

TListOfEnums(TClass *cl = 0);
~TListOfEnums();
protected:
TClass* GetClass() const {return fClass;}
TExMap* GetIds() { return fIds;}
TEnum* FindUnloaded(const char* name) { return (TEnum*)fUnloaded->FindObject(name);}
TEnum *Get(DeclId_t id, const char *name);

virtual void Clear(Option_t *option);
virtual void Delete(Option_t *option="");
public:

using THashList::FindObject;
virtual TObject *FindObject(const char *name) const;
TListOfEnums(TClass *cl = 0);
~TListOfEnums() override;

TEnum *Get(DeclId_t id, const char *name);
void Clear(Option_t *option) override;
void Delete(Option_t *option="") override;

Bool_t IsLoaded() const { return fIsLoaded; }
void AddFirst(TObject *obj);
void AddFirst(TObject *obj, Option_t *opt);
void AddLast(TObject *obj);
void AddLast(TObject *obj, Option_t *opt);
void AddAt(TObject *obj, Int_t idx);
void AddAfter(const TObject *after, TObject *obj);
void AddAfter(TObjLink *after, TObject *obj);
void AddBefore(const TObject *before, TObject *obj);
void AddBefore(TObjLink *before, TObject *obj);

void RecursiveRemove(TObject *obj);
TObject *Remove(TObject *obj);
TObject *Remove(TObjLink *lnk);

void Load();
void Unload();
void Unload(TEnum *e);
void SetClass(TClass* cl) { fClass = cl; }
void AddFirst(TObject *obj) override;
void AddFirst(TObject *obj, Option_t *opt) override;
void AddLast(TObject *obj) override;
void AddLast(TObject *obj, Option_t *opt) override;
void AddAt(TObject *obj, Int_t idx) override;
void AddAfter(const TObject *after, TObject *obj) override;
void AddAfter(TObjLink *after, TObject *obj) override;
void AddBefore(const TObject *before, TObject *obj) override;
void AddBefore(TObjLink *before, TObject *obj) override;

void RecursiveRemove(TObject *obj) override;
TObject *Remove(TObject *obj) override;
TObject *Remove(TObjLink *lnk) override;

ClassDef(TListOfEnums,2); // List of TDataMembers for a class
};
Expand Down
103 changes: 103 additions & 0 deletions core/meta/inc/TListOfEnumsWithLock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// @(#)root/cont
// Author: Bianca-Cristina Cristescu February 2014

/*************************************************************************
* Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/

#ifndef ROOT_TListOfEnumsWithLock
#define ROOT_TListOfEnumsWithLock

//////////////////////////////////////////////////////////////////////////
// //
// TListOfEnumsWithLock //
// //
// A collection of TEnum objects designed for fast access given a //
// DeclId_t and for keep track of TEnum that were described //
// unloaded enum. //
// //
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_TListOfEnums
#include "TListOfEnums.h"
#endif

class TExMap;
class TEnum;

class TListOfEnumsWithLock : public TListOfEnums
{
private:
typedef TDictionary::DeclId_t DeclId_t;

TListOfEnumsWithLock(const TListOfEnumsWithLock&) = delete;
TListOfEnumsWithLock& operator=(const TListOfEnumsWithLock&) = delete;

public:

TListOfEnumsWithLock(TClass *cl = 0);
~TListOfEnumsWithLock() override;

void Clear(Option_t *option) override;
void Delete(Option_t *option="") override;

TObject *FindObject(const TObject* obj) const override;
TObject *FindObject(const char *name) const override;
TIterator *MakeIterator(Bool_t dir = kIterForward) const override;

TObject *At(Int_t idx) const override;
TObject *After(const TObject *obj) const override;
TObject *Before(const TObject *obj) const override;
TObject *First() const override;
TObjLink *FirstLink() const override;
TObject **GetObjectRef(const TObject *obj) const override;
TObject *Last() const override;
TObjLink *LastLink() const override;

Int_t GetLast() const override;
Int_t IndexOf(const TObject *obj) const override;

Int_t GetSize() const override;

void AddFirst(TObject *obj) override;
void AddFirst(TObject *obj, Option_t *opt) override;
void AddLast(TObject *obj) override;
void AddLast(TObject *obj, Option_t *opt) override;
void AddAt(TObject *obj, Int_t idx) override;
void AddAfter(const TObject *after, TObject *obj) override;
void AddAfter(TObjLink *after, TObject *obj) override;
void AddBefore(const TObject *before, TObject *obj) override;
void AddBefore(TObjLink *before, TObject *obj) override;

void RecursiveRemove(TObject *obj) override;
TObject *Remove(TObject *obj) override;
TObject *Remove(TObjLink *lnk) override;

ClassDef(TListOfEnumsWithLock,2); // List of TDataMembers for a class
};


//////////////////////////////////////////////////////////////////////////
// //
// TListOfEnumsWithLockIter //
// //
// Iterator of TListOfEnumsWithLock. //
// //
//////////////////////////////////////////////////////////////////////////
class TListOfEnumsWithLockIter : public TListIter
{
public:
TListOfEnumsWithLockIter(const TListOfEnumsWithLock *l, Bool_t dir = kIterForward);

using TListIter::operator=;

TObject *Next();

ClassDef(TListOfEnumsWithLockIter,0)
};

#endif // ROOT_TListOfEnumsWithLock
37 changes: 33 additions & 4 deletions core/meta/src/TClass.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
#include "TListOfFunctions.h"
#include "TListOfFunctionTemplates.h"
#include "TListOfEnums.h"
#include "TListOfEnumsWithLock.h"
#include "TViewPubDataMembers.h"
#include "TViewPubFunctions.h"

Expand Down Expand Up @@ -3321,12 +3322,40 @@ TList *TClass::GetListOfBases()
TList *TClass::GetListOfEnums(Bool_t load /* = kTRUE */)
{
// Return list containing the TEnums of a class.
auto temp = fEnums.load();
if(temp) {
return temp;
}

R__LOCKGUARD(gInterpreterMutex);
if(not load) {
if(! ((kIsClass | kIsStruct | kIsUnion) & Property()) ) {
R__LOCKGUARD(gInterpreterMutex);
if(fEnums) {
return fEnums.load();
}
//namespaces can have enums added to them
fEnums = new TListOfEnumsWithLock(this);
return fEnums;
}
//no one is supposed to modify the returned results
static TListOfEnums s_list;
return &s_list;
}

if (!fEnums) fEnums = new TListOfEnums(this);
if (load) fEnums->Load();
return fEnums;
R__LOCKGUARD(gInterpreterMutex);
if(fEnums) {
return fEnums.load();
}
if( (kIsClass | kIsStruct | kIsUnion) & Property()) {
// For this case, the list will be immutable
temp = new TListOfEnums(this);
} else {
//namespaces can have enums added to them
temp = new TListOfEnumsWithLock(this);
}
temp->Load();
fEnums = temp;
return temp;
}

//______________________________________________________________________________
Expand Down
8 changes: 3 additions & 5 deletions core/meta/src/TCling.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3167,20 +3167,18 @@ void TCling::CreateListOfBaseClasses(TClass *cl) const
}

//______________________________________________________________________________
void TCling::LoadEnums(TClass* cl) const
void TCling::LoadEnums(TListOfEnums& enumList) const
{
// Create list of pointers to enums for TClass cl.
R__LOCKGUARD2(gInterpreterMutex);

const Decl * D;
TListOfEnums* enumList;
TClass* cl = enumList.GetClass();
if (cl) {
D = ((TClingClassInfo*)cl->GetClassInfo())->GetDecl();
enumList = (TListOfEnums*)cl->GetListOfEnums(false);
}
else {
D = fInterpreter->getCI()->getASTContext().getTranslationUnitDecl();
enumList = (TListOfEnums*)gROOT->GetListOfEnums();
}
// Iterate on the decl of the class and get the enums.
if (const clang::DeclContext* DC = dyn_cast<clang::DeclContext>(D)) {
Expand All @@ -3204,7 +3202,7 @@ void TCling::LoadEnums(TClass* cl) const
if (!buf.empty()) {
const char* name = buf.c_str();
// Add the enum to the list of loaded enums.
enumList->Get(ED, name);
enumList.Get(ED, name);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/meta/src/TCling.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class TCling : public TInterpreter {
virtual DeclId_t GetEnum(TClass *cl, const char *name) const;
virtual TEnum* CreateEnum(void *VD, TClass *cl) const;
virtual void UpdateEnumConstants(TEnum* enumObj, TClass* cl) const;
virtual void LoadEnums(TClass* cl) const;
virtual void LoadEnums(TListOfEnums& cl) const;
TString GetMangledName(TClass* cl, const char* method, const char* params, Bool_t objectIsConst = kFALSE);
TString GetMangledNameWithPrototype(TClass* cl, const char* method, const char* proto, Bool_t objectIsConst = kFALSE, ROOT::EFunctionMatchMode mode = ROOT::kConversionMatch);
void* GetInterfaceMethod(TClass* cl, const char* method, const char* params, Bool_t objectIsConst = kFALSE);
Expand Down
22 changes: 2 additions & 20 deletions core/meta/src/TListOfEnums.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -176,25 +176,6 @@ void TListOfEnums::Delete(Option_t *option /* ="" */)
fIsLoaded = kFALSE;
}

//______________________________________________________________________________
TObject *TListOfEnums::FindObject(const char *name) const
{
// Specialize FindObject to do search for the
// a enum just by name or create it if its not already in the list

TObject *result = THashList::FindObject(name);
if (!result) {

R__LOCKGUARD(gInterpreterMutex);

TInterpreter::DeclId_t decl;
if (fClass) decl = gInterpreter->GetEnum(fClass, name);
else decl = gInterpreter->GetEnum(0, name);
if (decl) result = const_cast<TListOfEnums *>(this)->Get(decl, name);
}
return result;
}

//______________________________________________________________________________
TEnum *TListOfEnums::Get(DeclId_t id, const char *name)
{
Expand Down Expand Up @@ -261,6 +242,7 @@ TEnum *TListOfEnums::Get(DeclId_t id, const char *name)
return e;
}


//______________________________________________________________________________
void TListOfEnums::UnmapObject(TObject *obj)
{
Expand Down Expand Up @@ -375,7 +357,7 @@ void TListOfEnums::Load()
// We cannot clear the whole unloaded list. It is too much.
// fUnloaded->Clear();

gInterpreter->LoadEnums(fClass);
gInterpreter->LoadEnums(*this);
}

//______________________________________________________________________________
Expand Down
Loading