#include "Varargs.h"
#include "TQConnection.h"
#include "TROOT.h"
#include "TRefCnt.h"
#include "TClass.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "TInterpreter.h"
#include "Riostream.h"
#include "TVirtualMutex.h"
#include "THashTable.h"
ClassImpQ(TQConnection)
char *gTQSlotParams;
class TQSlot : public TObject, public TRefCnt {
protected:
CallFunc_t *fFunc;
ClassInfo_t *fClass;
TFunction *fMethod;
Long_t fOffset;
TString fName;
Int_t fExecuting;
public:
TQSlot(TClass *cl, const char *method, const char *funcname);
TQSlot(const char *class_name, const char *funcname);
virtual ~TQSlot();
const char *GetName() const { return fName.Data(); }
void ExecuteMethod(void *object);
void ExecuteMethod(void *object, Int_t nargs, va_list ap);
void ExecuteMethod(void *object, Long_t param);
void ExecuteMethod(void *object, Long64_t param);
void ExecuteMethod(void *object, Double_t param);
void ExecuteMethod(void *object, const char *params);
void ExecuteMethod(void *object, Long_t *paramArr, Int_t nparam = -1);
void Print(Option_t *opt= "") const;
void ls(Option_t *opt= "") const { Print(opt); }
Bool_t IsExecuting() const { return fExecuting > 0; }
};
TQSlot::TQSlot(TClass *cl, const char *method_name,
const char *funcname) : TObject(), TRefCnt()
{
fFunc = 0;
fClass = 0;
fOffset = 0;
fMethod = 0;
fName = "";
fExecuting = 0;
fName = method_name;
char *method = new char[strlen(method_name)+1];
if (method) strcpy(method, method_name);
char *proto;
char *tmp;
char *params = 0;
if ((proto = strchr(method,'('))) {
*proto++ = '\0';
if ((tmp = strrchr(proto,')'))) *tmp = '\0';
if ((params = strchr(proto,'='))) *params = ' ';
}
R__LOCKGUARD2(gCINTMutex);
fFunc = gCint->CallFunc_Factory();
if (cl) {
if (params) {
gCint->CallFunc_SetFunc(fFunc,cl->GetClassInfo(), method, params, &fOffset);
fMethod = cl->GetMethod(method, params);
} else {
gCint->CallFunc_SetFuncProto(fFunc,cl->GetClassInfo(), method, proto, &fOffset);
fMethod = cl->GetMethodWithPrototype(method, proto);
}
} else {
fClass = gCint->ClassInfo_Factory();
if (params) {
gCint->CallFunc_SetFunc(fFunc,fClass, (char*)funcname, params, &fOffset);
fMethod = gROOT->GetGlobalFunction(funcname, params, kTRUE);
} else {
gCint->CallFunc_SetFuncProto(fFunc,fClass, (char*)funcname, proto, &fOffset);
fMethod = gROOT->GetGlobalFunctionWithPrototype(funcname, proto, kTRUE);
}
}
delete [] method;
}
TQSlot::TQSlot(const char *class_name, const char *funcname) :
TObject(), TRefCnt()
{
fFunc = 0;
fClass = 0;
fOffset = 0;
fMethod = 0;
fName = funcname;
fExecuting = 0;
char *method = new char[strlen(funcname)+1];
if (method) strcpy(method, funcname);
char *proto;
char *tmp;
char *params = 0;
if ((proto = strchr(method,'('))) {
*proto++ = '\0';
if ((tmp = strrchr(proto,')'))) *tmp = '\0';
if ((params = strchr(proto,'='))) *params = ' ';
}
R__LOCKGUARD2(gCINTMutex);
fFunc = gCint->CallFunc_Factory();
fClass = gCint->ClassInfo_Factory();
TClass *cl = 0;
if (!class_name)
;
else {
gCint->ClassInfo_Init(fClass,class_name);
cl = TClass::GetClass(class_name);
}
if (params) {
gCint->CallFunc_SetFunc(fFunc,fClass, method, params, &fOffset);
if (cl)
fMethod = cl->GetMethod(method, params);
else
fMethod = gROOT->GetGlobalFunction(method, params, kTRUE);
} else {
gCint->CallFunc_SetFuncProto(fFunc,fClass, method, proto , &fOffset);
if (cl)
fMethod = cl->GetMethodWithPrototype(method, proto);
else
fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
}
delete [] method;
}
TQSlot::~TQSlot()
{
if (!fExecuting) {
gCint->CallFunc_Delete(fFunc);
gCint->ClassInfo_Delete(fClass);
}
}
inline void TQSlot::ExecuteMethod(void *object)
{
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
R__LOCKGUARD2(gCINTMutex);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, Int_t nargs, va_list ap)
{
if (!fMethod) {
Error("ExecuteMethod", "method %s not found,"
"\n(note: interpreted methods are not supported with varargs)",
fName.Data());
return;
}
if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
nargs > fMethod->GetNargs()) {
Error("ExecuteMethod", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
fMethod->GetNargs());
return;
}
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_ResetArg(fFunc);
if (nargs > 0) {
TIter next(fMethod->GetListOfMethodArgs());
TMethodArg *arg;
for (int i = 0; i < nargs; i++) {
arg = (TMethodArg*) next();
TString type = arg->GetFullTypeName();
TDataType *dt = gROOT->GetType(type);
if (dt)
type = dt->GetFullTypeName();
if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, void*));
else if (type == "bool")
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
else if (type == "char" || type == "unsigned char")
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
else if (type == "short" || type == "unsigned short")
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
else if (type == "int" || type == "unsigned int")
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
else if (type == "long" || type == "unsigned long")
gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, long));
else if (type == "long long")
gCint->CallFunc_SetArg(fFunc,(Long64_t) va_arg(ap, Long64_t));
else if (type == "unsigned long long")
gCint->CallFunc_SetArg(fFunc,(ULong64_t) va_arg(ap, ULong64_t));
else if (type == "float")
gCint->CallFunc_SetArg(fFunc,(Double_t) va_arg(ap, double));
else if (type == "double")
gCint->CallFunc_SetArg(fFunc,(Double_t) va_arg(ap, double));
}
}
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, Long_t param)
{
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_ResetArg(fFunc);
gCint->CallFunc_SetArg(fFunc,param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, Long64_t param)
{
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_ResetArg(fFunc);
gCint->CallFunc_SetArg(fFunc,param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, Double_t param)
{
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_ResetArg(fFunc);
gCint->CallFunc_SetArg(fFunc,param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, const char *param)
{
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gTQSlotParams = (char*)param;
gCint->CallFunc_SetArgs(fFunc,"gTQSlotParams");
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
inline void TQSlot::ExecuteMethod(void *object, Long_t *paramArr, Int_t nparam)
{
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_SetArgArray(fFunc,paramArr, nparam);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
gCint->CallFunc_Exec(fFunc,address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
gCint->CallFunc_Delete(fFunc);
}
void TQSlot::Print(Option_t *) const
{
cout <<IsA()->GetName() << "\t" << GetName() << "\t"
<< "Number of Connections = " << References() << endl;
}
class TQSlotPool {
private:
THashTable *fTable;
public:
TQSlotPool() { fTable = new THashTable(50); }
virtual ~TQSlotPool() { fTable->Clear("nodelete"); }
TQSlot *New(const char *class_name, const char *funcname);
TQSlot *New(TClass *cl, const char *method, const char *func);
void Free(TQSlot *slot);
};
TQSlot *TQSlotPool::New(const char *class_name, const char *funcname)
{
TString name = class_name;
name += "::";
name += funcname;
TQSlot *slot = (TQSlot*)fTable->FindObject(name.Data());
if (!slot) {
slot = new TQSlot(class_name, funcname);
fTable->Add(slot);
}
slot->AddReference();
return slot;
}
TQSlot *TQSlotPool::New(TClass *cl, const char *method, const char *func)
{
TString name;
if (cl) {
name = cl->GetName();
name += "::";
name += method;
} else {
name = "::";
name += func;
}
TQSlot *slot = (TQSlot*)fTable->FindObject(name.Data());
if (!slot) {
slot = new TQSlot(cl, method, func);
fTable->Add(slot);
}
slot->AddReference();
return slot;
}
void TQSlotPool::Free(TQSlot *slot)
{
slot->RemoveReference();
if (slot->References() <= 0) {
fTable->Remove(slot);
if (!slot->IsExecuting()) SafeDelete(slot);
}
}
static TQSlotPool gSlotPool;
TQConnection::TQConnection() : TList(), TQObject()
{
fReceiver = 0;
fSlot = 0;
}
TQConnection::TQConnection(TClass *cl, void *receiver, const char *method_name)
: TList(), TQObject()
{
const char *funcname = 0;
fReceiver = receiver;
if (!cl) {
funcname = gCint->Getp2f2funcname(fReceiver);
if (!funcname)
Warning("TQConnection", "%s cannot be compiled", method_name);
}
if (cl) fClassName = cl->GetName();
fSlot = gSlotPool.New(cl, method_name, funcname);
}
TQConnection::TQConnection(const char *class_name, void *receiver,
const char *funcname) : TList(), TQObject()
{
fClassName = class_name;
fSlot = gSlotPool.New(class_name, funcname);
fReceiver = receiver;
}
TQConnection::TQConnection(const TQConnection &con): TList(), TQObject()
{
fClassName = con.fClassName;
fSlot = con.fSlot;
fSlot->AddReference();
fReceiver = con.fReceiver;
}
TQConnection::~TQConnection()
{
TIter next(this);
register TList *list;
while ((list = (TList*)next())) {
list->Remove(this);
if (list->IsEmpty()) delete list;
}
Clear("nodelete");
if (!fSlot) return;
gSlotPool.Free(fSlot);
}
const char *TQConnection::GetName() const
{
return fSlot->GetName();
}
void TQConnection::Destroyed()
{
MakeZombie();
Emit("Destroyed()");
}
void TQConnection::ls(Option_t *option) const
{
cout << "\t" << IsA()->GetName() << "\t" << GetName() << endl;
((TQConnection*)this)->R__FOR_EACH(TList,ls)(option);
}
void TQConnection::PrintCollectionHeader(Option_t *) const
{
TROOT::IndentLevel();
cout << IsA()->GetName() << "\t" << fReceiver << "\t" << GetName() << endl;
}
void TQConnection::ExecuteMethod()
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(Int_t nargs, va_list va)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, nargs, va);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(Long_t param)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(Long64_t param)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(Double_t param)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(Long_t *params, Int_t nparam)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, params, nparam);
if (s->References() <= 0) delete s;
}
void TQConnection::ExecuteMethod(const char *param)
{
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}