source: Sophya/trunk/SophyaLib/BaseTools/segdatablock.h@ 2931

Last change on this file since 2931 was 2884, checked in by ansari, 20 years ago

Modifs pour compilation avec g++ 4 (V >= 3.4) - Reza 4 Jan 2006

File size: 8.5 KB
Line 
1// This may look like C code, but it is really -*- C++ -*-
2// Gestion de block de donnees avec partage de references
3// R. Ansari Mars 2005
4// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
5#ifndef SEGDATABLOCK_H
6#define SEGDATABLOCK_H
7
8#include "machdefs.h"
9#include "anydataobj.h"
10#include <string.h>
11#include <vector>
12#include <iostream>
13#include <iomanip>
14#include <typeinfo>
15
16/*!
17 \class SOPHYA::SegDBInterface
18 \ingroup BaseTools
19 Interface definition for segmented data container (template class).
20*/
21/*!
22 \class SOPHYA::SegDataBlock
23 \ingroup BaseTools
24 Template class impementing segmented data container in memory with
25 management of reference sharing.
26*/
27
28namespace SOPHYA {
29
30////////////////////////////////////////////////////////////////
31//// ---------------- Class SegDBInterface ------------------ //
32//// ----------------- Class SegDataBlock ------------------- //
33////////////////////////////////////////////////////////////////
34
35template <class T>
36class SegDBInterface : public AnyDataObj {
37public:
38 virtual ~SegDBInterface() {}
39 //! Changes the data segment size and reallocates the memory segments
40 // segsz : Segment size ; nbseg : Number of data segments
41 virtual void SetSize(size_t segsz, size_t nbseg=0) = 0;
42 //! Alias for SetSize()
43 inline void ReSize(size_t segsz, size_t nbseg=0) { SetSize(segsz, nbseg); }
44 //! Adds one segment to the data structure - returns the new number of segments.
45 virtual size_t Extend() = 0;
46 //! Return the segment size data structure
47 virtual size_t SegmentSize() const = 0;
48 //! Return the number of data segments
49 virtual size_t NbSegments() const = 0;
50 //! Return the current size of the segmented data structure
51 inline size_t Size() const { return SegmentSize()*NbSegments(); }
52 //! Return the pointer to data segment \b k
53 virtual T* GetSegment(size_t k) = 0;
54 //! Return the const (read-only) pointer to data segment \b k
55 virtual T const * GetCstSegment(size_t k) const = 0;
56};
57
58
59// classe de container avec partage de reference
60template <class T>
61class SegDataBlock : public SegDBInterface<T> {
62
63public:
64
65 //! Default constructor - optional specification of segment size and number of segments
66 explicit SegDataBlock(size_t segsz=32, size_t nbseg=0)
67 {
68 mSRef = NULL;
69 SetSize(segsz, nbseg);
70 }
71 //! copy constructor - shares the data
72 SegDataBlock(const SegDataBlock<T>& a)
73 {
74 mSRef = a.mSRef;
75 mSRef->nref++;
76 }
77 //! copy constructor with specification of flags for data sharing and element value copy
78 SegDataBlock(const SegDataBlock<T>& a, bool share, bool cpval=true)
79 {
80 if (share) {
81 mSRef = a.mSRef;
82 mSRef->nref++;
83 }
84 else {
85 mSRef = NULL;
86 Clone(a, cpval);
87 }
88 }
89 //! copy constructor - shares the data if \b is a SegDataBlock, clones otherwise
90 SegDataBlock(const SegDBInterface<T>& a)
91 {
92 SegDataBlock<T> * sdb = dynamic_cast< SegDataBlock<T> *>(&a);
93 if (sdb != NULL) {
94 mSRef = sdb->mSRef;
95 mSRef->nref++;
96 }
97 else Clone(a, true);
98 }
99 //! Destructor. The memory is freed when the last object referencing the data segment is destroyed
100 virtual ~SegDataBlock()
101 {
102 //DEL cout << " DEBUG-~SegDataBlock() " << hex << mSRef << dec << " NRef()= " << NRef() << endl;
103 Delete();
104 }
105
106
107 //! Adds one segment to the data structure - returns the pointer to the allocated segment.
108 virtual size_t Extend()
109 {
110 T * p = new T[mSRef->segsize];
111 mSRef->dseg.push_back(p);
112 return( mSRef->dseg.size());
113 }
114
115 //! Changes the data segment size and reallocates the memory segments
116 // segsz : Segment size ; nbseg : Number of data segments
117 virtual void SetSize(size_t segsz, size_t nbseg=0)
118 {
119 Delete();
120 mSRef = new SDREF;
121 mSRef->nref = 1;
122 mSRef->segsize = segsz;
123 mSRef->dsid = AnyDataObj::getUniqueId();
124 for(size_t k=0; k<nbseg; k++) Extend();
125 }
126//! Shares the data between two SegDataBlock objects
127 void Share(const SegDataBlock<T>& a)
128 {
129 Delete();
130 mSRef = a.mSRef;
131 mSRef->nref++;
132 }
133
134//! Makes a clone of the data structure and optionaly copie the data
135 void Clone(const SegDBInterface<T> & a, bool cpval=true)
136 {
137 Delete();
138 mSRef = new SDREF;
139 mSRef->nref = 1;
140 mSRef->segsize = a.SegmentSize();
141 for(size_t k=0; k<a.NbSegments(); k++) {
142 Extend();
143 if (cpval) {
144 T * dst = GetSegment(k);
145 const T * src = a.GetCstSegment(k);
146 memcpy(dst, src, mSRef->segsize*sizeof(T));
147 }
148 }
149 }
150
151
152 //! Return the segment size of the data structure
153 virtual size_t SegmentSize() const { return mSRef->segsize; }
154 //! Return the number of data segments
155 virtual size_t NbSegments() const { return mSRef->dseg.size(); }
156 //! Return the current size of the segmented data structure
157 inline size_t Size() const { return mSRef->segsize*mSRef->dseg.size(); }
158
159 //! Return the pointer to data segment \b k
160 virtual T* GetSegment(size_t k) { return mSRef->dseg[k]; }
161 //! Return the const (read-only) pointer to data segment \b k
162 virtual T const * GetCstSegment(size_t k) const { return mSRef->dseg[k]; }
163
164 //! Return the segment index for element \b i
165 inline size_t SegIndex(size_t i) { return i/mSRef->segsize; }
166 //! Return the offset (in data segment) for element \b i
167 inline size_t EltOffset(size_t i) { return i%mSRef->segsize; }
168
169 //! Return the \b i th element of the segmented data structure
170 inline T& operator()(size_t i) { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));}
171 //! Return the \b i th element of the data structure
172 inline T& operator()(size_t i) const { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));}
173 //! Return the \b i th element of the segmented data structure
174 inline T& operator[](size_t i) { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));}
175 //! Return the \b i th element of the data structure
176 inline T& operator[](size_t i) const { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));}
177
178
179 //! Return the number of references to the data structure
180 inline size_t NRef() const { return mSRef->nref; }
181
182 //! Equal operator. Set all element values to \b v
183 SegDataBlock<T>& operator = (T const & v)
184 {
185 for(size_t k=0; k<NbSegments(); k++) {
186 T * p = mSRef->dseg[k];
187 for(size_t j=0; j<SegmentSize(); j++) p[j] = v;
188 }
189 return (*this);
190 }
191 //! Equal operator. Clones and copie values from \b a
192 inline SegDataBlock<T>& operator = (const SegDBInterface<T> & a)
193 {
194 Clone(a, true);
195 return (*this);
196 }
197 //! Equal operator. Clones and copie values from \b a
198 inline SegDataBlock<T>& operator = (const SegDataBlock<T> & a)
199 {
200 Clone(a, true);
201 return (*this);
202 }
203
204 //! ASCII formatted output (print)
205 void Print(ostream& os, int lev=0, const char * sep=NULL) const
206 {
207 os << "SegDataBlock< " << typeid(T).name() << "> mSRef= " << hex << mSRef
208 << " NRef=" << dec << NRef() << " DSId= " << DRefId() << endl;
209 os << " ... SegSize= " << SegmentSize() << " NbSeg= " << NbSegments()
210 << " Size= " << Size() << endl;
211 if (sep == NULL) sep = " ";
212 if (lev > 0) {
213 for(size_t k=0; k<NbSegments(); k++) {
214 T * p = mSRef->dseg[k];
215 os << " ..... DataSeg[ " << k << " ] : " << hex << p << dec << endl;
216 if (lev > 1)
217 for(size_t j=0; j<SegmentSize(); j++) os << p[j] << sep;
218 os << endl;
219 }
220 }
221 }
222 //! ASCII formatted output (print) on cout
223 inline void Print(int lev=0, const char * sep=NULL) const
224 {
225 Print(cout, lev, sep);
226 }
227
228 //! Returns the unique object identifier
229 inline uint_8 DRefId() const { return mSRef->dsid; }
230
231protected:
232 void Delete()
233 {
234 if (mSRef == NULL) return;
235 mSRef->nref--;
236 if (mSRef->nref > 0) { mSRef = NULL; return; }
237 //DEL cout << " DEBUG-SegDataBlock::Delete() NbSegments() = " << NbSegments() << endl;
238 for(size_t k=0; k<NbSegments(); k++) {
239 delete[] mSRef->dseg[k];
240 mSRef->dseg[k] = NULL;
241 }
242 delete mSRef;
243 mSRef = NULL;
244 }
245 /*! \cond
246 SDREF structure for reference management - for internal use by SegDataBlock
247 */
248 typedef struct {
249 size_t nref; // Number of references to the data structure
250 uint_8 dsid; // Data structure Id - Used by FIO_SegDataBlock
251 std::vector<T *> dseg;
252 size_t segsize;
253 } SDREF;
254 /*! \endcond */
255 SDREF * mSRef; //!< SDREF structure for reference sharing
256};
257
258//! Definition of operator \<\< for ascii formatted output of SegDataBlock
259template<class T>
260inline ostream& operator << (ostream& os, const SegDataBlock<T>& a)
261 { a.Print(os); return(os); }
262
263} // Fin du namespace
264
265#endif
Note: See TracBrowser for help on using the repository browser.