Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:26:04

0001 /// \file VecCore/VariableSizeObj.h
0002 /// \author Philippe Canal (pcanal@fnal.gov)
0003 
0004 #ifndef VECGEOM_VARIABLESIZEOBJ_H
0005 #define VECGEOM_VARIABLESIZEOBJ_H
0006 
0007 // This file will eventually move in VecCore.
0008 #include "VecGeom/base/Global.h"
0009 
0010 // For memset and memcpy
0011 #include <string.h>
0012 
0013 class TRootIOCtor;
0014 
0015 namespace vecgeom {
0016 
0017 /**
0018  * @brief   Array/vector of items with all information stored contiguously in memory.
0019  * @details Resizing operations require explicit new creation and copy.
0020  *    This is decomposed in the content part (VariableSizeObj) and the interface
0021  *    part (VariableSizeObjectInterface) so that the variable size part can be placed
0022  *    at the end of the object.
0023  */
0024 
0025 template <typename V>
0026 class VariableSizeObj {
0027 public:
0028   using Index_t = unsigned int;
0029 
0030   bool fSelfAlloc : 1;   //! Record whether the memory is externally managed.
0031   const Index_t fN : 31; // Number of elements.
0032   V fRealArray[1];       //! Beginning address of the array values -- real size: [fN]
0033 
0034   VariableSizeObj(TRootIOCtor *) : fSelfAlloc(false), fN(0) {}
0035 
0036   VECGEOM_FORCE_INLINE
0037   VECCORE_ATT_HOST_DEVICE
0038   VariableSizeObj(unsigned int nvalues) : fSelfAlloc(false), fN(nvalues) {}
0039 
0040   VECGEOM_FORCE_INLINE
0041   VECCORE_ATT_HOST_DEVICE
0042   VariableSizeObj(const VariableSizeObj &other) : fSelfAlloc(false), fN(other.fN)
0043   {
0044     if (other.fN) memcpy(GetValues(), other.GetValues(), (other.fN) * sizeof(V));
0045   }
0046 
0047   VECGEOM_FORCE_INLINE
0048   VECCORE_ATT_HOST_DEVICE
0049   VariableSizeObj(size_t new_size, const VariableSizeObj &other) : fSelfAlloc(false), fN(new_size)
0050   {
0051     if (other.fN) memcpy(GetValues(), other.GetValues(), (other.fN) * sizeof(V));
0052   }
0053 
0054   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE V *GetValues() { return &fRealArray[0]; }
0055   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE const V *GetValues() const { return &fRealArray[0]; }
0056 
0057   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE V &operator[](Index_t index) { return GetValues()[index]; };
0058   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE const V &operator[](Index_t index) const { return GetValues()[index]; };
0059 
0060   VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE VariableSizeObj &operator=(const VariableSizeObj &rhs)
0061   {
0062     // Copy data content using memcpy, limited by the respective size
0063     // of the the object.  If this is smaller there is data truncation,
0064     // if this is larger the extra datum are zero to zero.
0065 
0066     if (rhs.fN == fN) {
0067       memcpy(GetValues(), rhs.GetValues(), rhs.fN * sizeof(V));
0068     } else if (rhs.fN < fN) {
0069       memcpy(GetValues(), rhs.GetValues(), rhs.fN * sizeof(V));
0070       memset(GetValues() + rhs.fN, 0, (fN - rhs.fN) * sizeof(V));
0071     } else {
0072       // Truncation!
0073       memcpy(GetValues(), rhs.GetValues(), fN * sizeof(V));
0074     }
0075     return *this;
0076   }
0077 };
0078 
0079 template <typename Cont, typename V>
0080 class VariableSizeObjectInterface {
0081 protected:
0082   VariableSizeObjectInterface()  = default;
0083   ~VariableSizeObjectInterface() = default;
0084 
0085 public:
0086   // The static maker to be used to create an instance of the variable size object.
0087 
0088   template <typename... T>
0089   VECCORE_ATT_HOST_DEVICE
0090   static Cont *MakeInstance(size_t nvalues, const T &... params)
0091   {
0092     // Make an instance of the class which allocates the node array. To be
0093     // released using ReleaseInstance.
0094     size_t needed = SizeOf(nvalues);
0095     char *ptr     = new char[needed];
0096     if (!ptr) return 0;
0097     assert((((unsigned long long)ptr) % alignof(Cont)) == 0 && "alignment error");
0098     Cont *obj                         = new (ptr) Cont(nvalues, params...);
0099     obj->GetVariableData().fSelfAlloc = true;
0100     return obj;
0101   }
0102 
0103   template <typename... T>
0104   VECCORE_ATT_HOST_DEVICE
0105   static Cont *MakeInstanceAt(size_t nvalues, void *addr, const T &... params)
0106   {
0107     // Make an instance of the class which allocates the node array. To be
0108     // released using ReleaseInstance. If addr is non-zero, the user promised that
0109     // addr contains at least that many bytes:  size_t needed = SizeOf(nvalues);
0110     if (!addr) {
0111       return MakeInstance(nvalues, params...);
0112     } else {
0113       assert((((unsigned long long)addr) % alignof(Cont)) == 0 && "addr does not satisfy alignment");
0114       Cont *obj                         = new (addr) Cont(nvalues, params...);
0115       obj->GetVariableData().fSelfAlloc = false;
0116       return obj;
0117     }
0118   }
0119 
0120   // The equivalent of the copy constructor
0121   VECCORE_ATT_HOST_DEVICE
0122   static Cont *MakeCopy(const Cont &other)
0123   {
0124     // Make a copy of the variable size array and its container.
0125 
0126     size_t needed = SizeOf(other.GetVariableData().fN);
0127     char *ptr     = new char[needed];
0128     if (!ptr) return 0;
0129     Cont *copy                         = new (ptr) Cont(other);
0130     copy->GetVariableData().fSelfAlloc = true;
0131     return copy;
0132   }
0133 
0134   VECCORE_ATT_HOST_DEVICE
0135   static Cont *MakeCopy(size_t new_size, const Cont &other)
0136   {
0137     // Make a copy of a the variable size array and its container with
0138     // a new_size of the content.
0139 
0140     size_t needed = SizeOf(new_size);
0141     char *ptr     = new char[needed];
0142     if (!ptr) return 0;
0143     Cont *copy                         = new (ptr) Cont(new_size, other);
0144     copy->GetVariableData().fSelfAlloc = true;
0145     return copy;
0146   }
0147 
0148   // The equivalent of the copy constructor
0149   VECCORE_ATT_HOST_DEVICE
0150   static Cont *MakeCopyAt(const Cont &other, void *addr)
0151   {
0152     // Make a copy of a the variable size array and its container at the location (if indicated)
0153     if (addr) {
0154       Cont *copy                         = new (addr) Cont(other);
0155       copy->GetVariableData().fSelfAlloc = false;
0156       return copy;
0157     } else {
0158       return MakeCopy(other);
0159     }
0160   }
0161 
0162   // The equivalent of the copy constructor
0163   VECCORE_ATT_HOST_DEVICE
0164   static Cont *MakeCopyAt(size_t new_size, const Cont &other, void *addr)
0165   {
0166     // Make a copy of a the variable size array and its container at the location (if indicated)
0167     if (addr) {
0168       Cont *copy                         = new (addr) Cont(new_size, other);
0169       copy->GetVariableData().fSelfAlloc = false;
0170       return copy;
0171     } else {
0172       return MakeCopy(new_size, other);
0173     }
0174   }
0175 
0176   // The equivalent of the destructor
0177   VECCORE_ATT_HOST_DEVICE
0178   static void ReleaseInstance(Cont *obj)
0179   {
0180     // Releases the space allocated for the object
0181     obj->~Cont();
0182     if (obj->GetVariableData().fSelfAlloc) delete[](char *) obj;
0183   }
0184 
0185   // Equivalent of sizeof function (not taking into account padding for alignment)
0186   VECCORE_ATT_HOST_DEVICE
0187   static constexpr size_t SizeOf(size_t nvalues)
0188   {
0189     return (sizeof(Cont) + Cont::SizeOfExtra(nvalues) + sizeof(V) * (nvalues - 1));
0190   }
0191 
0192   // Size of the allocated derived type data members that are also variable size
0193   VECCORE_ATT_HOST_DEVICE
0194   static constexpr size_t SizeOfExtra(size_t nvalues) { return 0; }
0195 
0196   // equivalent of sizeof function taking into account padding for alignment
0197   // this function should be used when making arrays of VariableSizeObjects
0198   VECCORE_ATT_HOST_DEVICE
0199   static constexpr size_t SizeOfAlignAware(size_t nvalues) { return SizeOf(nvalues) + RealFillUp(nvalues); }
0200 
0201 private:
0202   VECCORE_ATT_HOST_DEVICE
0203   static constexpr size_t FillUp(size_t nvalues) { return alignof(Cont) - SizeOf(nvalues) % alignof(Cont); }
0204 
0205   VECCORE_ATT_HOST_DEVICE
0206   static constexpr size_t RealFillUp(size_t nvalues)
0207   {
0208     return (FillUp(nvalues) == alignof(Cont)) ? 0 : FillUp(nvalues);
0209   }
0210 };
0211 } // namespace vecgeom
0212 
0213 #endif //  VECGEOM_VARIABLESIZEOBJ_H