template<typename T, typename Backing>
Array<T, Backing> copy(const Array<T, Backing> &other)#
Create a copy of an Array, which does not share data
- #include <array.hxx>
ArrayData holds the actual data Handles the allocation and deletion of data
inline ArrayData(int size)#
inline int size() const#
inline ArrayData<T> &operator=(const ArrayData<T> &in)#
Copy assignment Copy the underlying data from one array to the other
in – ArrayData with the same len as this.
- inline ArrayData(int size)#
template<typename T, typename Backing = ArrayData<T>>
- #include <array.hxx>
Data array type with automatic memory management
This implements a container similar to std::vector but with reference counting like a smart pointer and custom memory management to minimise new and delete calls
This can be used as an alternative to static arrays
Array<dcomplex> vals(100); // 100 complex numbers
vals = 1.0; // ok
When an Array goes out of scope or is deleted, the underlying memory (dataBlock/Backing) is put into a map, rather than being freed. If the same size arrays are used repeatedly then this avoids the need to use new and delete.
This behaviour can be disabled by calling the static function useStore:
Array<dcomplex>::useStore(false); // Disables memory store
The second template argument determines what type of container to use to store data. This defaults to a custom struct but can be std::valarray ( provided T is a compatible type), std::vector etc. Must provide the following : size, operator=, operator, begin, end
Arrays can’t be used in GPU code. To access Array data inside a RAJA loop, first extract the raw pointer
inline ~Array() noexcept#
Destructor. Releases the underlying dataBlock
inline Array &operator=(Array other) noexcept#
Assignment operator After this both Arrays share the same dataBlock
Uses copy-and-swap idiom
inline void reallocate(size_type new_size)#
Reallocate the array with size =
Note that this invalidates the existing data!
inline void clear() noexcept#
Release data. After this the Array is empty and any data access will be invalid
inline void ensureUnique()#
Ensures that this Array does not share data with another This should be called before performing any write operations on the data.
inline T &operator(size_type ind)#
Access a data element. This will fail if the Array is empty (so ptr is null), or if ind is out of bounds. For efficiency no checking is performed, so the user should perform checks.
Public Static Functions
static inline bool useStore(bool keep_using = true) noexcept#
Holds a static variable which controls whether memory blocks (dataBlock) are put into a store or new/deleted each time.
The variable is initialised to true on first use, but can be set to false by passing “false” as input. Once set to false it can’t be changed back to true.
static inline void cleanup()#
Delete all data from the store and disable the store
Note: After this is called the store cannot be re-enabled
inline dataPtrType get(size_type len)#
Returns a pointer to a dataBlock object of size
lenwith no references. This is either from the store, or newly allocated
inline void release(dataPtrType &d) noexcept#
Release an dataBlock object, reducing its reference count by one. If no more references, then put back into the store. It’s important to pass a reference to the pointer, otherwise we get a copy of the shared_ptr, which therefore increases the use count and doesn’t allow us to free the pass pointer directly
Note that this is noexcept only because we’ve ensure that both a) store()[<size>] already exists, and b) it has space for at least one data block. Of course, store() could throw — in which case we’re doomed anyway, so the only thing we can do is abort
Private Static Functions
static inline storeType &store(bool cleanup = false)#
This maps from array size (size_type) to vectors of pointers to dataBlock objects
By putting the static store inside a function it is initialised on first use, and doesn’t need to be separately declared for each type T
cleanup – [in] If set to true, deletes all dataBlock and clears the store