Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TStorage.h
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Fons Rademakers 29/07/95
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 #ifndef ROOT_TStorage
13 #define ROOT_TStorage
14 
15 
16 //////////////////////////////////////////////////////////////////////////
17 // //
18 // TStorage //
19 // //
20 // Storage manager. //
21 // //
22 //////////////////////////////////////////////////////////////////////////
23 
24 #include "RConfigure.h"
25 #include "Rtypes.h"
26 
27 typedef void (*FreeHookFun_t)(void*, void *addr, size_t);
28 typedef void *(*ReAllocFun_t)(void*, size_t);
29 typedef void *(*ReAllocCFun_t)(void*, size_t, size_t);
30 typedef char *(*ReAllocCharFun_t)(char*, size_t, size_t);
31 
32 
33 class TStorage {
34 
35 private:
36  static size_t fgMaxBlockSize; // largest block allocated
37  static FreeHookFun_t fgFreeHook; // function called on free
38  static void *fgFreeHookData; // data used by this function
39  static ReAllocFun_t fgReAllocHook; // custom ReAlloc
40  static ReAllocCFun_t fgReAllocCHook; // custom ReAlloc with length check
41  static Bool_t fgHasCustomNewDelete; // true if using ROOT's new/delete
42 
43  //----- Private bits, clients can only test but not change them
44  enum {
45  kIsOnHeap = 0x01000000, ///< object is on heap
46  };
47 
48 public:
49  static const UInt_t kObjectAllocMemValue = 0x99999999;
50  // magic number for ObjectAlloc
51 
52 public:
53  virtual ~TStorage() { }
54 
55  static ULong_t GetHeapBegin();
56  static ULong_t GetHeapEnd();
57  static FreeHookFun_t GetFreeHook();
58  static void *GetFreeHookData();
59  static size_t GetMaxBlockSize();
60  static void *Alloc(size_t size);
61  static void Dealloc(void *ptr);
62  static void *ReAlloc(void *vp, size_t size);
63  static void *ReAlloc(void *vp, size_t size, size_t oldsize);
64  static char *ReAllocChar(char *vp, size_t size, size_t oldsize);
65  static Int_t *ReAllocInt(Int_t *vp, size_t size, size_t oldsize);
66  static void *ObjectAlloc(size_t size);
67  static void *ObjectAllocArray(size_t size);
68  static void *ObjectAlloc(size_t size, void *vp);
69  static void ObjectDealloc(void *vp);
70 #ifdef R__SIZEDDELETE
71  static void ObjectDealloc(void *vp, size_t size);
72 #endif
73  static void ObjectDealloc(void *vp, void *ptr);
74 
75  static void EnterStat(size_t size, void *p);
76  static void RemoveStat(void *p);
77  static void PrintStatistics();
78  static void SetMaxBlockSize(size_t size);
79  static void SetFreeHook(FreeHookFun_t func, void *data);
80  static void SetReAllocHooks(ReAllocFun_t func1, ReAllocCFun_t func2);
81  static void SetCustomNewDelete();
82  static void EnableStatistics(int size= -1, int ix= -1);
83 
84  static Bool_t HasCustomNewDelete();
85 
86  // only valid after call to a TStorage allocating method
87  static void AddToHeap(ULong_t begin, ULong_t end);
88  static Bool_t IsOnHeap(void *p);
89 
90  static Bool_t FilledByObjectAlloc(volatile const UInt_t* const member);
91  static void UpdateIsOnHeap(volatile const UInt_t &uniqueID, volatile UInt_t &bits);
92 
93  ClassDef(TStorage,0) //Storage manager class
94 };
95 
96 inline Bool_t TStorage::FilledByObjectAlloc(volatile const UInt_t *const member) {
97  //called by TObject's constructor to determine if object was created by call to new
98 
99  // This technique is necessary as there is one stack per thread
100  // and we can not rely on comparison with the current stack memory position.
101  // Note that a false positive (this routine returning true for an object
102  // created on the stack) requires the previous stack value to have been
103  // set to exactly kObjectAllocMemValue at exactly the right position (i.e.
104  // where this object's fUniqueID is located.
105  // The consequence of a false positive will be visible if and only if
106  // the object is auto-added to a TDirectory (i.e. TTree, TH*, TGraph,
107  // TEventList) or explicitly added to the directory by the user
108  // and
109  // the TDirectory (or TFile) object is created on the stack *before*
110  // the object.
111  // The consequence would be that those objects would be deleted twice, once
112  // by the TDirectory and once automatically when going out of scope
113  // (and thus quite visible). A false negative (which is not posible with
114  // this implementation) would have been a silent memory leak.
115 
116  // This will be reported by valgrind as uninitialized memory reads for
117  // object created on the stack, use $ROOTSYS/etc/valgrind-root.supp
118 R__INTENTIONALLY_UNINIT_BEGIN
119  return *member == kObjectAllocMemValue;
120 R__INTENTIONALLY_UNINIT_END
121 }
122 
123 // Assign the kIsOnHeap bit in 'bits' based on the pattern seen in uniqueID.
124 // See Storage::FilledByObjectAlloc for details.
125 // This routine is marked as inline with attribute noinline so that it never
126 // inlined and thus can be used in a valgrind suppression file to suppress
127 // the known/intentional uninitialized memory read but still be a 'quick'
128 // function call to avoid losing performance at object creation.
129 // Moving the function into the source file, results in doubling of the
130 // overhead (compared to inlining)
131 R__NEVER_INLINE void TStorage::UpdateIsOnHeap(volatile const UInt_t &uniqueID, volatile UInt_t &bits) {
132  if (TStorage::FilledByObjectAlloc(&uniqueID))
133  bits |= kIsOnHeap;
134  else
135  bits &= ~kIsOnHeap;
136 }
137 
138 
139 inline size_t TStorage::GetMaxBlockSize() { return fgMaxBlockSize; }
140 
141 inline void TStorage::SetMaxBlockSize(size_t size) { fgMaxBlockSize = size; }
142 
143 inline FreeHookFun_t TStorage::GetFreeHook() { return fgFreeHook; }
144 
145 namespace ROOT {
146 namespace Internal {
147 using FreeIfTMapFile_t = bool(void*);
148 R__EXTERN FreeIfTMapFile_t *gFreeIfTMapFile;
149 R__EXTERN void *gMmallocDesc;
150 }
151 }
152 
153 #endif