// This may look like C code, but it is really -*- C++ -*- // Gestion de block de donnees swapable // R. Ansari Mars 2005 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #ifndef SWSEGDATABLOCK_H #define SWSEGDATABLOCK_H #include "machdefs.h" #include "segdatablock.h" #include "pexceptions.h" #include #include /*! \class SOPHYA::DataSwapperInterface \ingroup BaseTools Interface definition for data swapper (pure virtual) classes to be used with SOPHYA::SwSegDataBlock classes. */ /*! \class SOPHYA::SwSegDataBlock \ingroup BaseTools Segmented data structure with swap space management. */ namespace SOPHYA { //////////////////////////////////////////////////////////////// //// ------------- Class DataSwapperInterface --------------- // //// ---------------- Class SwSegDataBlock ------------------ // //////////////////////////////////////////////////////////////// template class DataSwapperInterface { public: virtual ~DataSwapperInterface() { } /*! Swap out the data array pointed by \b d with size \b sz Return the swap position which might be used later to retrieve the data from swap \param d : Pointer to the memory segment \param sz : Number of elements (type T) \param idx : An integer which might be used to identify the data (optional) \param oswp : Old swap position, if the data has already been swapped \param osw : true -> data has already been swapped */ virtual int_8 WriteToSwap(const T * d, size_t sz, int_8 idx, int_8 oswp=0, bool osw=false) = 0; /*! Swap in the data array pointed by \b d with size \b sz Retrieves the data from swap space and copies it to \b d \param idx : optional data identifier \param swp : swap position (obtained from a previous call to WriteToSwap() \param d : pointer to T , where the data will be copied from swap space \param sz : Number of data elements (type T) */ virtual void ReadFromSwap(int_8 idx, int_8 swp, T* d, size_t sz) = 0; /*! Duplicate the swapper object and return the new object pointer. The returned pointer should be deleted when not needed any more. This method is used by SwSegDataBlock */ virtual DataSwapperInterface* Clone() = 0; }; template class SwSegDataBlock : public SegDBInterface { public: //! Constructor - creation from swap position tags (values) SwSegDataBlock(DataSwapperInterface & dsw, vector const & swpos, size_t segsz) { mSRef = NULL; SetSize(segsz, swpos.size()); SetSwapper(dsw); mSRef->swp = swpos; for(size_t k=0; kfgwp.size(); k++) mSRef->fgwp[k] = true; } //! Constructor - optional specification of segment size and number of segments SwSegDataBlock(DataSwapperInterface & dsw, size_t segsz=32, size_t nbseg=0) { mSRef = NULL; SetSize(segsz, nbseg); SetSwapper(dsw); } //! copy constructor - shares the data SwSegDataBlock(const SwSegDataBlock& a) { mSRef = a.mSRef; mSRef->nref++; } //! Destructor. The memory is freed when the last object referencing the data segment is destroyed virtual ~SwSegDataBlock() { Delete(); } //! Adds one segment to the data structure - returns the pointer to the allocated segment. virtual size_t Extend() { mSRef->swp.push_back(0); mSRef->fgwp.push_back(false); return mSRef->swp.size(); } /*! \brief Changes the data segment size and reallocates the memory segments \warning SetSwapper() must be called after call to SetSize() */ // segsz : Segment size ; nbseg : Number of data segments virtual void SetSize(size_t segsz, size_t nbseg=0) { Delete(); mSRef = new SWSDREF; mSRef->nref = 1; mSRef->segsize = segsz; mSRef->dsid = AnyDataObj::getUniqueId(); mSRef->buff = new T[segsz]; mSRef->bidx = -1; mSRef->fgcstbuff = true; for(size_t k=0; kswp.push_back(0); mSRef->fgwp.push_back(false); } mSRef->swapper = NULL; } //! Define the data swapper object. Should only be called if SetSize() is called void SetSwapper(DataSwapperInterface & dsw) { if (mSRef == NULL) return; if (mSRef->swapper) delete mSRef->swapper; mSRef->swapper = dsw.Clone(); } //! Return the segment size data structure virtual size_t SegmentSize() const { return mSRef->segsize; } //! Return the number of data segments virtual size_t NbSegments() const { return mSRef->swp.size(); } ; //! Return the current size of the segmented data structure inline size_t Size() const { return mSRef->swp.size()*mSRef->segsize; } //! Return the pointer to data segment \b k virtual T* GetSegment(size_t k) { getSeg(k); mSRef->fgcstbuff = false; return mSRef->buff; } //! Return the const (read-only) pointer to data segment \b k virtual T const * GetCstSegment(size_t k) const { getSeg(k); mSRef->fgcstbuff = true; return mSRef->buff; } //! Equal operator. Shares the data with \b a inline SwSegDataBlock& operator = (const SwSegDataBlock& a) { Delete(); mSRef = a.mSRef; mSRef->nref++; return *this; } //! Empties all memory buffers to swap stream void SwapOutBuffer() const { if ((mSRef->bidx >= 0) && !mSRef->fgcstbuff) { int_8 nswp = mSRef->swapper->WriteToSwap(mSRef->buff, mSRef->segsize, mSRef->bidx, mSRef->swp[mSRef->bidx], mSRef->fgwp[mSRef->bidx]); mSRef->swp[mSRef->bidx] = nswp; mSRef->fgwp[mSRef->bidx] = true; mSRef->bidx = -1; mSRef->fgcstbuff = true; } } //! Return the position tag (swap position) table, after call to SwapOutBuffer() std::vector< int_8 > & GetSwapPosTagTable() const { SwapOutBuffer(); return mSRef->swp; } protected: SwSegDataBlock() { throw ForbiddenError("SwSegDataBlock() default constructor not allowed (swsegdb.h)"); } void Delete() { if (mSRef == NULL) return; mSRef->nref--; if (mSRef->nref > 0) { mSRef = NULL; return; } if (mSRef->swapper) delete mSRef->swapper; delete[] mSRef->buff; delete mSRef; mSRef = NULL; } void getSeg(size_t k) const { if (k == mSRef->bidx) return ; if ((mSRef->bidx >= 0) && !mSRef->fgcstbuff) { int_8 nswp = mSRef->swapper->WriteToSwap(mSRef->buff, mSRef->segsize, mSRef->bidx, mSRef->swp[mSRef->bidx], mSRef->fgwp[mSRef->bidx]); mSRef->swp[mSRef->bidx] = nswp; mSRef->fgwp[mSRef->bidx] = true; } if (mSRef->fgwp[k]) mSRef->swapper->ReadFromSwap(k, mSRef->swp[k], mSRef->buff, mSRef->segsize); else { delete[] mSRef->buff; mSRef->buff = new T[mSRef->segsize]; } mSRef->bidx = k; return; } //! \cond typedef struct { size_t nref; // Number of references to the data structure uint_8 dsid; // Data structure id size_t segsize; // data segment size mutable std::vector< int_8 > swp; // swap position tag for each segment mutable std::vector< bool > fgwp; // swap flag (true = already swapped) for each segment mutable T * buff; // Data buffer mutable int_8 bidx; // segment index (number) corresponding to buffer mutable bool fgcstbuff; // true : this is a constant T * buff< DataSwapperInterface * swapper; // Data swapper } SWSDREF; //! \endcond SWSDREF * mSRef; // SWSDREF structure for reference sharing }; } // Fin du namespace #endif