ROOT  6.06/09
Reference Guide
TBuffer.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id: 6da0b5b613bbcfaa3a5cd4074e7b2be2448dfb31 $
2 // Author: Fons Rademakers 04/05/96
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 /** \class TBuffer
13 Buffer base class used for serializing objects.
14 */
15 
16 #include "TBuffer.h"
17 #include "TClass.h"
18 #include "TProcessID.h"
19 
20 const Int_t kExtraSpace = 8; // extra space at end of buffer (used for free block count)
21 
23 
24 ////////////////////////////////////////////////////////////////////////////////
25 /// The user has provided memory than we don't own, thus we can not extent it
26 /// either.
27 
28 static char *R__NoReAllocChar(char *, size_t, size_t)
29 {
30  return 0;
31 }
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 /// Create an I/O buffer object. Mode should be either TBuffer::kRead or
35 /// TBuffer::kWrite. By default the I/O buffer has a size of
36 /// TBuffer::kInitialSize (1024) bytes.
37 
39 {
41  fMode = mode;
42  fVersion = 0;
43  fParent = 0;
44 
46 
47  fBuffer = new char[fBufSize+kExtraSpace];
48 
49  fBufCur = fBuffer;
51 
52  SetReAllocFunc( 0 );
53 }
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Create an I/O buffer object. Mode should be either TBuffer::kRead or
57 /// TBuffer::kWrite.
58 
60 {
61  if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
62  fBufSize = bufsiz;
63  fMode = mode;
64  fVersion = 0;
65  fParent = 0;
66 
68 
69  fBuffer = new char[fBufSize+kExtraSpace];
70 
71  fBufCur = fBuffer;
73 
74  SetReAllocFunc( 0 );
75 }
76 
77 ////////////////////////////////////////////////////////////////////////////////
78 /// Create an I/O buffer object. Mode should be either TBuffer::kRead or
79 /// TBuffer::kWrite. By default the I/O buffer has a size of
80 /// TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
81 /// to TBuffer via the buf argument. By default this buffer will be adopted
82 /// unless adopt is false.
83 ///
84 /// If the new buffer is _not_ adopted and no memory allocation routine
85 /// is provided, a Fatal error will be issued if the Buffer attempts to
86 /// expand.
87 
88 TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
89 {
90  fBufSize = bufsiz;
91  fMode = mode;
92  fVersion = 0;
93  fParent = 0;
94 
96 
97  if (buf) {
98  fBuffer = (char *)buf;
99  if ( (fMode&kWrite)!=0 ) {
101  }
102  if (!adopt) ResetBit(kIsOwner);
103  } else {
104  if (fBufSize < kMinimalSize) {
106  }
107  fBuffer = new char[fBufSize+kExtraSpace];
108  }
109  fBufCur = fBuffer;
111 
112  SetReAllocFunc( reallocfunc );
113 
114  if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
115  Expand( kMinimalSize );
116  }
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Delete an I/O buffer object.
121 
123 {
124  if (TestBit(kIsOwner)) {
125  //printf("Deleting fBuffer=%lx\n", fBuffer);
126  delete [] fBuffer;
127  }
128  fBuffer = 0;
129  fParent = 0;
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Automatically calculate a new size and expand the buffer to fit at least size_needed.
134 /// The goals is to minimize the number of memory allocation and the memory allocation
135 /// which avoiding too much memory wastage.
136 ///
137 /// If the size_needed is larger than the current size, the policy
138 /// is to expand to double the current size or the size_needed which ever is largest.
139 
140 void TBuffer::AutoExpand(Int_t size_needed)
141 {
142  if (size_needed > fBufSize) {
143  if (size_needed > 2*fBufSize) {
144  Expand(size_needed);
145  } else {
146  Expand(2*fBufSize);
147  }
148  }
149 }
150 
151 ////////////////////////////////////////////////////////////////////////////////
152 /// Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
153 /// new buffer is expected to have the same size as the previous buffer.
154 /// The current buffer position is reset to the start of the buffer.
155 /// If the TBuffer owned the previous buffer, it will be deleted prior
156 /// to accepting the new buffer. By default the new buffer will be
157 /// adopted unless adopt is false.
158 ///
159 /// If the new buffer is _not_ adopted and no memory allocation routine
160 /// is provided, a Fatal error will be issued if the Buffer attempts to
161 /// expand.
162 
163 void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
164 {
165  if (fBuffer && TestBit(kIsOwner))
166  delete [] fBuffer;
167 
168  if (adopt)
169  SetBit(kIsOwner);
170  else
172 
173  fBuffer = (char *)buf;
174  fBufCur = fBuffer;
175  if (newsiz > 0) {
176  if ( (fMode&kWrite)!=0 ) {
177  fBufSize = newsiz - kExtraSpace;
178  } else {
179  fBufSize = newsiz;
180  }
181  }
183 
184  SetReAllocFunc( reallocfunc );
185 
186  if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
187  Expand( kMinimalSize );
188  }
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 /// Expand (or shrink) the I/O buffer to newsize bytes.
193 /// If copy is true (the default), the existing content of the
194 /// buffer is preserved, otherwise the buffer is returned zero-ed out.
195 ///
196 /// In order to avoid losing data, if the current length is greater than
197 /// the requested size, we only shrink down to the current length.
198 
199 void TBuffer::Expand(Int_t newsize, Bool_t copy)
200 {
201  Int_t l = Length();
202  if ( (l > newsize) && copy ) {
203  newsize = l;
204  }
205  if ( (fMode&kWrite)!=0 ) {
207  copy ? fBufSize+kExtraSpace : 0);
208  } else {
209  fBuffer = fReAllocFunc(fBuffer, newsize,
210  copy ? fBufSize : 0);
211  }
212  if (fBuffer == 0) {
214  Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
215  } if (fReAllocFunc == R__NoReAllocChar) {
216  Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
217  } else {
218  Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", (Long_t)fReAllocFunc);
219  }
220  }
221  fBufSize = newsize;
222  fBufCur = fBuffer + l;
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// Return pointer to parent of this buffer.
228 
230 {
231  return fParent;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Set parent owning this buffer.
236 
238 {
239  fParent = parent;
240 }
241 ////////////////////////////////////////////////////////////////////////////////
242 /// Return the reallocation method currently used.
243 
245 {
246  return fReAllocFunc;
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Set which memory reallocation method to use. If reallocafunc is null,
251 /// reset it to the default value (TStorage::ReAlloc)
252 
254 {
255  if (reallocfunc) {
256  fReAllocFunc = reallocfunc;
257  } else {
258  if (TestBit(kIsOwner)) {
260  } else {
261  fReAllocFunc = R__NoReAllocChar;
262  }
263  }
264 }
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 /// Set buffer in read mode.
268 
270 {
271  if ( (fMode&kWrite)!=0 ) {
272  // We had reserved space for the free block count,
273  // release it,
275  }
276  fMode = kRead;
277 }
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 /// Set buffer in write mode.
281 
283 {
284  if ( (fMode&kWrite)==0 ) {
285  // We had not yet reserved space for the free block count,
286  // reserve it now.
288  }
289  fMode = kWrite;
290 }
291 
292 ////////////////////////////////////////////////////////////////////////////////
293 /// Forward to TROOT::GetClass().
294 
295 TClass *TBuffer::GetClass(const type_info &typeinfo)
296 {
297  return TClass::GetClass(typeinfo);
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Forward to TROOT::GetClass().
302 
303 TClass *TBuffer::GetClass(const char *className)
304 {
305  return TClass::GetClass(className);
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Return the current Process-ID.
310 
312 {
313  if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
314  return 0;
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// Always return 0 (current processID).
319 
321 {
322  return 0;
323 }
324 
325 ////////////////////////////////////////////////////////////////////////////////
326 /// Push a new data cache area onto the list of area to be used for
327 /// temporarily store 'missing' data members.
328 
330 {
331  fCacheStack.push_back(obj);
332 }
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 /// Return the 'current' data cache area from the list of area to be used for
336 /// temporarily store 'missing' data members.
337 
339 {
340  if (fCacheStack.empty()) return 0;
341  return fCacheStack.back();
342 }
343 
344 ////////////////////////////////////////////////////////////////////////////////
345 /// Pop and Return the 'current' data cache area from the list of area to be used for
346 /// temporarily store 'missing' data members.
347 
349 {
350  TVirtualArray *val = PeekDataCache();
351  fCacheStack.pop_back();
352  return val;
353 }
354 
TObject * GetParent() const
Return pointer to parent of this buffer.
Definition: TBuffer.cxx:229
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:298
char * fBuffer
Definition: TBuffer.h:48
virtual ~TBuffer()
Delete an I/O buffer object.
Definition: TBuffer.cxx:122
const Int_t kExtraSpace
Definition: TBuffer.cxx:20
Bool_t fMode
Definition: TBuffer.h:45
unsigned short UShort_t
Definition: RtypesCore.h:36
static TClass * GetClass(const type_info &typeinfo)
Forward to TROOT::GetClass().
Definition: TBuffer.cxx:295
ReAllocCharFun_t fReAllocFunc
Definition: TBuffer.h:52
char *(* ReAllocCharFun_t)(char *, size_t, size_t)
Definition: TStorage.h:31
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual TVirtualArray * PeekDataCache() const
Return the 'current' data cache area from the list of area to be used for temporarily store 'missing'...
Definition: TBuffer.cxx:338
void SetParent(TObject *parent)
Set parent owning this buffer.
Definition: TBuffer.cxx:237
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:946
virtual TProcessID * ReadProcessID(UShort_t pidf)=0
Return the current Process-ID.
Definition: TBuffer.cxx:311
static char * ReAllocChar(char *vp, size_t size, size_t oldsize)
Reallocate (i.e.
Definition: TStorage.cxx:259
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:34
ClassImp(TBuffer) static char *R__NoReAllocChar(char *
The user has provided memory than we don't own, thus we can not extent it either. ...
virtual UShort_t WriteProcessID(TProcessID *pid)=0
Always return 0 (current processID).
Definition: TBuffer.cxx:320
void Expand(Int_t newsize, Bool_t copy=kTRUE)
Expand (or shrink) the I/O buffer to newsize bytes.
Definition: TBuffer.cxx:199
CacheList_t fCacheStack
Realloc function to be used when extending the buffer.
Definition: TBuffer.h:53
Int_t fVersion
Definition: TBuffer.h:46
Wrapper around an object and giving indirect access to its content even if the object is not of a cla...
Definition: TVirtualArray.h:26
unsigned int UInt_t
Definition: RtypesCore.h:42
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:173
void SetReadMode()
Set buffer in read mode.
Definition: TBuffer.cxx:269
TLine * l
Definition: textangle.C:4
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
char * fBufCur
Definition: TBuffer.h:49
long Long_t
Definition: RtypesCore.h:50
TObject * fParent
Definition: TBuffer.h:51
virtual TVirtualArray * PopDataCache()
Pop and Return the 'current' data cache area from the list of area to be used for temporarily store '...
Definition: TBuffer.cxx:348
virtual void PushDataCache(TVirtualArray *)
Push a new data cache area onto the list of area to be used for temporarily store 'missing' data memb...
Definition: TBuffer.cxx:329
ReAllocCharFun_t GetReAllocFunc() const
Return the reallocation method currently used.
Definition: TBuffer.cxx:244
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
Mother of all ROOT objects.
Definition: TObject.h:58
TBuffer()
Definition: TBuffer.h:56
Int_t Length() const
Definition: TBuffer.h:94
Int_t fBufSize
Definition: TBuffer.h:47
void ResetBit(UInt_t f)
Definition: TObject.h:172
void SetReAllocFunc(ReAllocCharFun_t reallocfunc=0)
Set which memory reallocation method to use.
Definition: TBuffer.cxx:253
TObject * obj
char * fBufMax
Definition: TBuffer.h:50
void AutoExpand(Int_t size_needed)
Automatically calculate a new size and expand the buffer to fit at least size_needed.
Definition: TBuffer.cxx:140
void SetWriteMode()
Set buffer in write mode.
Definition: TBuffer.cxx:282
void SetBuffer(void *buf, UInt_t bufsiz=0, Bool_t adopt=kTRUE, ReAllocCharFun_t reallocfunc=0)
Sets a new buffer in an existing TBuffer object.
Definition: TBuffer.cxx:163