// @(#)root/base:$Name: $:$Id: TQConnection.cxx,v 1.20 2005/06/22 20:18:10 brun Exp $
// Author: Valeriy Onuchin & Fons Rademakers 15/10/2000
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TQConnection class is an internal class, used in the object //
// communication mechanism. //
// //
// TQConnection: //
// - is a list of signal_lists containing pointers //
// to this connection //
// - receiver is the object to which slot-method is applied //
// //
// This implementation is provided by //
// Valeriy Onuchin (onuchin@sirius.ihep.su). //
// //
//////////////////////////////////////////////////////////////////////////
#include "TQConnection.h"
#include "TRefCnt.h"
#include "TClass.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "Api.h"
#include "G__ci.h"
#include "Riostream.h"
#include "TVirtualMutex.h"
#include "THashTable.h"
#include "TCint.h"
ClassImpQ(TQConnection)
char *gTQSlotParams; // used to pass string parameter
//////////////////////////////////////////////////////////////////////////
// //
// TQSlot = slightly modified TMethodCall class //
// used in the object communication mechanism //
// //
//////////////////////////////////////////////////////////////////////////
class TQSlot : public TObject, public TRefCnt {
protected:
G__CallFunc *fFunc; // CINT method invocation environment
TFunction *fMethod; // slot method or global function
Long_t fOffset; // offset added to object pointer
TString fName; // full name of method
Int_t fExecuting; // true if one of this slot's ExecuteMethod methods is being called
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()
{
// Create the method invocation environment. Necessary input
// information: the class, full method name with prototype
// string of the form: method(char*,int,float).
// To initialize class method with default arguments, method
// string with default parameters should be of the form:
// method(=\"ABC\",1234,3.14) (!! parameter string should
// consists of '=').
// To execute the method call TQSlot::ExecuteMethod(object,...).
fFunc = 0;
fOffset = 0;
fMethod = 0;
fName = "";
fExecuting = 0;
// cl==0, is the case of interpreted function.
fName = method_name;
char *method = new char[strlen(method_name)+1];
if (method) strcpy(method, method_name);
char *proto;
char *tmp;
char *params = 0;
// separate method and protoype strings
if ((proto = strchr(method,'('))) {
// substitute first '(' symbol with '\0'
*proto++ = '\0';
// last ')' symbol with '\0'
if ((tmp = strrchr(proto,')'))) *tmp = '\0';
if ((params = strchr(proto,'='))) *params = ' ';
}
R__LOCKGUARD2(gCINTMutex);
fFunc = new G__CallFunc;
// initiate class method (function) with proto
// or with default params
if (cl) {
if (params) {
fFunc->SetFunc(cl->GetClassInfo(), method, params, &fOffset);
fMethod = cl->GetMethod(method, params);
} else {
fFunc->SetFuncProto(cl->GetClassInfo(), method, proto, &fOffset);
fMethod = cl->GetMethodWithPrototype(method, proto);
}
} else {
G__ClassInfo gcl;
if (params) {
fFunc->SetFunc(&gcl, (char*)funcname, params, &fOffset);
fMethod = gROOT->GetGlobalFunction(funcname, params, kTRUE);
} else {
fFunc->SetFuncProto(&gcl, (char*)funcname, proto, &fOffset);
fMethod = gROOT->GetGlobalFunctionWithPrototype(funcname, proto, kTRUE);
}
}
// cleaning
delete [] method;
}
//______________________________________________________________________________
TQSlot::TQSlot(const char *class_name, const char *funcname) :
TObject(), TRefCnt()
{
// Create the method invocation environment. Necessary input
// information: the name of class (could be interpreted class),
// full method name with prototype or parameter string
// of the form: method(char*,int,float).
// To initialize class method with default arguments, method
// string with default parameters should be of the form:
// method(=\"ABC\",1234,3.14) (!! parameter string should
// consists of '=').
// To execute the method call TQSlot::ExecuteMethod(object,...).
fFunc = 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;
// separate method and protoype strings
if ((proto = strchr(method,'('))) {
*proto++ = '\0';
if ((tmp = strrchr(proto,')'))) *tmp = '\0';
if ((params = strchr(proto,'='))) *params = ' ';
}
R__LOCKGUARD2(gCINTMutex);
fFunc = new G__CallFunc;
G__ClassInfo gcl;
TClass *cl = 0;
if (!class_name)
; // function
else {
gcl.Init(class_name); // class
cl = gROOT->GetClass(class_name);
}
if (params) {
fFunc->SetFunc(&gcl, method, params, &fOffset);
if (cl)
fMethod = cl->GetMethod(method, params);
else
fMethod = gROOT->GetGlobalFunction(method, params, kTRUE);
} else {
fFunc->SetFuncProto(&gcl, method, proto , &fOffset);
if (cl)
fMethod = cl->GetMethodWithPrototype(method, proto);
else
fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
}
delete [] method;
return;
}
//______________________________________________________________________________
TQSlot::~TQSlot()
{
// TQSlot dtor.
// don't delete executing environment of a slot that is being executed
if (!fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object)
{
// ExecuteMethod the method (with preset arguments) for
// the specified object.
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
R__LOCKGUARD2(gCINTMutex);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, Int_t nargs, va_list ap)
{
// ExecuteMethod the method for the specified object and
// with variable argument list.
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);
fFunc->ResetArg();
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))
fFunc->SetArg((Long_t) va_arg(ap, void*));
//fCallEnv->SetParam((Long_t) va_arg(ap, void*));
else if (type == "bool")
fFunc->SetArg((Long_t) va_arg(ap, int)); // bool is promoted to int
//fCallEnv->SetParam((Long_t) va_arg(ap, int)); // bool is promoted to int
else if (type == "char" || type == "unsigned char")
fFunc->SetArg((Long_t) va_arg(ap, int)); // char is promoted to int
//fCallEnv->SetParam((Long_t) va_arg(ap, int)); // char is promoted to int
else if (type == "short" || type == "unsigned short")
fFunc->SetArg((Long_t) va_arg(ap, int)); // short is promoted to int
//fCallEnv->SetParam((Long_t) va_arg(ap, int)); // short is promoted to int
else if (type == "int" || type == "unsigned int")
fFunc->SetArg((Long_t) va_arg(ap, int));
//fCallEnv->SetParam((Long_t) va_arg(ap, int));
else if (type == "long" || type == "unsigned long")
fFunc->SetArg((Long_t) va_arg(ap, long));
//fCallEnv->SetParam((Long_t) va_arg(ap, long));
else if (type == "long long")
fFunc->SetArg((Long64_t) va_arg(ap, Long64_t));
//fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
else if (type == "unsigned long long")
fFunc->SetArg((ULong64_t) va_arg(ap, ULong64_t));
//fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
else if (type == "float")
fFunc->SetArg((Double_t) va_arg(ap, double)); // float is promoted to double
//fCallEnv->SetParam((Double_t) va_arg(ap, double)); // float is promoted to double
else if (type == "double")
fFunc->SetArg((Double_t) va_arg(ap, double));
//fCallEnv->SetParam((Double_t) va_arg(ap, double));
}
}
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, Long_t param)
{
// ExecuteMethod the method for the specified object and
// with single argument value.
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
fFunc->ResetArg();
fFunc->SetArg(param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, Long64_t param)
{
// ExecuteMethod the method for the specified object and
// with single argument value.
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
fFunc->ResetArg();
fFunc->SetArg(param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, Double_t param)
{
// ExecuteMethod the method for the specified object and
// with single argument value.
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
fFunc->ResetArg();
fFunc->SetArg(param);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, const char *param)
{
// ExecuteMethod the method for the specified object and text param.
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
gTQSlotParams = (char*)param;
fFunc->SetArgs("gTQSlotParams");
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
inline void TQSlot::ExecuteMethod(void *object, Long_t *paramArr, Int_t nparam)
{
// ExecuteMethod the method for the specified object and with
// several argument values.
// ParamArr is an array containing the function argument values.
// If nparam = -1 then paramArr must contain values for all function
// arguments, otherwise Nargs-NargsOpt <= nparam <= Nargs, where
// Nargs is the number of all arguments and NargsOpt is the number
// of default arguments.
void *address = 0;
R__LOCKGUARD2(gCINTMutex);
fFunc->SetArgArray(paramArr, nparam);
if (object) address = (void*)((Long_t)object + fOffset);
fExecuting++;
fFunc->Exec(address);
fExecuting--;
if (!TestBit(kNotDeleted) && !fExecuting)
delete fFunc;
}
//______________________________________________________________________________
void TQSlot::Print(Option_t *) const
{
// Print info about slot.
cout <<IsA()->GetName() << "\t" << GetName() << "\t"
<< "Number of Connections = " << References() << endl;
}
////////////////////////////////////////////////////////////////////////////////
class TQSlotPool : public THashTable {
public:
TQSlotPool() : THashTable(50) { }
virtual ~TQSlotPool() { Delete(); }
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)
{
// Create new slot or return already existing one.
TString name = class_name;
name += "::";
name += funcname;
TQSlot *slot = (TQSlot*)FindObject(name.Data());
if (!slot) {
slot = new TQSlot(class_name, funcname);
Add(slot);
}
slot->AddReference();
return slot;
}
//______________________________________________________________________________
TQSlot *TQSlotPool::New(TClass *cl, const char *method, const char *func)
{
// Create new slot or return already existing one.
TString name;
if (cl) {
name = cl->GetName();
name += "::";
name += method;
} else {
name = "::";
name += func;
}
TQSlot *slot = (TQSlot*)FindObject(name.Data());
if (!slot) {
slot = new TQSlot(cl, method, func);
Add(slot);
}
slot->AddReference();
return slot;
}
//______________________________________________________________________________
void TQSlotPool::Free(TQSlot *slot)
{
// Delete slot if there is no reference to it.
slot->RemoveReference(); // decrease references to slot
if (slot->References() <= 0) {
Remove(slot);
if (!slot->IsExecuting()) SafeDelete(slot);
}
}
static TQSlotPool gSlotPool; // global pool of slots
////////////////////////////////////////////////////////////////////////////////
//______________________________________________________________________________
TQConnection::TQConnection() : TList(), TQObject()
{
// Default constructor.
fReceiver = 0;
fSlot = 0;
}
//______________________________________________________________________________
TQConnection::TQConnection(TClass *cl, void *receiver, const char *method_name)
: TList(), TQObject()
{
// TQConnection ctor.
// cl != 0 - connection to object == receiver of class == cl
// and method == method_name
// cl == 0 - connection to function with name == method_name
char *funcname = 0;
fReceiver = receiver; // fReceiver is pointer to receiver
if (!cl) {
funcname = G__p2f2funcname(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()
{
// TQConnection ctor.
// Creates connection to method of class specified by name,
// it could be interpreted class and with method == funcname.
fClassName = class_name;
fSlot = gSlotPool.New(class_name, funcname); // new slot-method
fReceiver = receiver; // fReceiver is pointer to receiver
}
//______________________________________________________________________________
TQConnection::TQConnection(const TQConnection &con): TList(), TQObject()
{
// Copy constructor. Ignore connections to this TQConnections
fClassName = con.fClassName;
fSlot = con.fSlot;
fSlot->AddReference();
fReceiver = con.fReceiver;
}
//______________________________________________________________________________
TQConnection::~TQConnection()
{
// TQConnection dtor.
// - remove this connection from all signal lists
// - we do not delete fSlot if it has other connections,
// TQSlot::fCounter > 0 .
TIter next(this);
register TList *list;
while ((list = (TList*)next())) {
list->Remove(this);
if (list->IsEmpty()) delete list; // delete empty list
}
Clear("nodelete");
if (!fSlot) return;
gSlotPool.Free(fSlot);
}
//______________________________________________________________________________
const char *TQConnection::GetName() const
{
// Returns name of connection (aka name of slot)
return fSlot->GetName();
}
//______________________________________________________________________________
void TQConnection::Destroyed()
{
// Signal Destroyed tells that connection is destroyed.
MakeZombie();
Emit("Destroyed()");
}
//______________________________________________________________________________
void TQConnection::ls(Option_t *option) const
{
// List TQConnection full method name and list all signals
// connected to this connection.
cout << "\t" << IsA()->GetName() << "\t" << GetName() << endl;
((TQConnection*)this)->ForEach(TList,ls)(option);
}
//______________________________________________________________________________
void TQConnection::Print(Option_t *) const
{
// Print TQConnection full method name and print all
// signals connected to this connection.
cout << "\t\t\t" << IsA()->GetName() << "\t" << fReceiver <<
"\t" << GetName() << endl;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod()
{
// Apply slot-method to the fReceiver object without arguments.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(Int_t nargs, va_list va)
{
// Apply slot-method to the fReceiver object with
// variable argument list.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, nargs, va);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(Long_t param)
{
// Apply slot-method to the fReceiver object with
// single argument value.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(Long64_t param)
{
// Apply slot-method to the fReceiver object with
// single argument value.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(Double_t param)
{
// Apply slot-method to the fReceiver object with
// single argument value.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(Long_t *params, Int_t nparam)
{
// Apply slot-method to the fReceiver object with variable
// number of argument values.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, params, nparam);
if (s->References() <= 0) delete s;
}
//______________________________________________________________________________
void TQConnection::ExecuteMethod(const char *param)
{
// Apply slot-method to the fReceiver object and
// with string parameter.
// This connection might be deleted in result of the method execution
// (for example in case of a Disconnect). Hence we do not assume
// the object is still valid on return.
TQSlot *s = fSlot;
fSlot->ExecuteMethod(fReceiver, param);
if (s->References() <= 0) delete s;
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.