#include "TListOfFunctions.h"
#include "TClass.h"
#include "TExMap.h"
#include "TFunction.h"
#include "TMethod.h"
#include "TInterpreter.h"
#include "TVirtualMutex.h"
ClassImp(TListOfFunctions)
TListOfFunctions::TListOfFunctions(TClass *cl) : fClass(cl),fIds(0),fUnloaded(0),fLastLoadMarker(0)
{
fIds = new TExMap;
fUnloaded = new THashList;
}
TListOfFunctions::~TListOfFunctions()
{
THashList::Delete();
delete fIds;
fUnloaded->Delete();
delete fUnloaded;
}
void TListOfFunctions::MapObject(TObject *obj)
{
TFunction *f = dynamic_cast<TFunction*>(obj);
if (f) {
fIds->Add((Long64_t)f->GetDeclId(),(Long64_t)f);
}
}
void TListOfFunctions::AddFirst(TObject *obj)
{
THashList::AddFirst(obj);
MapObject(obj);
}
void TListOfFunctions::AddFirst(TObject *obj, Option_t *opt)
{
THashList::AddFirst(obj,opt);
MapObject(obj);
}
void TListOfFunctions::AddLast(TObject *obj)
{
THashList::AddLast(obj);
MapObject(obj);
}
void TListOfFunctions::AddLast(TObject *obj, Option_t *opt)
{
THashList::AddLast(obj, opt);
MapObject(obj);
}
void TListOfFunctions::AddAt(TObject *obj, Int_t idx)
{
THashList::AddAt(obj, idx);
MapObject(obj);
}
void TListOfFunctions::AddAfter(const TObject *after, TObject *obj)
{
THashList::AddAfter(after, obj);
MapObject(obj);
}
void TListOfFunctions::AddAfter(TObjLink *after, TObject *obj)
{
THashList::AddAfter(after, obj);
MapObject(obj);
}
void TListOfFunctions::AddBefore(const TObject *before, TObject *obj)
{
THashList::AddBefore(before, obj);
MapObject(obj);
}
void TListOfFunctions::AddBefore(TObjLink *before, TObject *obj)
{
THashList::AddBefore(before, obj);
MapObject(obj);
}
void TListOfFunctions::Clear(Option_t *option)
{
fUnloaded->Clear(option);
fIds->Clear();
THashList::Clear(option);
}
void TListOfFunctions::Delete(Option_t *option )
{
fUnloaded->Delete(option);
fIds->Clear();
THashList::Delete(option);
}
TObject *TListOfFunctions::FindObject(const char *name) const
{
R__LOCKGUARD(gInterpreterMutex);
TObject *result = THashList::FindObject(name);
if (!result) {
TInterpreter::DeclId_t decl;
if (fClass) decl = gInterpreter->GetFunction(fClass->GetClassInfo(),name);
else decl = gInterpreter->GetFunction(0,name);
if (decl) result = const_cast<TListOfFunctions*>(this)->Get(decl);
}
return result;
}
TList* TListOfFunctions::GetListForObjectNonConst(const char* name)
{
R__LOCKGUARD(gInterpreterMutex);
TList* overloads = (TList*)fOverloads.FindObject(name);
TExMap overloadsSet;
Bool_t wasEmpty = true;
if (!overloads) {
overloads = new TList();
overloads->SetName(name);
fOverloads.Add(overloads);
} else {
TIter iOverload(overloads);
while (TFunction* over = (TFunction*)iOverload()) {
wasEmpty = false;
overloadsSet.Add((Long64_t)(ULong64_t)over->GetDeclId(),
(Long64_t)(ULong64_t)over);
}
}
std::vector<DeclId_t> overloadDecls;
ClassInfo_t* ci = fClass ? fClass->GetClassInfo() : 0;
gInterpreter->GetFunctionOverloads(ci, name, overloadDecls);
for (std::vector<DeclId_t>::const_iterator iD = overloadDecls.begin(),
eD = overloadDecls.end(); iD != eD; ++iD) {
TFunction* over = Get(*iD);
if (wasEmpty || !overloadsSet.GetValue((Long64_t)(ULong64_t)over->GetDeclId())) {
overloads->Add(over);
}
}
return overloads;
}
TList* TListOfFunctions::GetListForObject(const char* name) const
{
return const_cast<TListOfFunctions*>(this)->GetListForObjectNonConst(name);
}
TList* TListOfFunctions::GetListForObject(const TObject* obj) const
{
if (!obj) return 0;
return const_cast<TListOfFunctions*>(this)
->GetListForObjectNonConst(obj->GetName());
}
TFunction *TListOfFunctions::Find(DeclId_t id) const
{
if (!id) return 0;
R__LOCKGUARD(gInterpreterMutex);
return (TFunction*)fIds->GetValue((Long64_t)id);
}
TFunction *TListOfFunctions::Get(DeclId_t id)
{
if (!id) return 0;
TFunction *f = Find(id);
if (f) return f;
R__LOCKGUARD(gInterpreterMutex);
if (fClass) {
if (!gInterpreter->ClassInfo_Contains(fClass->GetClassInfo(),id)) return 0;
} else {
if (!gInterpreter->ClassInfo_Contains(0,id)) return 0;
}
R__LOCKGUARD(gInterpreterMutex);
MethodInfo_t *m = gInterpreter->MethodInfo_Factory(id);
const char *name = gInterpreter->MethodInfo_Name(m);
if (TList* bucketForMethod = fUnloaded->GetListForObject(name)) {
TString mangledName( gInterpreter->MethodInfo_GetMangledName(m) );
TIter next(bucketForMethod);
TFunction *uf;
while ((uf = (TFunction *) next())) {
if (uf->GetMangledName() == mangledName) {
fUnloaded->Remove(uf);
uf->Update(m);
f = uf;
break;
}
}
}
if (!f) {
if (fClass) f = new TMethod(m, fClass);
else f = new TFunction(m);
}
THashList::AddLast(f);
fIds->Add((Long64_t)id,(Long64_t)f);
return f;
}
void TListOfFunctions::UnmapObject(TObject *obj)
{
TFunction *f = dynamic_cast<TFunction*>(obj);
if (f) {
fIds->Remove((Long64_t)f->GetDeclId());
}
}
void TListOfFunctions::RecursiveRemove(TObject *obj)
{
if (!obj) return;
THashList::RecursiveRemove(obj);
fUnloaded->RecursiveRemove(obj);
UnmapObject(obj);
}
TObject* TListOfFunctions::Remove(TObject *obj)
{
Bool_t found;
found = THashList::Remove(obj);
if (!found) {
found = fUnloaded->Remove(obj);
}
UnmapObject(obj);
if (found) return obj;
else return 0;
}
TObject* TListOfFunctions::Remove(TObjLink *lnk)
{
if (!lnk) return 0;
TObject *obj = lnk->GetObject();
THashList::Remove(lnk);
fUnloaded->Remove(obj);
UnmapObject(obj);
return obj;
}
void TListOfFunctions::Load()
{
if (fClass && fClass->GetClassInfo() == 0) return;
R__LOCKGUARD(gInterpreterMutex);
ULong64_t currentTransaction = gInterpreter->GetInterpreterStateMarker();
if (currentTransaction == fLastLoadMarker) {
return;
}
fLastLoadMarker = currentTransaction;
ClassInfo_t *info;
if (fClass) info = fClass->GetClassInfo();
else info = gInterpreter->ClassInfo_Factory();
MethodInfo_t *t = gInterpreter->MethodInfo_Factory(info);
while (gInterpreter->MethodInfo_Next(t)) {
if (gInterpreter->MethodInfo_IsValid(t)) {
TDictionary::DeclId_t mid = gInterpreter->GetDeclId(t);
Get(mid);
}
}
gInterpreter->MethodInfo_Delete(t);
if (!fClass) gInterpreter->ClassInfo_Delete(info);
}
void TListOfFunctions::Unload()
{
TObjLink *lnk = FirstLink();
while (lnk) {
TFunction *func = (TFunction*)lnk->GetObject();
fIds->Remove((Long64_t)func->GetDeclId());
fUnloaded->Add(func);
lnk = lnk->Next();
}
THashList::Clear();
}
void TListOfFunctions::Unload(TFunction *func)
{
if (THashList::Remove(func)) {
fIds->Remove((Long64_t)func->GetDeclId());
fUnloaded->Add(func);
}
}
TObject* TListOfFunctions::FindObject(const TObject* obj) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::FindObject(obj);
}
TIterator* TListOfFunctions::MakeIterator(Bool_t dir ) const
{
R__LOCKGUARD(gInterpreterMutex);
return new TListOfFunctionsIter(this,dir);
}
TObject* TListOfFunctions::At(Int_t idx) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::At(idx);
}
TObject* TListOfFunctions::After(const TObject *obj) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::After(obj);
}
TObject* TListOfFunctions::Before(const TObject *obj) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::Before(obj);
}
TObject* TListOfFunctions::First() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::First();
}
TObjLink* TListOfFunctions::FirstLink() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::FirstLink();
}
TObject** TListOfFunctions::GetObjectRef(const TObject *obj) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::GetObjectRef(obj);
}
TObject* TListOfFunctions::Last() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::Last();
}
TObjLink* TListOfFunctions::LastLink() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::LastLink();
}
Int_t TListOfFunctions::GetLast() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::GetLast();
}
Int_t TListOfFunctions::IndexOf(const TObject *obj) const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::IndexOf(obj);
}
Int_t TListOfFunctions::GetSize() const
{
R__LOCKGUARD(gInterpreterMutex);
return THashList::GetSize();
}
ClassImp(TListOfFunctionsIter)
TListOfFunctionsIter::TListOfFunctionsIter(const TListOfFunctions *l, Bool_t dir ):
TListIter(l,dir) {}
TObject *TListOfFunctionsIter::Next()
{
R__LOCKGUARD(gInterpreterMutex);
return TListIter::Next();
}