00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "Varargs.h"
00028 #include "TQConnection.h"
00029 #include "TROOT.h"
00030 #include "TRefCnt.h"
00031 #include "TClass.h"
00032 #include "TMethod.h"
00033 #include "TMethodArg.h"
00034 #include "TDataType.h"
00035 #include "TInterpreter.h"
00036 #include "Riostream.h"
00037 #include "TVirtualMutex.h"
00038 #include "THashTable.h"
00039
00040 ClassImpQ(TQConnection)
00041
00042 char *gTQSlotParams;
00043
00044
00045
00046
00047
00048
00049
00050
00051 class TQSlot : public TObject, public TRefCnt {
00052
00053 protected:
00054 CallFunc_t *fFunc;
00055 ClassInfo_t *fClass;
00056 TFunction *fMethod;
00057 Long_t fOffset;
00058 TString fName;
00059 Int_t fExecuting;
00060 public:
00061 TQSlot(TClass *cl, const char *method, const char *funcname);
00062 TQSlot(const char *class_name, const char *funcname);
00063 virtual ~TQSlot();
00064
00065 const char *GetName() const { return fName.Data(); }
00066
00067 void ExecuteMethod(void *object);
00068 void ExecuteMethod(void *object, Int_t nargs, va_list ap);
00069 void ExecuteMethod(void *object, Long_t param);
00070 void ExecuteMethod(void *object, Long64_t param);
00071 void ExecuteMethod(void *object, Double_t param);
00072 void ExecuteMethod(void *object, const char *params);
00073 void ExecuteMethod(void *object, Long_t *paramArr, Int_t nparam = -1);
00074 void Print(Option_t *opt= "") const;
00075 void ls(Option_t *opt= "") const { Print(opt); }
00076
00077 Bool_t IsExecuting() const { return fExecuting > 0; }
00078 };
00079
00080
00081
00082 TQSlot::TQSlot(TClass *cl, const char *method_name,
00083 const char *funcname) : TObject(), TRefCnt()
00084 {
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 fFunc = 0;
00095 fClass = 0;
00096 fOffset = 0;
00097 fMethod = 0;
00098 fName = "";
00099 fExecuting = 0;
00100
00101
00102
00103 fName = method_name;
00104
00105 char *method = new char[strlen(method_name)+1];
00106 if (method) strcpy(method, method_name);
00107
00108 char *proto;
00109 char *tmp;
00110 char *params = 0;
00111
00112
00113
00114 if ((proto = strchr(method,'('))) {
00115
00116
00117 *proto++ = '\0';
00118
00119
00120 if ((tmp = strrchr(proto,')'))) *tmp = '\0';
00121 if ((params = strchr(proto,'='))) *params = ' ';
00122 }
00123
00124 R__LOCKGUARD2(gCINTMutex);
00125 fFunc = gCint->CallFunc_Factory();
00126
00127
00128
00129
00130 if (cl) {
00131 if (params) {
00132 gCint->CallFunc_SetFunc(fFunc,cl->GetClassInfo(), method, params, &fOffset);
00133 fMethod = cl->GetMethod(method, params);
00134 } else {
00135 gCint->CallFunc_SetFuncProto(fFunc,cl->GetClassInfo(), method, proto, &fOffset);
00136 fMethod = cl->GetMethodWithPrototype(method, proto);
00137 }
00138 } else {
00139 fClass = gCint->ClassInfo_Factory();
00140 if (params) {
00141 gCint->CallFunc_SetFunc(fFunc,fClass, (char*)funcname, params, &fOffset);
00142 fMethod = gROOT->GetGlobalFunction(funcname, params, kTRUE);
00143 } else {
00144 gCint->CallFunc_SetFuncProto(fFunc,fClass, (char*)funcname, proto, &fOffset);
00145 fMethod = gROOT->GetGlobalFunctionWithPrototype(funcname, proto, kTRUE);
00146 }
00147 }
00148
00149
00150 delete [] method;
00151 }
00152
00153
00154 TQSlot::TQSlot(const char *class_name, const char *funcname) :
00155 TObject(), TRefCnt()
00156 {
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 fFunc = 0;
00168 fClass = 0;
00169 fOffset = 0;
00170 fMethod = 0;
00171 fName = funcname;
00172 fExecuting = 0;
00173
00174 char *method = new char[strlen(funcname)+1];
00175 if (method) strcpy(method, funcname);
00176
00177 char *proto;
00178 char *tmp;
00179 char *params = 0;
00180
00181
00182
00183 if ((proto = strchr(method,'('))) {
00184 *proto++ = '\0';
00185 if ((tmp = strrchr(proto,')'))) *tmp = '\0';
00186 if ((params = strchr(proto,'='))) *params = ' ';
00187 }
00188
00189 R__LOCKGUARD2(gCINTMutex);
00190 fFunc = gCint->CallFunc_Factory();
00191
00192 fClass = gCint->ClassInfo_Factory();
00193 TClass *cl = 0;
00194
00195 if (!class_name)
00196 ;
00197 else {
00198 gCint->ClassInfo_Init(fClass,class_name);
00199 cl = TClass::GetClass(class_name);
00200 }
00201
00202 if (params) {
00203 gCint->CallFunc_SetFunc(fFunc,fClass, method, params, &fOffset);
00204 if (cl)
00205 fMethod = cl->GetMethod(method, params);
00206 else
00207 fMethod = gROOT->GetGlobalFunction(method, params, kTRUE);
00208 } else {
00209 gCint->CallFunc_SetFuncProto(fFunc,fClass, method, proto , &fOffset);
00210 if (cl)
00211 fMethod = cl->GetMethodWithPrototype(method, proto);
00212 else
00213 fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
00214 }
00215
00216 delete [] method;
00217 }
00218
00219
00220 TQSlot::~TQSlot()
00221 {
00222
00223
00224
00225 if (!fExecuting) {
00226 gCint->CallFunc_Delete(fFunc);
00227 gCint->ClassInfo_Delete(fClass);
00228 }
00229 }
00230
00231
00232 inline void TQSlot::ExecuteMethod(void *object)
00233 {
00234
00235
00236
00237 void *address = 0;
00238 if (object) address = (void*)((Long_t)object + fOffset);
00239 R__LOCKGUARD2(gCINTMutex);
00240 fExecuting++;
00241 gCint->CallFunc_Exec(fFunc,address);
00242 fExecuting--;
00243 if (!TestBit(kNotDeleted) && !fExecuting)
00244 gCint->CallFunc_Delete(fFunc);
00245 }
00246
00247
00248 inline void TQSlot::ExecuteMethod(void *object, Int_t nargs, va_list ap)
00249 {
00250
00251
00252
00253 if (!fMethod) {
00254 Error("ExecuteMethod", "method %s not found,"
00255 "\n(note: interpreted methods are not supported with varargs)",
00256 fName.Data());
00257 return;
00258 }
00259
00260 if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
00261 nargs > fMethod->GetNargs()) {
00262 Error("ExecuteMethod", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
00263 nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
00264 fMethod->GetNargs());
00265 return;
00266 }
00267
00268 void *address = 0;
00269 R__LOCKGUARD2(gCINTMutex);
00270
00271 gCint->CallFunc_ResetArg(fFunc);
00272
00273 if (nargs > 0) {
00274 TIter next(fMethod->GetListOfMethodArgs());
00275 TMethodArg *arg;
00276
00277 for (int i = 0; i < nargs; i++) {
00278 arg = (TMethodArg*) next();
00279 TString type = arg->GetFullTypeName();
00280 TDataType *dt = gROOT->GetType(type);
00281 if (dt)
00282 type = dt->GetFullTypeName();
00283 if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
00284 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, void*));
00285
00286 else if (type == "bool")
00287 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
00288
00289 else if (type == "char" || type == "unsigned char")
00290 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
00291
00292 else if (type == "short" || type == "unsigned short")
00293 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
00294
00295 else if (type == "int" || type == "unsigned int")
00296 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, int));
00297
00298 else if (type == "long" || type == "unsigned long")
00299 gCint->CallFunc_SetArg(fFunc,(Long_t) va_arg(ap, long));
00300
00301 else if (type == "long long")
00302 gCint->CallFunc_SetArg(fFunc,(Long64_t) va_arg(ap, Long64_t));
00303
00304 else if (type == "unsigned long long")
00305 gCint->CallFunc_SetArg(fFunc,(ULong64_t) va_arg(ap, ULong64_t));
00306
00307 else if (type == "float")
00308 gCint->CallFunc_SetArg(fFunc,(Double_t) va_arg(ap, double));
00309
00310 else if (type == "double")
00311 gCint->CallFunc_SetArg(fFunc,(Double_t) va_arg(ap, double));
00312
00313 }
00314 }
00315
00316 if (object) address = (void*)((Long_t)object + fOffset);
00317 fExecuting++;
00318 gCint->CallFunc_Exec(fFunc,address);
00319 fExecuting--;
00320 if (!TestBit(kNotDeleted) && !fExecuting)
00321 gCint->CallFunc_Delete(fFunc);
00322 }
00323
00324
00325 inline void TQSlot::ExecuteMethod(void *object, Long_t param)
00326 {
00327
00328
00329
00330 void *address = 0;
00331 R__LOCKGUARD2(gCINTMutex);
00332 gCint->CallFunc_ResetArg(fFunc);
00333 gCint->CallFunc_SetArg(fFunc,param);
00334 if (object) address = (void*)((Long_t)object + fOffset);
00335 fExecuting++;
00336 gCint->CallFunc_Exec(fFunc,address);
00337 fExecuting--;
00338 if (!TestBit(kNotDeleted) && !fExecuting)
00339 gCint->CallFunc_Delete(fFunc);
00340 }
00341
00342
00343 inline void TQSlot::ExecuteMethod(void *object, Long64_t param)
00344 {
00345
00346
00347
00348 void *address = 0;
00349 R__LOCKGUARD2(gCINTMutex);
00350 gCint->CallFunc_ResetArg(fFunc);
00351 gCint->CallFunc_SetArg(fFunc,param);
00352 if (object) address = (void*)((Long_t)object + fOffset);
00353 fExecuting++;
00354 gCint->CallFunc_Exec(fFunc,address);
00355 fExecuting--;
00356 if (!TestBit(kNotDeleted) && !fExecuting)
00357 gCint->CallFunc_Delete(fFunc);
00358 }
00359
00360
00361 inline void TQSlot::ExecuteMethod(void *object, Double_t param)
00362 {
00363
00364
00365
00366 void *address = 0;
00367 R__LOCKGUARD2(gCINTMutex);
00368 gCint->CallFunc_ResetArg(fFunc);
00369 gCint->CallFunc_SetArg(fFunc,param);
00370 if (object) address = (void*)((Long_t)object + fOffset);
00371 fExecuting++;
00372 gCint->CallFunc_Exec(fFunc,address);
00373 fExecuting--;
00374 if (!TestBit(kNotDeleted) && !fExecuting)
00375 gCint->CallFunc_Delete(fFunc);
00376 }
00377
00378
00379 inline void TQSlot::ExecuteMethod(void *object, const char *param)
00380 {
00381
00382
00383 void *address = 0;
00384 R__LOCKGUARD2(gCINTMutex);
00385 gTQSlotParams = (char*)param;
00386 gCint->CallFunc_SetArgs(fFunc,"gTQSlotParams");
00387 if (object) address = (void*)((Long_t)object + fOffset);
00388 fExecuting++;
00389 gCint->CallFunc_Exec(fFunc,address);
00390 fExecuting--;
00391 if (!TestBit(kNotDeleted) && !fExecuting)
00392 gCint->CallFunc_Delete(fFunc);
00393 }
00394
00395
00396 inline void TQSlot::ExecuteMethod(void *object, Long_t *paramArr, Int_t nparam)
00397 {
00398
00399
00400
00401
00402
00403
00404
00405
00406 void *address = 0;
00407 R__LOCKGUARD2(gCINTMutex);
00408 gCint->CallFunc_SetArgArray(fFunc,paramArr, nparam);
00409 if (object) address = (void*)((Long_t)object + fOffset);
00410 fExecuting++;
00411 gCint->CallFunc_Exec(fFunc,address);
00412 fExecuting--;
00413 if (!TestBit(kNotDeleted) && !fExecuting)
00414 gCint->CallFunc_Delete(fFunc);
00415 }
00416
00417
00418 void TQSlot::Print(Option_t *) const
00419 {
00420
00421
00422 cout <<IsA()->GetName() << "\t" << GetName() << "\t"
00423 << "Number of Connections = " << References() << endl;
00424 }
00425
00426
00427
00428 class TQSlotPool {
00429 private:
00430 THashTable *fTable;
00431 public:
00432 TQSlotPool() { fTable = new THashTable(50); }
00433 virtual ~TQSlotPool() { fTable->Clear("nodelete"); }
00434
00435 TQSlot *New(const char *class_name, const char *funcname);
00436 TQSlot *New(TClass *cl, const char *method, const char *func);
00437 void Free(TQSlot *slot);
00438 };
00439
00440
00441 TQSlot *TQSlotPool::New(const char *class_name, const char *funcname)
00442 {
00443
00444
00445 TString name = class_name;
00446 name += "::";
00447 name += funcname;
00448
00449 TQSlot *slot = (TQSlot*)fTable->FindObject(name.Data());
00450
00451 if (!slot) {
00452 slot = new TQSlot(class_name, funcname);
00453 fTable->Add(slot);
00454 }
00455 slot->AddReference();
00456 return slot;
00457 }
00458
00459
00460 TQSlot *TQSlotPool::New(TClass *cl, const char *method, const char *func)
00461 {
00462
00463
00464 TString name;
00465
00466 if (cl) {
00467 name = cl->GetName();
00468 name += "::";
00469 name += method;
00470 } else {
00471 name = "::";
00472 name += func;
00473 }
00474
00475 TQSlot *slot = (TQSlot*)fTable->FindObject(name.Data());
00476
00477 if (!slot) {
00478 slot = new TQSlot(cl, method, func);
00479 fTable->Add(slot);
00480 }
00481 slot->AddReference();
00482 return slot;
00483 }
00484
00485
00486 void TQSlotPool::Free(TQSlot *slot)
00487 {
00488
00489
00490 slot->RemoveReference();
00491
00492 if (slot->References() <= 0) {
00493 fTable->Remove(slot);
00494 if (!slot->IsExecuting()) SafeDelete(slot);
00495 }
00496 }
00497
00498 static TQSlotPool gSlotPool;
00499
00500
00501
00502
00503 TQConnection::TQConnection() : TList(), TQObject()
00504 {
00505
00506
00507 fReceiver = 0;
00508 fSlot = 0;
00509 }
00510
00511
00512 TQConnection::TQConnection(TClass *cl, void *receiver, const char *method_name)
00513 : TList(), TQObject()
00514 {
00515
00516
00517
00518
00519
00520 const char *funcname = 0;
00521 fReceiver = receiver;
00522
00523 if (!cl) {
00524 funcname = gCint->Getp2f2funcname(fReceiver);
00525 if (!funcname)
00526 Warning("TQConnection", "%s cannot be compiled", method_name);
00527 }
00528
00529 if (cl) fClassName = cl->GetName();
00530 fSlot = gSlotPool.New(cl, method_name, funcname);
00531 }
00532
00533
00534 TQConnection::TQConnection(const char *class_name, void *receiver,
00535 const char *funcname) : TList(), TQObject()
00536 {
00537
00538
00539
00540
00541 fClassName = class_name;
00542 fSlot = gSlotPool.New(class_name, funcname);
00543 fReceiver = receiver;
00544 }
00545
00546
00547 TQConnection::TQConnection(const TQConnection &con): TList(), TQObject()
00548 {
00549
00550
00551 fClassName = con.fClassName;
00552 fSlot = con.fSlot;
00553 fSlot->AddReference();
00554 fReceiver = con.fReceiver;
00555 }
00556
00557
00558 TQConnection::~TQConnection()
00559 {
00560
00561
00562
00563
00564
00565 TIter next(this);
00566 register TList *list;
00567
00568 while ((list = (TList*)next())) {
00569 list->Remove(this);
00570 if (list->IsEmpty()) delete list;
00571 }
00572 Clear("nodelete");
00573
00574 if (!fSlot) return;
00575 gSlotPool.Free(fSlot);
00576 }
00577
00578
00579 const char *TQConnection::GetName() const
00580 {
00581
00582
00583 return fSlot->GetName();
00584 }
00585
00586
00587 void TQConnection::Destroyed()
00588 {
00589
00590
00591 MakeZombie();
00592 Emit("Destroyed()");
00593 }
00594
00595
00596 void TQConnection::ls(Option_t *option) const
00597 {
00598
00599
00600
00601 cout << "\t" << IsA()->GetName() << "\t" << GetName() << endl;
00602 ((TQConnection*)this)->R__FOR_EACH(TList,ls)(option);
00603 }
00604
00605
00606 void TQConnection::PrintCollectionHeader(Option_t *) const
00607 {
00608
00609
00610
00611 TROOT::IndentLevel();
00612 cout << IsA()->GetName() << "\t" << fReceiver << "\t" << GetName() << endl;
00613 }
00614
00615
00616 void TQConnection::ExecuteMethod()
00617 {
00618
00619
00620
00621
00622
00623 TQSlot *s = fSlot;
00624 fSlot->ExecuteMethod(fReceiver);
00625 if (s->References() <= 0) delete s;
00626 }
00627
00628
00629 void TQConnection::ExecuteMethod(Int_t nargs, va_list va)
00630 {
00631
00632
00633
00634
00635
00636
00637 TQSlot *s = fSlot;
00638 fSlot->ExecuteMethod(fReceiver, nargs, va);
00639 if (s->References() <= 0) delete s;
00640 }
00641
00642
00643 void TQConnection::ExecuteMethod(Long_t param)
00644 {
00645
00646
00647
00648
00649
00650
00651 TQSlot *s = fSlot;
00652 fSlot->ExecuteMethod(fReceiver, param);
00653 if (s->References() <= 0) delete s;
00654 }
00655
00656
00657 void TQConnection::ExecuteMethod(Long64_t param)
00658 {
00659
00660
00661
00662
00663
00664
00665 TQSlot *s = fSlot;
00666 fSlot->ExecuteMethod(fReceiver, param);
00667 if (s->References() <= 0) delete s;
00668 }
00669
00670
00671 void TQConnection::ExecuteMethod(Double_t param)
00672 {
00673
00674
00675
00676
00677
00678
00679 TQSlot *s = fSlot;
00680 fSlot->ExecuteMethod(fReceiver, param);
00681 if (s->References() <= 0) delete s;
00682 }
00683
00684
00685 void TQConnection::ExecuteMethod(Long_t *params, Int_t nparam)
00686 {
00687
00688
00689
00690
00691
00692
00693 TQSlot *s = fSlot;
00694 fSlot->ExecuteMethod(fReceiver, params, nparam);
00695 if (s->References() <= 0) delete s;
00696 }
00697
00698
00699 void TQConnection::ExecuteMethod(const char *param)
00700 {
00701
00702
00703
00704
00705
00706
00707 TQSlot *s = fSlot;
00708 fSlot->ExecuteMethod(fReceiver, param);
00709 if (s->References() <= 0) delete s;
00710 }