Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
Rtypes.h
Go to the documentation of this file.
1 /* @(#)root/base:$Id$ */
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2014, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_Rtypes
12 #define ROOT_Rtypes
13 
14 //////////////////////////////////////////////////////////////////////////
15 // //
16 // Rtypes //
17 // //
18 // Basic types used by ROOT; ClassDef macros. //
19 // //
20 //////////////////////////////////////////////////////////////////////////
21 
22 
23 #include "RtypesCore.h"
24 #include "DllImport.h"
25 
26 #include "snprintf.h" // part of stdio.h on systems that have it
27 #include "strlcpy.h" // part of string.h on systems that have it
28 
29 #include <atomic>
30 #include <stdio.h>
31 #include <string.h>
32 #include <typeinfo>
33 #include <type_traits>
34 
35 #ifndef __CLING__
36 // __attribute__ is not supported on Windows, but it is internally needed by Cling
37 // for autoloading and Clad rely on __attribute__((annotate("D")))
38 #if defined(R__WIN32)
39 #define __attribute__(unused)
40 #endif
41 #endif
42 
43 //---- forward declared class types --------------------------------------------
44 
45 class TClass;
46 class TBuffer;
47 class TDirectory;
48 class TMemberInspector;
49 class TObject;
50 class TNamed;
51 class TCollection;
52 class TFileMergeInfo;
53 class TString;
54 
55 //Moved from TSystem.
56 enum ESysConstants {
57  kMAXSIGNALS = 15,
58  kMAXPATHLEN = 8192,
59  kBUFFERSIZE = 8192,
60  kItimerResolution = 10 // interval-timer resolution in ms
61 };
62 
63 enum EColor { kWhite =0, kBlack =1, kGray=920,
64  kRed =632, kGreen =416, kBlue=600, kYellow=400, kMagenta=616, kCyan=432,
65  kOrange=800, kSpring=820, kTeal=840, kAzure =860, kViolet =880, kPink=900 };
66 
67 // There is several streamer concepts.
68 class TClassStreamer; // Streamer functor for a class
69 class TMemberStreamer; // Streamer functor for a data member
70 typedef void (*ClassStreamerFunc_t)(TBuffer&, void*); // Streamer function for a class
71 typedef void (*ClassConvStreamerFunc_t)(TBuffer&, void*, const TClass*); // Streamer function for a class with conversion.
72 typedef void (*MemberStreamerFunc_t)(TBuffer&, void*, Int_t); // Streamer function for a data member
73 
74 // This class is used to implement proxy around collection classes.
75 class TVirtualCollectionProxy;
76 
77 typedef void (*VoidFuncPtr_t)(); //pointer to void function
78 typedef TClass* (*DictFuncPtr_t)(); //pointer to dictionary function
79 // NOTE: the previous name must be changed.
80 
81 //--- bit manipulation ---------------------------------------------------------
82 
83 #define BIT(n) (1ULL << (n))
84 #define SETBIT(n,i) ((n) |= BIT(i))
85 #define CLRBIT(n,i) ((n) &= ~BIT(i))
86 #define TESTBIT(n,i) ((Bool_t)(((n) & BIT(i)) != 0))
87 
88 
89 //---- debug global ------------------------------------------------------------
90 
91 R__EXTERN Int_t gDebug;
92 
93 
94 //---- ClassDef macros ---------------------------------------------------------
95 
96 typedef void (*ShowMembersFunc_t)(const void *obj, TMemberInspector &R__insp, Bool_t isTransient);
97 class TVirtualIsAProxy;
98 typedef TClass *(*IsAGlobalFunc_t)(const TClass*, const void *obj);
99 
100 // TBuffer.h declares and implements the following 2 operators
101 template <class Tmpl> TBuffer &operator>>(TBuffer &buf, Tmpl *&obj);
102 template <class Tmpl> TBuffer &operator<<(TBuffer &buf, const Tmpl *obj);
103 
104 // This might get used if we implement setting a class version.
105 // template <class RootClass> Short_t GetClassVersion(RootClass *);
106 
107 namespace ROOT {
108 
109  class TGenericClassInfo;
110  typedef void *(*NewFunc_t)(void *);
111  typedef void *(*NewArrFunc_t)(Long_t size, void *arena);
112  typedef void (*DelFunc_t)(void *);
113  typedef void (*DelArrFunc_t)(void *);
114  typedef void (*DesFunc_t)(void *);
115  typedef void (*DirAutoAdd_t)(void *, TDirectory *);
116  typedef Long64_t (*MergeFunc_t)(void *, TCollection *, TFileMergeInfo *);
117  typedef void (*ResetAfterMergeFunc_t)(void *, TFileMergeInfo *);
118 
119  template <class RootClass> Short_t SetClassVersion(RootClass *);
120 
121  extern TClass *CreateClass(const char *cname, Version_t id,
122  const std::type_info &info, TVirtualIsAProxy *isa,
123  const char *dfil, const char *ifil,
124  Int_t dl, Int_t il);
125  extern void AddClass(const char *cname, Version_t id, const std::type_info &info,
126  DictFuncPtr_t dict, Int_t pragmabits);
127  extern void RemoveClass(const char *cname);
128  extern void ResetClassVersion(TClass*, const char*, Short_t);
129  extern void AddClassAlternate(const char *normName, const char *alternate);
130 
131  extern TNamed *RegisterClassTemplate(const char *name,
132  const char *file, Int_t line);
133 
134  extern void Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector&);
135 
136 #if 0
137  // This function is only implemented in the dictionary file.
138  // The parameter is 'only' for overloading resolution.
139  // Used to be a template <class T> TGenericClassInfo *GenerateInitInstance(const T*);
140  template <class T> TGenericClassInfo *GetClassInfo(const T* t) {
141  TGenericClassInfo *GenerateInitInstance(const T*);
142  return CreateInitInstance(t);
143  };
144 #endif
145 
146  namespace Internal {
147  class TInitBehavior {
148  // This class defines the interface for the class registration and
149  // the TClass creation. To modify the default behavior, one would
150  // inherit from this class and overload ROOT::DefineBehavior().
151  // See TQObject.h and table/inc/Ttypes.h for examples.
152  public:
153  virtual ~TInitBehavior() { }
154 
155  virtual void Register(const char *cname, Version_t id,
156  const std::type_info &info,
157  DictFuncPtr_t dict, Int_t pragmabits) const = 0;
158  virtual void Unregister(const char *classname) const = 0;
159  virtual TClass *CreateClass(const char *cname, Version_t id,
160  const std::type_info &info, TVirtualIsAProxy *isa,
161  const char *dfil, const char *ifil,
162  Int_t dl, Int_t il) const = 0;
163  };
164 
165  class TDefaultInitBehavior: public TInitBehavior {
166  public:
167  virtual void Register(const char *cname, Version_t id,
168  const std::type_info &info,
169  DictFuncPtr_t dict, Int_t pragmabits) const {
170  ROOT::AddClass(cname, id, info, dict, pragmabits);
171  }
172 
173  virtual void Unregister(const char *classname) const {
174  ROOT::RemoveClass(classname);
175  }
176 
177  virtual TClass *CreateClass(const char *cname, Version_t id,
178  const std::type_info &info, TVirtualIsAProxy *isa,
179  const char *dfil, const char *ifil,
180  Int_t dl, Int_t il) const {
181  return ROOT::CreateClass(cname, id, info, isa, dfil, ifil, dl, il);
182  }
183  };
184 
185  const TInitBehavior *DefineBehavior(void * /*parent_type*/,
186  void * /*actual_type*/);
187  } // namespace Internal
188 
189 } // namespace ROOT
190 
191 // The macros below use TGenericClassInfo and TInstrumentedIsAProxy, so let's
192 // ensure they are included.
193 #include "TGenericClassInfo.h"
194 
195 typedef std::atomic<TClass*> atomic_TClass_ptr;
196 
197 #include "TIsAProxy.h"
198 
199 namespace ROOT { namespace Internal {
200 
201 class TCDGIILIBase {
202 public:
203  // All implemented in TGenericClassInfo.cxx.
204  static void SetInstance(::ROOT::TGenericClassInfo& R__instance,
205  NewFunc_t, NewArrFunc_t, DelFunc_t, DelArrFunc_t, DesFunc_t);
206  static void SetName(const std::string& name, std::string& nameMember);
207  static void SetfgIsA(atomic_TClass_ptr& isA, TClass*(*dictfun)());
208 };
209 
210 template <typename T>
211 class ClassDefGenerateInitInstanceLocalInjector:
212  public TCDGIILIBase {
213  static atomic_TClass_ptr fgIsA;
214  static ::ROOT::TGenericClassInfo *fgGenericInfo;
215  public:
216  static void *New(void *p) { return p ? new(p) T : new T; };
217  static void *NewArray(Long_t nElements, void *p) {
218  return p ? new(p) T[nElements] : new T[nElements]; }
219  static void Delete(void *p) { delete ((T*)p); }
220  static void DeleteArray(void *p) { delete[] ((T*)p); }
221  static void Destruct(void *p) { ((T*)p)->~T(); }
222  static ::ROOT::TGenericClassInfo *GenerateInitInstanceLocal() {
223  static ::TVirtualIsAProxy* isa_proxy = new ::TInstrumentedIsAProxy<T>(0);
224  static ::ROOT::TGenericClassInfo
225  R__instance(T::Class_Name(), T::Class_Version(),
226  T::DeclFileName(), T::DeclFileLine(),
227  typeid(T), ::ROOT::Internal::DefineBehavior((T*)0, (T*)0),
228  &T::Dictionary, isa_proxy, 0, sizeof(T) );
229  SetInstance(R__instance, &New, &NewArray, &Delete, &DeleteArray, &Destruct);
230  return &R__instance;
231  }
232  // We need a reference to the template instance static member in a concrete function in order
233  // to force its instantiation (even before the function is actually run)
234  // Since we do have a reference to Dictionary (in T::Dictionary), using fgGenericInfo
235  // here will insure that it is initialized at process start or library load time.
236  static TClass *Dictionary() { fgIsA = fgGenericInfo->GetClass(); return fgIsA; }
237  static TClass *Class() { SetfgIsA(fgIsA, &Dictionary); return fgIsA; }
238  static const char* Name() {
239  static std::string gName;
240  if (gName.empty())
241  SetName(GetDemangledTypeName(typeid(T)), gName);
242  return gName.c_str();
243  }
244  };
245 
246  template<typename T>
247  atomic_TClass_ptr ClassDefGenerateInitInstanceLocalInjector<T>::fgIsA{};
248  template<typename T>
249  ::ROOT::TGenericClassInfo *ClassDefGenerateInitInstanceLocalInjector<T>::fgGenericInfo {
250  ClassDefGenerateInitInstanceLocalInjector<T>::GenerateInitInstanceLocal()
251  };
252 
253  template <typename T>
254  struct THashConsistencyHolder {
255  static Bool_t fgHashConsistency;
256  };
257 
258  template <typename T>
259  Bool_t THashConsistencyHolder<T>::fgHashConsistency;
260 
261  void DefaultStreamer(TBuffer &R__b, const TClass *cl, void *objpointer);
262  Bool_t HasConsistentHashMember(TClass &clRef);
263  Bool_t HasConsistentHashMember(const char *clName);
264 }} // namespace ROOT::Internal
265 
266 
267 // Common part of ClassDef definition.
268 // DeclFileLine() is not part of it since CINT uses that as trigger for
269 // the class comment string.
270 #define _ClassDefBase_(name, id, virtual_keyword, overrd) \
271 private: \
272  static_assert(std::is_integral<decltype(id)>::value, "ClassDef(Inline) macro: the specified class version number is not an integer."); \
273  virtual_keyword Bool_t CheckTObjectHashConsistency() const overrd \
274  { \
275  static std::atomic<UChar_t> recurseBlocker(0); \
276  if (R__likely(recurseBlocker >= 2)) { \
277  return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; \
278  } else if (recurseBlocker == 1) { \
279  return false; \
280  } else if (recurseBlocker++ == 0) { \
281  ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency = \
282  ::ROOT::Internal::HasConsistentHashMember(_QUOTE_(name)) || \
283  ::ROOT::Internal::HasConsistentHashMember(*IsA()); \
284  ++recurseBlocker; \
285  return ::ROOT::Internal::THashConsistencyHolder<decltype(*this)>::fgHashConsistency; \
286  } \
287  return false; /* unreacheable */ \
288  } \
289  \
290 public: \
291  static Version_t Class_Version() { return id; } \
292  virtual_keyword TClass *IsA() const overrd { return name::Class(); } \
293  virtual_keyword void ShowMembers(TMemberInspector &insp) const overrd \
294  { \
295  ::ROOT::Class_ShowMembers(name::Class(), this, insp); \
296  } \
297  void StreamerNVirtual(TBuffer &ClassDef_StreamerNVirtual_b) { name::Streamer(ClassDef_StreamerNVirtual_b); } \
298  static const char *DeclFileName() { return __FILE__; }
299 
300 #define _ClassDefOutline_(name,id, virtual_keyword, overrd) \
301  _ClassDefBase_(name,id, virtual_keyword, overrd) \
302 private: \
303  static atomic_TClass_ptr fgIsA; \
304 public: \
305  static int ImplFileLine(); \
306  static const char *ImplFileName(); \
307  static const char *Class_Name(); \
308  static TClass *Dictionary(); \
309  static TClass *Class(); \
310  virtual_keyword void Streamer(TBuffer&) overrd;
311 
312 #define _ClassDefInline_(name, id, virtual_keyword, overrd) \
313  _ClassDefBase_(name, id, virtual_keyword, overrd) public : static int ImplFileLine() { return -1; } \
314  static const char *ImplFileName() { return 0; } \
315  static const char *Class_Name() \
316  { \
317  return ::ROOT::Internal::ClassDefGenerateInitInstanceLocalInjector<name>::Name(); \
318  } \
319  static TClass *Dictionary() \
320  { \
321  return ::ROOT::Internal::ClassDefGenerateInitInstanceLocalInjector<name>::Dictionary(); \
322  } \
323  static TClass *Class() { return ::ROOT::Internal::ClassDefGenerateInitInstanceLocalInjector<name>::Class(); } \
324  virtual_keyword void Streamer(TBuffer &R__b) overrd { ::ROOT::Internal::DefaultStreamer(R__b, name::Class(), this); }
325 
326 #define ClassDef(name,id) \
327  _ClassDefOutline_(name,id,virtual,) \
328  static int DeclFileLine() { return __LINE__; }
329 
330 #define ClassDefOverride(name,id) \
331  _ClassDefOutline_(name,id,,override) \
332  static int DeclFileLine() { return __LINE__; }
333 
334 #define ClassDefNV(name,id) \
335  _ClassDefOutline_(name,id,,) \
336  static int DeclFileLine() { return __LINE__; }
337 
338 #define ClassDefInline(name,id) \
339  _ClassDefInline_(name,id,virtual,) \
340  static int DeclFileLine() { return __LINE__; }
341 
342 #define ClassDefInlineOverride(name,id) \
343  _ClassDefInline_(name,id,,override) \
344  static int DeclFileLine() { return __LINE__; }
345 
346 #define ClassDefInlineNV(name,id) \
347  _ClassDefInline_(name,id,,) \
348  static int DeclFileLine() { return __LINE__; }
349 
350 //#define _ClassDefInterp_(name,id) ClassDefInline(name,id)
351 
352 #define R__UseDummy(name) \
353  class _NAME2_(name,_c) { public: _NAME2_(name,_c)() { if (name) { } } }
354 
355 
356 #define ClassImpUnique(name,key) \
357  namespace ROOT { \
358  TGenericClassInfo *GenerateInitInstance(const name*); \
359  namespace { \
360  static int _R__UNIQUE_(_NAME2_(R__dummyint,key)) __attribute__((unused)) = \
361  GenerateInitInstance((name*)0x0)->SetImplFile(__FILE__, __LINE__); \
362  R__UseDummy(_R__UNIQUE_(_NAME2_(R__dummyint,key))); \
363  } \
364  }
365 #define ClassImp(name) ClassImpUnique(name,default)
366 
367 // Macro for Namespace
368 
369 #define NamespaceImpUnique(name,key) \
370  namespace name { \
371  namespace ROOT { \
372  ::ROOT::TGenericClassInfo *GenerateInitInstance(); \
373  namespace { \
374  static int _R__UNIQUE_(_NAME2_(R__dummyint,key)) = \
375  GenerateInitInstance()->SetImplFile(__FILE__, __LINE__); \
376  R__UseDummy(_R__UNIQUE_(_NAME2_(R__dummyint,key))); \
377  } \
378  } \
379  }
380 #define NamespaceImp(name) NamespaceImpUnique(name,default)
381 
382 //---- ClassDefT macros for templates with one template argument ---------------
383 // ClassDefT corresponds to ClassDef
384 // ClassDefT2 goes in the same header as ClassDefT but must be
385 // outside the class scope
386 // ClassImpT corresponds to ClassImp
387 
388 
389 // This ClassDefT is stricly redundant and is kept only for
390 // backward compatibility.
391 
392 #define ClassDefT(name,id) \
393  _ClassDefOutline_(name,id,virtual,) \
394  static int DeclFileLine() { return __LINE__; }
395 
396 #define ClassDefTNV(name,id) \
397  _ClassDefOutline_(name,id,virtual,) \
398  static int DeclFileLine() { return __LINE__; }
399 
400 
401 #define ClassDefT2(name,Tmpl)
402 
403 #define templateClassImpUnique(name, key) \
404  namespace ROOT { \
405  static TNamed * \
406  _R__UNIQUE_(_NAME2_(R__dummyholder, key)) = ::ROOT::RegisterClassTemplate(_QUOTE_(name), __FILE__, __LINE__); \
407  R__UseDummy(_R__UNIQUE_(_NAME2_(R__dummyholder, key))); \
408  }
409 #define templateClassImp(name) templateClassImpUnique(name,default)
410 
411 #define ClassImpT(name,Tmpl) templateClassImp(name)
412 
413 //---- ClassDefT macros for templates with two template arguments --------------
414 // ClassDef2T2 goes in the same header as ClassDefT but must be
415 // outside the class scope
416 // ClassImp2T corresponds to ClassImpT
417 
418 #define ClassDef2T2(name,Tmpl1,Tmpl2)
419 #define ClassImp2T(name,Tmpl1,Tmpl2) templateClassImp(name)
420 
421 
422 //---- ClassDefT macros for templates with three template arguments ------------
423 // ClassDef3T2 goes in the same header as ClassDefT but must be
424 // outside the class scope
425 // ClassImp3T corresponds to ClassImpT
426 
427 #define ClassDef3T2(name,Tmpl1,Tmpl2,Tmpl3)
428 #define ClassImp3T(name,Tmpl1,Tmpl2,Tmpl3) templateClassImp(name)
429 
430 
431 //---- Macro to set the class version of non instrumented classes --------------
432 
433 #define RootClassVersion(name,VersionNumber) \
434 namespace ROOT { \
435  TGenericClassInfo *GenerateInitInstance(const name*); \
436  static Short_t _R__UNIQUE_(R__dummyVersionNumber) = \
437  GenerateInitInstance((name*)0x0)->SetVersion(VersionNumber); \
438  R__UseDummy(_R__UNIQUE_(R__dummyVersionNumber)); \
439 }
440 
441 #define RootStreamer(name,STREAMER) \
442 namespace ROOT { \
443  TGenericClassInfo *GenerateInitInstance(const name*); \
444  static Short_t _R__UNIQUE_(R__dummyStreamer) = \
445  GenerateInitInstance((name*)0x0)->SetStreamer(STREAMER); \
446  R__UseDummy(_R__UNIQUE_(R__dummyStreamer)); \
447 }
448 
449 //---- Macro to load a library into the interpreter --------------
450 // Call as R__LOAD_LIBRARY(libEvent)
451 // This macro intentionally does not take string as argument, to
452 // prevent compilation errors with complex diagnostics due to
453 // TString BAD_DO_NOT_TRY = "lib";
454 // R__LOAD_LIBRARY(BAD_DO_NOT_TRY + "BAD_DO_NOT_TRY.so") // ERROR!
455 #ifdef __CLING__
456 # define _R_PragmaStr(x) _Pragma(#x)
457 # define R__LOAD_LIBRARY(LIBRARY) _R_PragmaStr(cling load ( #LIBRARY ))
458 # define R__ADD_INCLUDE_PATH(PATH) _R_PragmaStr(cling add_include_path ( #PATH ))
459 # define R__ADD_LIBRARY_PATH(PATH) _R_PragmaStr(cling add_library_path ( #PATH ))
460 #elif defined(R__WIN32)
461 # define _R_PragmaStr(x) __pragma(#x)
462 # define R__LOAD_LIBRARY(LIBRARY) _R_PragmaStr(comment(lib, #LIBRARY))
463 # define R__ADD_INCLUDE_PATH(PATH) _R_PragmaStr(comment(path, #PATH))
464 # define R__ADD_LIBRARY_PATH(PATH) _R_PragmaStr(comment(path, #PATH))
465 #else
466 // No way to inform linker though preprocessor :-(
467 // We could even inform the user:
468 /*
469 # define R__LOAD_LIBRARY(LIBRARY) \
470  _R_PragmaStr(message "Compiler cannot handle linking against " #LIBRARY \
471  ". Use -L and -l instead.")
472 */
473 # define R__LOAD_LIBRARY(LIBRARY)
474 # define R__ADD_INCLUDE_PATH(PATH)
475 # define R__ADD_LIBRARY_PATH(PATH)
476 #endif
477 
478 // Convenience macros to disable cling pointer check.
479 #ifdef __CLING__
480 # define R__CLING_PTRCHECK(ONOFF) __attribute__((annotate("__cling__ptrcheck(" #ONOFF ")")))
481 #else
482 # define R__CLING_PTRCHECK(ONOFF)
483 #endif
484 
485 // On Windows strtok_r does not exist: the function is called strtok_s.
486 inline char *R__STRTOK_R(char *str, const char *delim, char **saveptr)
487 {
488 #if defined(R__WIN32)
489  return strtok_s(str, delim, saveptr);
490 #else
491  return strtok_r(str, delim, saveptr);
492 #endif
493 }
494 
495 #endif