Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TListOfFunctions.cxx
Go to the documentation of this file.
1 // @(#)root/cont
2 // Author: Philippe Canal Aug 2013
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TListOfFunctions
13 A collection of TFunction objects designed for fast access given a
14 DeclId_t and for keep track of TFunction that were described
15 unloaded function.
16 */
17 
18 #include "TListOfFunctions.h"
19 #include "TClass.h"
20 #include "TExMap.h"
21 #include "TFunction.h"
22 #include "TMethod.h"
23 #include "TInterpreter.h"
24 #include "TVirtualMutex.h"
25 
26 ClassImp(TListOfFunctions);
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// Constructor.
30 
31 TListOfFunctions::TListOfFunctions(TClass *cl) : fClass(cl),fIds(0),fUnloaded(0),fLastLoadMarker(0)
32 {
33  fIds = new TExMap;
34  fUnloaded = new THashList;
35 }
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Destructor.
39 
40 TListOfFunctions::~TListOfFunctions()
41 {
42  THashList::Delete();
43  delete fIds;
44  fUnloaded->Delete();
45  delete fUnloaded;
46 }
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Add pair<id, object> to the map of functions and their ids.
50 
51 void TListOfFunctions::MapObject(TObject *obj)
52 {
53  TFunction *f = dynamic_cast<TFunction*>(obj);
54  if (f) {
55  fIds->Add((Long64_t)f->GetDeclId(),(Long64_t)f);
56  }
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Add object at the beginning of the list.
61 
62 void TListOfFunctions::AddFirst(TObject *obj)
63 {
64  THashList::AddFirst(obj);
65  MapObject(obj);
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Add object at the beginning of the list and also store option.
70 /// Storing an option is useful when one wants to change the behaviour
71 /// of an object a little without having to create a complete new
72 /// copy of the object. This feature is used, for example, by the Draw()
73 /// method. It allows the same object to be drawn in different ways.
74 
75 void TListOfFunctions::AddFirst(TObject *obj, Option_t *opt)
76 {
77  THashList::AddFirst(obj,opt);
78  MapObject(obj);
79 }
80 
81 ////////////////////////////////////////////////////////////////////////////////
82 /// Add object at the end of the list.
83 
84 void TListOfFunctions::AddLast(TObject *obj)
85 {
86  THashList::AddLast(obj);
87  MapObject(obj);
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Add object at the end of the list and also store option.
92 /// Storing an option is useful when one wants to change the behaviour
93 /// of an object a little without having to create a complete new
94 /// copy of the object. This feature is used, for example, by the Draw()
95 /// method. It allows the same object to be drawn in different ways.
96 
97 void TListOfFunctions::AddLast(TObject *obj, Option_t *opt)
98 {
99  THashList::AddLast(obj, opt);
100  MapObject(obj);
101 }
102 
103 ////////////////////////////////////////////////////////////////////////////////
104 /// Insert object at location idx in the list.
105 
106 void TListOfFunctions::AddAt(TObject *obj, Int_t idx)
107 {
108  THashList::AddAt(obj, idx);
109  MapObject(obj);
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Insert object after object after in the list.
114 
115 void TListOfFunctions::AddAfter(const TObject *after, TObject *obj)
116 {
117  THashList::AddAfter(after, obj);
118  MapObject(obj);
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Insert object after object after in the list.
123 
124 void TListOfFunctions::AddAfter(TObjLink *after, TObject *obj)
125 {
126  THashList::AddAfter(after, obj);
127  MapObject(obj);
128 }
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Insert object before object before in the list.
132 
133 void TListOfFunctions::AddBefore(const TObject *before, TObject *obj)
134 {
135  THashList::AddBefore(before, obj);
136  MapObject(obj);
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Insert object before object before in the list.
141 
142 void TListOfFunctions::AddBefore(TObjLink *before, TObject *obj)
143 {
144  THashList::AddBefore(before, obj);
145  MapObject(obj);
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// Remove all objects from the list. Does not delete the objects unless
150 /// the THashList is the owner (set via SetOwner()).
151 
152 void TListOfFunctions::Clear(Option_t *option)
153 {
154  fUnloaded->Clear(option);
155  fIds->Clear();
156  THashList::Clear(option);
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Delete all TFunction object files.
161 
162 void TListOfFunctions::Delete(Option_t *option /* ="" */)
163 {
164  fUnloaded->Delete(option);
165  fIds->Clear();
166  THashList::Delete(option);
167 }
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Specialize FindObject to do search for the
171 /// a function just by name or create it if its not already in the list
172 
173 TObject *TListOfFunctions::FindObject(const char *name) const
174 {
175  R__LOCKGUARD(gInterpreterMutex);
176  TObject *result = THashList::FindObject(name);
177  if (!result) {
178 
179  TInterpreter::DeclId_t decl;
180  if (fClass) decl = gInterpreter->GetFunction(fClass->GetClassInfo(),name);
181  else decl = gInterpreter->GetFunction(0,name);
182  if (decl) result = const_cast<TListOfFunctions*>(this)->Get(decl);
183  }
184  return result;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Return the set of overloads for this name, collecting all available ones.
189 /// Can construct and insert new TFunction-s.
190 
191 TList* TListOfFunctions::GetListForObjectNonConst(const char* name)
192 {
193  R__LOCKGUARD(gInterpreterMutex);
194 
195  TList* overloads = (TList*)fOverloads.FindObject(name);
196  TExMap overloadsSet;
197  Bool_t wasEmpty = true;
198  if (!overloads) {
199  overloads = new TList();
200  overloads->SetName(name);
201  fOverloads.Add(overloads);
202  } else {
203  TIter iOverload(overloads);
204  while (TFunction* over = (TFunction*)iOverload()) {
205  wasEmpty = false;
206  overloadsSet.Add((Long64_t)(ULong64_t)over->GetDeclId(),
207  (Long64_t)(ULong64_t)over);
208  }
209  }
210 
211  // Update if needed.
212  std::vector<DeclId_t> overloadDecls;
213  ClassInfo_t* ci = fClass ? fClass->GetClassInfo() : 0;
214  gInterpreter->GetFunctionOverloads(ci, name, overloadDecls);
215  for (std::vector<DeclId_t>::const_iterator iD = overloadDecls.begin(),
216  eD = overloadDecls.end(); iD != eD; ++iD) {
217  TFunction* over = Get(*iD);
218  if (wasEmpty || !overloadsSet.GetValue((Long64_t)(ULong64_t)over->GetDeclId())) {
219  overloads->Add(over);
220  }
221  }
222 
223  return overloads;
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// Return the set of overloads for this name, collecting all available ones.
228 /// Can construct and insert new TFunction-s.
229 
230 TList* TListOfFunctions::GetListForObject(const char* name) const
231 {
232  return const_cast<TListOfFunctions*>(this)->GetListForObjectNonConst(name);
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Return the set of overloads for function obj, collecting all available ones.
237 /// Can construct and insert new TFunction-s.
238 
239 TList* TListOfFunctions::GetListForObject(const TObject* obj) const
240 {
241  if (!obj) return 0;
242  return const_cast<TListOfFunctions*>(this)
243  ->GetListForObjectNonConst(obj->GetName());
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// Return the TMethod or TFunction describing the function corresponding
248 /// to the Decl 'id'. Return NULL if not found.
249 
250 TFunction *TListOfFunctions::Find(DeclId_t id) const
251 {
252  if (!id) return 0;
253 
254  R__LOCKGUARD(gInterpreterMutex);
255  return (TFunction*)fIds->GetValue((Long64_t)id);
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////////
259 /// Return (after creating it if necessary) the TMethod or TFunction
260 /// describing the function corresponding to the Decl 'id'.
261 
262 TFunction *TListOfFunctions::Get(DeclId_t id)
263 {
264  if (!id) return 0;
265 
266  R__LOCKGUARD(gInterpreterMutex);
267  //need the Find and possible Add to be one atomic operation
268  TFunction *f = Find(id);
269  if (f) return f;
270 
271  if (fClass) {
272  if (!gInterpreter->ClassInfo_Contains(fClass->GetClassInfo(),id)) return 0;
273  } else {
274  if (!gInterpreter->ClassInfo_Contains(0,id)) return 0;
275  }
276 
277  MethodInfo_t *m = gInterpreter->MethodInfo_Factory(id);
278 
279  // Let's see if this is a reload ...
280  const char *name = gInterpreter->MethodInfo_Name(m);
281  if (const TList* bucketForMethod = fUnloaded->GetListForObject(name)) {
282  TString mangledName( gInterpreter->MethodInfo_GetMangledName(m) );
283  TIter next(bucketForMethod);
284  TFunction *uf;
285  while ((uf = (TFunction *) next())) {
286  if (uf->GetMangledName() == mangledName) {
287  // Reuse
288  fUnloaded->Remove(uf);
289 
290  uf->Update(m);
291  f = uf;
292  break;
293  }
294  }
295  }
296  if (!f) {
297  if (fClass) f = new TMethod(m, fClass);
298  else f = new TFunction(m);
299  }
300  // Calling 'just' THahList::Add would turn around and call
301  // TListOfFunctions::AddLast which should *also* do the fIds->Add.
302  THashList::AddLast(f);
303  fIds->Add((Long64_t)id,(Long64_t)f);
304 
305  return f;
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Remove a pair<id, object> from the map of functions and their ids.
310 
311 void TListOfFunctions::UnmapObject(TObject *obj)
312 {
313  TFunction *f = dynamic_cast<TFunction*>(obj);
314  if (f) {
315  fIds->Remove((Long64_t)f->GetDeclId());
316  }
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Remove object from this collection and recursively remove the object
321 /// from all other objects (and collections).
322 /// This function overrides TCollection::RecursiveRemove that calls
323 /// the Remove function. THashList::Remove cannot be called because
324 /// it uses the hash value of the hash table. This hash value
325 /// is not available anymore when RecursiveRemove is called from
326 /// the TObject destructor.
327 
328 void TListOfFunctions::RecursiveRemove(TObject *obj)
329 {
330  if (!obj) return;
331 
332  THashList::RecursiveRemove(obj);
333  fUnloaded->RecursiveRemove(obj);
334  UnmapObject(obj);
335 
336 }
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// Remove object from the list.
340 
341 TObject* TListOfFunctions::Remove(TObject *obj)
342 {
343  Bool_t found;
344 
345  found = THashList::Remove(obj);
346  if (!found) {
347  found = fUnloaded->Remove(obj);
348  }
349  UnmapObject(obj);
350  if (found) return obj;
351  else return 0;
352 }
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Remove object via its objlink from the list.
356 
357 TObject* TListOfFunctions::Remove(TObjLink *lnk)
358 {
359  if (!lnk) return 0;
360 
361  TObject *obj = lnk->GetObject();
362 
363  THashList::Remove(lnk);
364  fUnloaded->Remove(obj);
365 
366  UnmapObject(obj);
367  return obj;
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Load all the functions known to the interpreter for the scope 'fClass'
372 /// into this collection.
373 
374 void TListOfFunctions::Load()
375 {
376  if (fClass && fClass->GetClassInfo() == 0) return;
377 
378  R__LOCKGUARD(gInterpreterMutex);
379 
380  ULong64_t currentTransaction = gInterpreter->GetInterpreterStateMarker();
381  if (currentTransaction == fLastLoadMarker) {
382  return;
383  }
384  fLastLoadMarker = currentTransaction;
385 
386  ClassInfo_t *info;
387  if (fClass) info = fClass->GetClassInfo();
388  else info = gInterpreter->ClassInfo_Factory();
389 
390  MethodInfo_t *t = gInterpreter->MethodInfo_Factory(info);
391  while (gInterpreter->MethodInfo_Next(t)) {
392  if (gInterpreter->MethodInfo_IsValid(t)) {
393  TDictionary::DeclId_t mid = gInterpreter->GetDeclId(t);
394  // Get will check if there is already there or create a new one
395  // (or re-use a previously unloaded version).
396  Get(mid);
397  }
398  }
399  gInterpreter->MethodInfo_Delete(t);
400  if (!fClass) gInterpreter->ClassInfo_Delete(info);
401 }
402 
403 ////////////////////////////////////////////////////////////////////////////////
404 /// Mark 'all func' as being unloaded.
405 /// After the unload, the function can no longer be found directly,
406 /// until the decl can be found again in the interpreter (in which
407 /// the func object will be reused.
408 
409 void TListOfFunctions::Unload()
410 {
411  TObjLink *lnk = FirstLink();
412  while (lnk) {
413  TFunction *func = (TFunction*)lnk->GetObject();
414 
415  fIds->Remove((Long64_t)func->GetDeclId());
416  fUnloaded->Add(func);
417 
418  lnk = lnk->Next();
419  }
420 
421  THashList::Clear();
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Mark 'func' as being unloaded.
426 /// After the unload, the function can no longer be found directly,
427 /// until the decl can be found again in the interpreter (in which
428 /// the func object will be reused.
429 
430 void TListOfFunctions::Unload(TFunction *func)
431 {
432  if (THashList::Remove(func)) {
433  // We contains the object, let remove it from the other internal
434  // list and move it to the list of unloaded objects.
435 
436  fIds->Remove((Long64_t)func->GetDeclId());
437  fUnloaded->Add(func);
438  }
439 }
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 
443 TObject* TListOfFunctions::FindObject(const TObject* obj) const
444 {
445  R__LOCKGUARD(gInterpreterMutex);
446  return THashList::FindObject(obj);
447 }
448 
449 ////////////////////////////////////////////////////////////////////////////////
450 
451 TIterator* TListOfFunctions::MakeIterator(Bool_t dir ) const
452 {
453  R__LOCKGUARD(gInterpreterMutex);
454  return new TListOfFunctionsIter(this,dir);
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 
459 TObject* TListOfFunctions::At(Int_t idx) const
460 {
461  R__LOCKGUARD(gInterpreterMutex);
462  return THashList::At(idx);
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 
467 TObject* TListOfFunctions::After(const TObject *obj) const
468 {
469  R__LOCKGUARD(gInterpreterMutex);
470  return THashList::After(obj);
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 
475 TObject* TListOfFunctions::Before(const TObject *obj) const
476 {
477  R__LOCKGUARD(gInterpreterMutex);
478  return THashList::Before(obj);
479 }
480 
481 ////////////////////////////////////////////////////////////////////////////////
482 
483 TObject* TListOfFunctions::First() const
484 {
485  R__LOCKGUARD(gInterpreterMutex);
486  return THashList::First();
487 }
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 
491 TObjLink* TListOfFunctions::FirstLink() const
492 {
493  R__LOCKGUARD(gInterpreterMutex);
494  return THashList::FirstLink();
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 
499 TObject** TListOfFunctions::GetObjectRef(const TObject *obj) const
500 {
501  R__LOCKGUARD(gInterpreterMutex);
502  return THashList::GetObjectRef(obj);
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 
507 TObject* TListOfFunctions::Last() const
508 {
509  R__LOCKGUARD(gInterpreterMutex);
510  return THashList::Last();
511 }
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 
515 TObjLink* TListOfFunctions::LastLink() const
516 {
517  R__LOCKGUARD(gInterpreterMutex);
518  return THashList::LastLink();
519 }
520 
521 
522 ////////////////////////////////////////////////////////////////////////////////
523 
524 Int_t TListOfFunctions::GetLast() const
525 {
526  R__LOCKGUARD(gInterpreterMutex);
527  return THashList::GetLast();
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 
532 Int_t TListOfFunctions::IndexOf(const TObject *obj) const
533 {
534  R__LOCKGUARD(gInterpreterMutex);
535  return THashList::IndexOf(obj);
536 }
537 
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 
541 Int_t TListOfFunctions::GetSize() const
542 {
543  R__LOCKGUARD(gInterpreterMutex);
544  return THashList::GetSize();
545 }
546 
547 /** \class TListOfFunctionsIter
548 Iterator for TListOfFunctions.
549 */
550 
551 ClassImp(TListOfFunctionsIter);
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 
555 TListOfFunctionsIter::TListOfFunctionsIter(const TListOfFunctions *l, Bool_t dir ):
556  TListIter(l,dir) {}
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 
560 TObject *TListOfFunctionsIter::Next()
561 {
562  R__LOCKGUARD(gInterpreterMutex);
563  return TListIter::Next();
564 }
565