Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/corecel/data/CollectionBuilder.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/data/CollectionBuilder.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <initializer_list>
0010 #include <limits>
0011 
0012 #include "corecel/Config.hh"
0013 
0014 #include "Collection.hh"
0015 
0016 #include "detail/FillInvalid.hh"
0017 
0018 namespace celeritas
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Helper class for constructing Collection objects.
0023  *
0024  * This is intended for use with host data but can also be used to resize
0025  * device collections. It's constructed with a reference to the host
0026  * collection, and it provides vector-like methods for extending it. The size
0027  * *cannot* be decreased because that would invalidate previously created \c
0028  * ItemRange items.
0029  *
0030  * \code
0031     auto cb = make_builder(&myintcol.host);
0032     cb.reserve(100);
0033     ItemRange<int> insertion
0034         = cb.insert_back(local_ints.begin(), local_ints.end());
0035     cb.push_back(123);
0036    \endcode
0037 
0038  * The CollectionBuilder can also be used to resize device-value collections
0039  * without having to allocate a host version and copy to device. (This is
0040  * useful for state allocations.) When resizing values with debugging
0041  * assertions enabled on host memory, it will assign garbage values to aid in
0042  * reproducible debugging.)
0043  */
0044 template<class T, MemSpace M = MemSpace::host, class I = ItemId<T>>
0045 class CollectionBuilder
0046 {
0047   public:
0048     //!@{
0049     //! \name Type aliases
0050     using CollectionT = Collection<T, Ownership::value, M, I>;
0051     using value_type = T;
0052     using size_type = typename CollectionT::size_type;
0053     using ItemIdT = typename CollectionT::ItemIdT;
0054     using ItemRangeT = typename CollectionT::ItemRangeT;
0055     //!@}
0056 
0057   public:
0058     //! Construct from a collection
0059     explicit CollectionBuilder(CollectionT* collection) : col_(*collection)
0060     {
0061         CELER_EXPECT(collection);
0062     }
0063 
0064     // Increase size to this capacity
0065     inline void resize(std::size_t count);
0066 
0067     // Reserve space
0068     inline void reserve(std::size_t count);
0069 
0070     // Extend with a series of elements, returning the range inserted
0071     template<class InputIterator>
0072     inline ItemRangeT insert_back(InputIterator first, InputIterator last);
0073 
0074     // Extend with a series of elements from an initializer list
0075     inline ItemRangeT insert_back(std::initializer_list<value_type> init);
0076 
0077     // Append a single element
0078     inline ItemIdT push_back(value_type const& element);
0079 
0080     //! Number of elements in the collection
0081     size_type size() const { return col_.size(); }
0082 
0083     //! Get the size as an ID type
0084     ItemIdT size_id() const { return ItemIdT{size()}; }
0085 
0086   private:
0087     //!@{
0088     //! Access storage
0089     using StorageT = typename CollectionT::StorageT;
0090     StorageT& storage() { return col_.storage(); }
0091     StorageT const& storage() const { return col_.storage(); }
0092     //!@}
0093 
0094     //! Maximum elements in a Collection
0095     static constexpr std::size_t max_size()
0096     {
0097         return std::numeric_limits<size_type>::max();
0098     }
0099 
0100     CollectionT& col_;
0101 };
0102 
0103 //---------------------------------------------------------------------------//
0104 // DEDUCTION GUIDES
0105 //---------------------------------------------------------------------------//
0106 
0107 template<class T, MemSpace M, class I>
0108 CollectionBuilder(Collection<T, Ownership::value, M, I>*)
0109     -> CollectionBuilder<T, M, I>;
0110 
0111 //---------------------------------------------------------------------------//
0112 // INLINE DEFINITIONS
0113 //---------------------------------------------------------------------------//
0114 /*!
0115  * Reserve space for the given number of elements.
0116  */
0117 template<class T, MemSpace M, class I>
0118 void CollectionBuilder<T, M, I>::reserve(std::size_t count)
0119 {
0120     CELER_EXPECT(count <= max_size());
0121     static_assert(M == MemSpace::host,
0122                   "Reserve currently works only for host memory");
0123     this->storage().reserve(count);
0124 }
0125 
0126 //---------------------------------------------------------------------------//
0127 /*!
0128  * Insert the given elements at the end of the allocation.
0129  */
0130 template<class T, MemSpace M, class I>
0131 template<class InputIterator>
0132 auto CollectionBuilder<T, M, I>::insert_back(InputIterator first,
0133                                              InputIterator last) -> ItemRangeT
0134 {
0135     CELER_EXPECT(std::distance(first, last) + this->storage().size()
0136                  <= this->max_size());
0137     static_assert(M == MemSpace::host,
0138                   "Insertion currently works only for host memory");
0139     auto start = this->size_id();
0140     this->storage().insert(this->storage().end(), first, last);
0141     return {start, this->size_id()};
0142 }
0143 
0144 //---------------------------------------------------------------------------//
0145 /*!
0146  * Insert the given list of elements at the end of the allocation.
0147  */
0148 template<class T, MemSpace M, class I>
0149 auto CollectionBuilder<T, M, I>::insert_back(std::initializer_list<T> init)
0150     -> ItemRangeT
0151 {
0152     return this->insert_back(init.begin(), init.end());
0153 }
0154 
0155 //---------------------------------------------------------------------------//
0156 /*!
0157  * Add a new element to the end of the allocation.
0158  */
0159 template<class T, MemSpace M, class I>
0160 auto CollectionBuilder<T, M, I>::push_back(T const& el) -> ItemIdT
0161 {
0162     CELER_EXPECT(this->storage().size() + 1 <= this->max_size());
0163     static_assert(M == MemSpace::host,
0164                   "Insertion currently works only for host memory");
0165     auto result = this->size_id();
0166     this->storage().push_back(el);
0167     return result;
0168 }
0169 
0170 //---------------------------------------------------------------------------//
0171 /*!
0172  * Increase the size to the given number of elements.
0173  */
0174 template<class T, MemSpace M, class I>
0175 void CollectionBuilder<T, M, I>::resize(std::size_t count)
0176 {
0177     CELER_EXPECT(this->storage().empty());
0178     CELER_EXPECT(count <= max_size());
0179     this->storage() = StorageT(count);
0180     if constexpr (CELERITAS_DEBUG && M == MemSpace::host)
0181     {
0182         // Fill with invalid values to help with debugging on host
0183         detail::fill_invalid(&col_);
0184     }
0185 }
0186 
0187 //---------------------------------------------------------------------------//
0188 /*!
0189  * Helper function for constructing collection builders.
0190  *
0191  * (Will not be needed under C++17's template argument deduction).
0192  */
0193 template<class T, MemSpace M, class I>
0194 CollectionBuilder<T, M, I>
0195 make_builder(Collection<T, Ownership::value, M, I>* collection)
0196 {
0197     CELER_EXPECT(collection);
0198     return CollectionBuilder<T, M, I>(collection);
0199 }
0200 
0201 //---------------------------------------------------------------------------//
0202 /*!
0203  * Helper function for resizing a single collection.
0204  *
0205  * This is useful for analogy to the resize method defined for states.
0206  */
0207 template<class T, MemSpace M, class I>
0208 void resize(Collection<T, Ownership::value, M, I>* collection, std::size_t size)
0209 {
0210     CELER_EXPECT(collection);
0211     CollectionBuilder<T, M, I>(collection).resize(size);
0212 }
0213 
0214 //---------------------------------------------------------------------------//
0215 }  // namespace celeritas