source: Sophya/trunk/SophyaLib/BaseTools/swsegdb.h@ 4071

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

Debug protections thread-safe pour SegDataBlock<T> et SwSegDataBlock<T>, Reza 12/04/2007

File size: 9.0 KB
RevLine 
[2660]1// This may look like C code, but it is really -*- C++ -*-
2// Gestion de block de donnees swapable
3// R. Ansari Mars 2005
4// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
5#ifndef SWSEGDATABLOCK_H
6#define SWSEGDATABLOCK_H
7
8#include "machdefs.h"
9#include "segdatablock.h"
10#include "pexceptions.h"
11#include <vector>
12#include <typeinfo>
13
[2805]14/*!
15 \class SOPHYA::DataSwapperInterface
16 \ingroup BaseTools
17 Interface definition for data swapper (pure virtual) classes to be used
18 with SOPHYA::SwSegDataBlock classes.
19*/
20/*!
21 \class SOPHYA::SwSegDataBlock
22 \ingroup BaseTools
23 Segmented data structure with swap space management.
24*/
25
[2660]26namespace SOPHYA {
27
28////////////////////////////////////////////////////////////////
29//// ------------- Class DataSwapperInterface --------------- //
30//// ---------------- Class SwSegDataBlock ------------------ //
31////////////////////////////////////////////////////////////////
32
33template <class T>
34class DataSwapperInterface {
35public:
36 virtual ~DataSwapperInterface() { }
[2805]37 /*! Swap out the data array pointed by \b d with size \b sz
38 Return the swap position which might be used later to retrieve the data from swap
39 \param d : Pointer to the memory segment
40 \param sz : Number of elements (type T)
41 \param idx : An integer which might be used to identify the data (optional)
42 \param oswp : Old swap position, if the data has already been swapped
43 \param osw : true -> data has already been swapped
44 */
[2660]45 virtual int_8 WriteToSwap(const T * d, size_t sz, int_8 idx, int_8 oswp=0, bool osw=false) = 0;
[2805]46 /*! Swap in the data array pointed by \b d with size \b sz
47 Retrieves the data from swap space and copies it to \b d
48 \param idx : optional data identifier
49 \param swp : swap position (obtained from a previous call to WriteToSwap()
50 \param d : pointer to T , where the data will be copied from swap space
51 \param sz : Number of data elements (type T)
52 */
[2660]53 virtual void ReadFromSwap(int_8 idx, int_8 swp, T* d, size_t sz) = 0;
[2863]54
55 /*! Duplicate the swapper object and return the new object pointer.
56 The returned pointer should be deleted when not needed any more.
57 This method is used by SwSegDataBlock<T>
58 */
59 virtual DataSwapperInterface<T>* Clone() = 0;
[2660]60};
61
62template <class T>
63class SwSegDataBlock : public SegDBInterface<T> {
64public:
65 //! Constructor - creation from swap position tags (values)
66 SwSegDataBlock(DataSwapperInterface<T> & dsw, vector<int_8> const & swpos, size_t segsz)
67 {
68 mSRef = NULL;
69 SetSize(segsz, swpos.size());
[2863]70 SetSwapper(dsw);
[3213]71 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2660]72 mSRef->swp = swpos;
73 for(size_t k=0; k<mSRef->fgwp.size(); k++) mSRef->fgwp[k] = true;
[3213]74 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[2660]75 }
76 //! Constructor - optional specification of segment size and number of segments
77 SwSegDataBlock(DataSwapperInterface<T> & dsw, size_t segsz=32, size_t nbseg=0)
78 {
79 mSRef = NULL;
80 SetSize(segsz, nbseg);
[2863]81 SetSwapper(dsw);
[2660]82 }
83 //! copy constructor - shares the data
84 SwSegDataBlock(const SwSegDataBlock<T>& a)
85 {
[3214]86 a.mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2660]87 mSRef = a.mSRef;
88 mSRef->nref++;
[3214]89 size_t segsz = mSRef->segsize;
90 a.mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
91 buff = new T[segsz];
92 bidx = -1;
93 fgcstbuff = true;
[2660]94 }
95
96 //! Destructor. The memory is freed when the last object referencing the data segment is destroyed
[3213]97 virtual ~SwSegDataBlock()
98 {
99 Delete();
100 }
[2660]101 //! Adds one segment to the data structure - returns the pointer to the allocated segment.
102 virtual size_t Extend()
103 {
[3213]104 size_t rs = 0;
105 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2660]106 mSRef->swp.push_back(0);
107 mSRef->fgwp.push_back(false);
[3213]108 rs = mSRef->swp.size();
109 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
110 return rs;
[2660]111 }
[2863]112 /*! \brief Changes the data segment size and reallocates the memory segments
113 \warning SetSwapper() must be called after call to SetSize()
114 */
[2660]115 // segsz : Segment size ; nbseg : Number of data segments
116 virtual void SetSize(size_t segsz, size_t nbseg=0)
117 {
118 Delete();
[3214]119 mSRef = new SWSDREF;
[3213]120 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2660]121 mSRef->nref = 1;
122 mSRef->segsize = segsz;
123 mSRef->dsid = AnyDataObj::getUniqueId();
124 for(size_t k=0; k<nbseg; k++) {
125 mSRef->swp.push_back(0);
126 mSRef->fgwp.push_back(false);
127 }
[2863]128 mSRef->swapper = NULL;
[3213]129 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[3214]130 buff = new T[segsz];
131 bidx = -1;
132 fgcstbuff = true;
[2660]133 }
[2863]134
135 //! Define the data swapper object. Should only be called if SetSize() is called
136 void SetSwapper(DataSwapperInterface<T> & dsw)
137 {
138 if (mSRef == NULL) return;
[3213]139 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2863]140 if (mSRef->swapper) delete mSRef->swapper;
141 mSRef->swapper = dsw.Clone();
[3213]142 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[2863]143 }
144
[2660]145 //! Return the segment size data structure
146 virtual size_t SegmentSize() const { return mSRef->segsize; }
147 //! Return the number of data segments
148 virtual size_t NbSegments() const { return mSRef->swp.size(); } ;
149 //! Return the current size of the segmented data structure
150 inline size_t Size() const { return mSRef->swp.size()*mSRef->segsize; }
[2698]151 //! Return the pointer to data segment \b k
[2660]152 virtual T* GetSegment(size_t k)
153 {
154 getSeg(k);
[3214]155 fgcstbuff = false;
156 return buff;
[2660]157 }
[2698]158 //! Return the const (read-only) pointer to data segment \b k
159 virtual T const * GetCstSegment(size_t k) const
[2660]160 {
[3214]161 if (getSeg(k)) fgcstbuff = true;
162 return buff;
[2660]163 }
[2692]164
165 //! Equal operator. Shares the data with \b a
166 inline SwSegDataBlock<T>& operator = (const SwSegDataBlock<T>& a)
167 {
168 Delete();
[3214]169 a.mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2692]170 mSRef = a.mSRef;
171 mSRef->nref++;
[3214]172 size_t segsz = mSRef->segsize;
173 a.mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
174 buff = new T[segsz];
175 bidx = -1;
176 fgcstbuff = true;
[2695]177 return *this;
[2692]178 }
179
[2695]180 //! Empties all memory buffers to swap stream
181 void SwapOutBuffer() const
182 {
[3213]183 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[3214]184 if ((bidx >= 0) && !fgcstbuff) {
185 int_8 nswp = mSRef->swapper->WriteToSwap(buff, mSRef->segsize, bidx,
186 mSRef->swp[bidx], mSRef->fgwp[bidx]);
187 mSRef->swp[bidx] = nswp;
188 mSRef->fgwp[bidx] = true;
189 bidx = -1;
190 fgcstbuff = true;
[2695]191 }
[3213]192 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[2695]193 }
194 //! Return the position tag (swap position) table, after call to SwapOutBuffer()
195 std::vector< int_8 > & GetSwapPosTagTable() const
196 {
197 SwapOutBuffer();
[2660]198 return mSRef->swp;
199 }
200
201protected:
202 SwSegDataBlock()
203 {
204 throw ForbiddenError("SwSegDataBlock() default constructor not allowed (swsegdb.h)");
205 }
206 void Delete()
207 {
208 if (mSRef == NULL) return;
[3213]209 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
[2660]210 mSRef->nref--;
[3213]211 if (mSRef->nref > 0) {
212 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[3214]213 delete[] buff;
[3213]214 mSRef = NULL;
215 return;
216 }
[2863]217 if (mSRef->swapper) delete mSRef->swapper;
[3213]218 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
[2660]219 delete mSRef;
[3214]220 delete[] buff;
[2660]221 mSRef = NULL;
222 }
[3172]223 bool getSeg(size_t k) const
[2660]224 {
[3214]225 if (k == bidx) return false;
226 mSRef->gThsop.lock(); // (ThreadSafe) - Start of atomic operation
227 if ((bidx >= 0) && !fgcstbuff) {
228 int_8 nswp = mSRef->swapper->WriteToSwap(buff, mSRef->segsize, bidx,
229 mSRef->swp[bidx], mSRef->fgwp[bidx]);
230 mSRef->swp[bidx] = nswp;
231 mSRef->fgwp[bidx] = true;
[2660]232 }
233 if (mSRef->fgwp[k])
[3214]234 mSRef->swapper->ReadFromSwap(k, mSRef->swp[k], buff, mSRef->segsize);
[3172]235 //DEL-02022007 else { delete[] mSRef->buff; mSRef->buff = new T[mSRef->segsize]; }
[3214]236 mSRef->gThsop.unlock(); // (ThreadSafe) - End of atomic operation
237 bidx = k;
[3172]238 return true;
[2660]239 }
240
[2805]241 //! \cond
[2660]242 typedef struct {
243 size_t nref; // Number of references to the data structure
244 uint_8 dsid; // Data structure id
245 size_t segsize; // data segment size
246 mutable std::vector< int_8 > swp; // swap position tag for each segment
247 mutable std::vector< bool > fgwp; // swap flag (true = already swapped) for each segment
248 DataSwapperInterface<T> * swapper; // Data swapper
[3213]249 ThSafeOp gThsop; // Mutex for thread safe operation one / SWSDREF struct
[2660]250 } SWSDREF;
[2805]251 //! \endcond
[3213]252 SWSDREF * mSRef; //!< SWSDREF structure for reference sharing
[3214]253 mutable T * buff; // Data buffer
254 mutable int_8 bidx; // segment index (number) corresponding to buffer
255 mutable bool fgcstbuff; // true : this is a constant T * buff
[3213]256
[2660]257};
258
259
260} // Fin du namespace
261
262#endif
Note: See TracBrowser for help on using the repository browser.