// Gestion de block de donnees avec partage de references // C.Magneville 04/99 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "machdefs.h" #include #include #include #include #include "pexceptions.h" #include "ndatablock.h" #include "objfio.h" using namespace PlanckDPC; // define DEBUG_NDATABLOCK #ifdef DEBUG_NDATABLOCK static size_t NallocData = 0; static size_t NallocSRef = 0; #endif //////////////////////////////////////////////////////////////// //************ Createur, Destructeur template NDataBlock::NDataBlock(size_t n) // Createur d'une structure de "n" donnees : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(size_t n, T* data, Bridge* br) // Createur d'une structure de "n" donnees, avec donnees preallouees // (Voir explications dans Alloc()) : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::NDataBlock("< NDataBlock::NDataBlock() // Createur par default : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(const NDataBlock& a) // Createur par copie: partage les donnees si "a" temporaire, clone sinon. : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(const NDataBlock& a,bool share) // Createur avec choix de partager ou non selon "share" : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::NDataBlock("< NDataBlock::~NDataBlock() // Destructeur { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::~NDataBlock("< void NDataBlock::Alloc(size_t n,T* data,Bridge* br) // Allocation d'un NOUVEL espace de stoquage de "n" donnees // Si data==NULL : allocation de l'espace memoire (vide) // data!=NULL : partage des donnees avec l'adresse data // Si br==NULL : les donnees nous appartiennent // br!=NULL : les donnees ne nous appartiennent pas (ex: Blitz) // // Exemple: on veut connecter a un tableau de T* // 1- On veut que NDataBlock NE DESALLOUE PAS le tableau "data" // a- Premiere solution // float *x = new float[5]; ... remplissage de x[] ...; // NDataBlock A(5,x,new Bridge); // delete [] x; // Il faut deleter explicitement // (et Bridge est delete par le destructeur de la classe) // b- Autre solution: // NDataBlock A(5); A.FillFrom(5,x); // delete [] x; // Il faut deleter explicitement // 2- On veut que NDataBlock desalloue le tableau // float *x = new float[5]; ... remplissage de x[] ...; // NDataBlock A(5,x); // (Ne Pas Faire "delete [] x;") { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::Alloc("<nref = 1; if(data) mSRef->data = data; else {mSRef->data = new T[n]; memset(mSRef->data,0,n*sizeof(T));} mSRef->bridge = br; #ifdef DEBUG_NDATABLOCK // Meme dans le cas data!=0 et br==0 (connexion d'un tableau // avec destruction geree par ~NDataBlock (cas 2-) on compte // comme si on avait fait une allocation du tableau (ce qui a ete // fait au niveau du dessus!). if(!br) NallocData++; NallocSRef++; cout<<"...?_NDataBlock::Alloc mSz="<nref="<nref<<" mSRef->data="<< mSRef->data <<" mSRef->bridge="<bridge<<" IsTemp="< void NDataBlock::Clone(const NDataBlock& a) // Clone: copie de donnees a partir de "a" { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::Clone("< void NDataBlock::CloneOrShare(const NDataBlock& a) // CloneOrShare: Share si "a" temporaire, Clone sinon. { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::CloneOrShare("< void NDataBlock::Share(const NDataBlock& a) // Share: Partage les donnees avec "a" { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::Share("<nref++; #ifdef DEBUG_NDATABLOCK cout<<"...?_NDataBlock::Share mSz="<nref="<nref<<" mSRef->data="<< mSRef->data <<" mSRef->bridge="<bridge<<" IsTemp="< void NDataBlock::Delete(void) // Pour detruire les pointeurs en tenant compte des references { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::Delete("<nref="<nref<<" mSRef->data=" <data<<" mSRef->bridge="<bridge; cout<nref--; if(mSRef->nref != 0) { #ifdef DEBUG_NDATABLOCK cout<<"...?_NDataBlock::Delete() pas de desallocation il reste nref=" <nref<<" Total("<bridge) NallocData--; NallocSRef--; cout<<"...?_NDataBlock::Delete() desallocation complete il reste nref=" <nref<<" Total("<bridge) delete mSRef->bridge; else delete [] mSRef->data; mSRef->bridge=NULL; mSRef->data=NULL; delete mSRef; mSRef=NULL; mSz = 0; } template void NDataBlock::FillFrom(size_t n,T* data) // Remplissage par un tableau de donnees // - Si classe vide : creation de l'espace memoire // - Si classe connectee : on ecrit selon la longueur minimale // (cad this->mSz ou "n") { if(data==NULL) throw(NullPtrError("NDataBlock::FillFrom data==NULL\n")); if(n==0) throw(ParmError("NDataBlock::FillFrom n<=0\n")); if(mSRef==NULL) Alloc(n); if(mSz void NDataBlock::Print(ostream& os,size_t i1,size_t n) const // Impression de n elements a partir de i1 { size_t nr = 0; T* p = NULL; Bridge* br = NULL; if(mSRef) {nr = mSRef->nref; p = mSRef->data; br = mSRef->bridge;} os<<"NDataBlock::Print("<=mSz || n<=0 || !p) return; size_t i2 = i1+n; if(i2>mSz) i2=mSz; size_t im = 1; bool enl=false; while(i1 T NDataBlock::Sum(size_t i1,size_t n) const // Somme des elements de i1 a i1+n-1 { if(i1>=mSz) return 0; if(n>mSz) n = mSz; if(n==0) n = mSz-i1; T const *p=Begin()+i1, *pe=p+n; T val = 0; while (p T NDataBlock::Product(size_t i1,size_t n) const // Produit des elements de i1 a i1+n-1 { if(i1>=mSz) return 0; if(n>mSz) n = mSz; if(n==0) n = mSz-i1; T const *p=Begin()+i1, *pe=p+n; T val = 0; while (p b; template NDataBlock& NDataBlock::operator = (const NDataBlock& a) // Affectation: partage des donnees si "a" temporaire, clone sinon. { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::operator=("< NDataBlock& NDataBlock::operator = (T v) // Affectation de tous les elements a une constante "v" { #ifdef DEBUG_NDATABLOCK cout<<"?_NDataBlock::operator=("< b; template NDataBlock& NDataBlock::operator += (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator+=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator -= (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator-=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator *= (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator*=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator /= (T b) { if(b==(T) 0) throw(ParmError("NDataBlock::operator/=v divide by zero\n")); if(mSz==0) throw(SzMismatchError("NDataBlock::operator/=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator += (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator+=A size mismatch/null")); T *p=Begin(), *pe=End(); T const * pa=a.Begin(); while (p NDataBlock& NDataBlock::operator -= (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator-=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (p NDataBlock& NDataBlock::operator *= (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator*=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (p NDataBlock& NDataBlock::operator /= (const NDataBlock& a) // Attention, aucune protection si un element de "a" est nul. { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator/=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (pb; // NDataBlock = b+NDataBlock; template NDataBlock NDataBlock::Add(T b) const // Pour A+b { NDataBlock result(*this); result.SetTemp(true); result += b; return result; } template NDataBlock NDataBlock::Sub(T b) const // Pour A-b { NDataBlock result(*this); result.SetTemp(true); return result -= b; } template NDataBlock NDataBlock::SubInv(T b) const // Pour b-A { NDataBlock result(*this); result.SetTemp(true); T *p=result.Begin(), *pe=result.End(); T const *pa=this->Begin(); while(p NDataBlock NDataBlock::Mul(T b) const // Pour A*b { NDataBlock result(*this); result.SetTemp(true); return result *= b; } template NDataBlock NDataBlock::Div(T b) const // Pour A/b { NDataBlock result(*this); result.SetTemp(true); return result /= b; } template NDataBlock NDataBlock::DivInv(T b) const // Pour b/A { NDataBlock result(*this); result.SetTemp(true); T *p=result.Begin(), *pe=result.End(); T const *pa = this->Begin(); while(p NDataBlock NDataBlock::Add(const NDataBlock& b) const // Pour A+B { if(mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A+B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) {result.Share(b); result += *this;} else {result.CloneOrShare(*this); result += b;} return result; } template NDataBlock NDataBlock::Mul(const NDataBlock& b) const // Pour A*B { if(mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A*B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) {result.Share(b); result *= *this;} else {result.CloneOrShare(*this); result *= b;} return result; } template NDataBlock NDataBlock::Sub(const NDataBlock& b) const // Pour A-B { if(mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A-B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); T *p=result.Begin(), *pe=result.End(); T const *pa=Begin(); while(p NDataBlock NDataBlock::Div(const NDataBlock& b) const // Pour A/B { if(mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A/B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); T *p=result.Begin(), *pe=result.End(); T const *pa=Begin(); while(p void ObjFileIO< NDataBlock >::ReadSelf(PInPersist& is) template void ObjFileIO< NDataBlock >::WriteSelf(POutPersist& os) */ // Pour pouvoir ecrire des tableaux de complex, en attendant // PIn/POutPersist::Get/Put(complex<>) #include template FIO_NDataBlock::FIO_NDataBlock() { dobj=new NDataBlock; ownobj=true; } template FIO_NDataBlock::FIO_NDataBlock(string const & filename) { dobj=new NDataBlock; ownobj=true; Read(filename); } template FIO_NDataBlock::FIO_NDataBlock(const NDataBlock & obj) { dobj = new NDataBlock(obj); ownobj=true; } template FIO_NDataBlock::FIO_NDataBlock(NDataBlock * obj) { dobj = obj; ownobj=false; } template FIO_NDataBlock::~FIO_NDataBlock() { if (ownobj && dobj) delete dobj; } template AnyDataObj* FIO_NDataBlock::DataObj() { return(dobj); } template void FIO_NDataBlock::ReadSelf(PInPersist& is) { // On lit les 3 premiers uint_8 uint_8 itab[3]; is.Get(itab, 3); if (dobj == NULL) dobj = new NDataBlock(itab[1]); else dobj->ReSize(itab[1]); // On lit le tableau de nombres PIOSReadArray(is, dobj->Data(), dobj->Size()); } template void FIO_NDataBlock::WriteSelf(POutPersist& os) const { if (dobj == NULL) return; // Attention - $CHECK$ Reza 26/04/99 // On ecrit 3 uint_4 // 0 : Numero de version, 1 : Taille, 2 reserve a l uint_8 itab[3]; itab[0] = 1; itab[1] = dobj->Size(); itab[2] = 0; os.Put(itab, 3); // On ecrit le tableau de nombres PIOSWriteArray(os, dobj->Data(), dobj->Size()); } /////////////////////////////////////////////////////////////// #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock< complex > #pragma define_template NDataBlock< complex > // Instances des delegues FileIO (PPersist) #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock< complex > #pragma define_template FIO_NDataBlock< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock< complex >; template class NDataBlock< complex >; // Instances des delegues FileIO (PPersist) template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock< complex >; template class FIO_NDataBlock< complex >; #endif