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

Last change on this file since 3213 was 3213, checked in by ansari, 18 years ago

Sw/SegDataBlock<T> rendu en principe ThreadSafe + changement numero de version SOPHYA et module BaseTools, Reza 11/04/2007

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