// This may look like C code, but it is really -*- C++ -*- // Gestion de block de donnees avec partage de references // R. Ansari Mars 2005 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #ifndef SEGDATABLOCK_H #define SEGDATABLOCK_H #include "machdefs.h" #include "anydataobj.h" #include #include #include #include #include namespace SOPHYA { //////////////////////////////////////////////////////////////// //// ---------------- Class SegDBInterface ------------------ // //// ----------------- Class SegDataBlock ------------------- // //////////////////////////////////////////////////////////////// /*! \class SOPHYA::SegDBInterface \ingroup BaseTools Interface definition for segmented data container (template class). */ template class SegDBInterface : public AnyDataObj { public: virtual ~SegDBInterface() {} //! Changes the data segment size and reallocates the memory segments // segsz : Segment size ; nbseg : Number of data segments virtual void SetSize(size_t segsz, size_t nbseg=0) = 0; //! Alias for SetSize() inline void ReSize(size_t segsz, size_t nbseg=0) { SetSize(segsz, nbseg); } //! Adds one segment to the data structure - returns the new number of segments. virtual size_t Extend() = 0; //! Return the segment size data structure virtual size_t SegmentSize() const = 0; //! Return the number of data segments virtual size_t NbSegments() const = 0; //! Return the current size of the segmented data structure inline size_t Size() const { return SegmentSize()*NbSegments(); } //! Return the pointer to data segment \b k virtual T* GetSegment(size_t k) = 0; //! Return the const (read-only) pointer to data segment \b k virtual T const * GetCstSegment(size_t k) const = 0; }; // classe de container avec partage de reference //! Segmented data container with reference sharing /*! \class SOPHYA::SegDataBlock \ingroup BaseTools Template class impementing segmented data container in memory with management of reference sharing. */ template class SegDataBlock : public SegDBInterface { public: //! Default constructor - optional specification of segment size and number of segments explicit SegDataBlock(size_t segsz=32, size_t nbseg=0) { mSRef = NULL; SetSize(segsz, nbseg); } //! copy constructor - shares the data SegDataBlock(const SegDataBlock& a) { mSRef = a.mSRef; mSRef->nref++; } //! copy constructor with specification of flags for data sharing and element value copy SegDataBlock(const SegDataBlock& a, bool share, bool cpval=true) { if (share) { mSRef = a.mSRef; mSRef->nref++; } else { mSRef = NULL; Clone(a, cpval); } } //! copy constructor - shares the data if \b is a SegDataBlock, clones otherwise SegDataBlock(const SegDBInterface& a) { SegDataBlock * sdb = dynamic_cast< SegDataBlock *>(&a); if (p != NULL) { mSRef = p->mSRef; mSRef->nref++; } else Clone(a, true); } //! Destructor. The memory is freed when the last object referencing the data segment is destroyed virtual ~SegDataBlock() { //DEL cout << " DEBUG-~SegDataBlock() " << hex << mSRef << dec << " NRef()= " << NRef() << endl; Delete(); } //! Adds one segment to the data structure - returns the pointer to the allocated segment. virtual size_t Extend() { T * p = new T[mSRef->segsize]; mSRef->dseg.push_back(p); return( mSRef->dseg.size()); } //! Changes the data segment size and reallocates the memory segments // segsz : Segment size ; nbseg : Number of data segments virtual void SetSize(size_t segsz, size_t nbseg=0) { Delete(); mSRef = new SDREF; mSRef->nref = 1; mSRef->segsize = segsz; mSRef->dsid = AnyDataObj::getUniqueId(); for(size_t k=0; k& a) { Delete(); mSRef = a.mSRef; mSRef->nref++; } //! Makes a clone of the data structure and optionaly copie the data void Clone(const SegDBInterface & a, bool cpval=true) { Delete(); mSRef = new SDREF; mSRef->nref = 1; mSRef->segsize = a.SegmentSize(); for(size_t k=0; ksegsize*sizeof(T)); } } } //! Return the segment size of the data structure virtual size_t SegmentSize() const { return mSRef->segsize; } //! Return the number of data segments virtual size_t NbSegments() const { return mSRef->dseg.size(); } //! Return the current size of the segmented data structure inline size_t Size() const { return mSRef->segsize*mSRef->dseg.size(); } //! Return the pointer to data segment \b k virtual T* GetSegment(size_t k) { return mSRef->dseg[k]; } //! Return the const (read-only) pointer to data segment \b k virtual T const * GetCstSegment(size_t k) const { return mSRef->dseg[k]; } //! Return the segment index for element \b i inline size_t SegIndex(size_t i) { return i/mSRef->segsize; } //! Return the offset (in data segment) for element \b i inline size_t EltOffset(size_t i) { return i%mSRef->segsize; } //! Return the \b i th element of the segmented data structure inline T& operator()(size_t i) { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));} //! Return the \b i th element of the data structure inline T& operator()(size_t i) const { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));} //! Return the \b i th element of the segmented data structure inline T& operator[](size_t i) { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));} //! Return the \b i th element of the data structure inline T& operator[](size_t i) const { return *(mSRef->dseg[SegIndex(i)]+EltOffset(i));} //! Return the number of references to the data structure inline size_t NRef() const { return mSRef->nref; } //! Equal operator. Set all element values to \b v SegDataBlock& operator = (T const & v) { for(size_t k=0; kdseg[k]; for(size_t j=0; j& operator = (const SegDBInterface & a) { Clone(a, true); return (*this); } //! Equal operator. Clones and copie values from \b a inline SegDataBlock& operator = (const SegDataBlock & a) { Clone(a, true); return (*this); } //! ASCII formatted output (print) void Print(ostream& os, int lev=0, const char * sep=NULL) const { os << "SegDataBlock< " << typeid(T).name() << "> mSRef= " << hex << mSRef << " NRef=" << dec << NRef() << " DSId= " << DRefId() << endl; os << " ... SegSize= " << SegmentSize() << " NbSeg= " << NbSegments() << " Size= " << Size() << endl; if (sep == NULL) sep = " "; if (lev > 0) { for(size_t k=0; kdseg[k]; os << " ..... DataSeg[ " << k << " ] : " << hex << p << dec << endl; if (lev > 1) for(size_t j=0; jdsid; } protected: void Delete() { if (mSRef == NULL) return; mSRef->nref--; if (mSRef->nref > 0) { mSRef = NULL; return; } //DEL cout << " DEBUG-SegDataBlock::Delete() NbSegments() = " << NbSegments() << endl; for(size_t k=0; kdseg[k]; mSRef->dseg[k] = NULL; } delete mSRef; mSRef = NULL; } //! SDREF structure for reference management - for internal use by SegDataBlock typedef struct { size_t nref; //!< Number of references to the data structure uint_8 dsid; //!< Data structure Id - Used by FIO_SegDataBlock std::vector dseg; size_t segsize; } SDREF; SDREF * mSRef; //!< SDREF structure for reference sharing }; //! Definition of operator \<\< for ascii formatted output of SegDataBlock template inline ostream& operator << (ostream& os, const SegDataBlock& a) { a.Print(os); return(os); } } // Fin du namespace #endif