GEOSX
bufferManipulation.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, Lawrence Livermore National Security, LLC and LvArray contributors.
3  * All rights reserved.
4  * See the LICENSE file for details.
5  * SPDX-License-Identifier: (BSD-3-Clause)
6  */
7 
13 #pragma once
14 
15 // Source includes
16 #include "LvArrayConfig.hpp"
17 #include "Macros.hpp"
18 #include "typeManipulation.hpp"
19 #include "arrayManipulation.hpp"
20 
21 // System includes
22 #include <utility>
23 
24 namespace LvArray
25 {
26 
31 enum class MemorySpace
32 {
33  NONE
34  , CPU
35 #if defined(LVARRAY_USE_CUDA)
36  , GPU
37 #endif
38 };
39 
46 inline std::ostream & operator<<( std::ostream & os, MemorySpace const space )
47 {
48  if( space == MemorySpace::NONE )
49  os << "NONE";
50  if( space == MemorySpace::CPU )
51  os << "CPU";
52 #if defined(LVARRAY_USE_CUDA)
53  if( space == MemorySpace::GPU )
54  os << "GPU";
55 #endif
56  return os;
57 }
58 
63 namespace bufferManipulation
64 {
65 
71 HAS_MEMBER_FUNCTION_NO_RTYPE( move, MemorySpace::CPU, true );
72 
79 struct VoidBuffer
80 {
89  void moveNested( MemorySpace const space, std::ptrdiff_t const size, bool const touch ) const
90  {
92  LVARRAY_UNUSED_VARIABLE( touch );
93  LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::CPU, "This Buffer type can only be used on the CPU." );
94  }
95 
103  void move( MemorySpace const space, bool const touch ) const
104  {
105  LVARRAY_UNUSED_VARIABLE( touch );
106  LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::CPU, "This Buffer type can only be used on the CPU." );
107  }
108 
115  void registerTouch( MemorySpace const space ) const
116  { LVARRAY_ERROR_IF_NE_MSG( space, MemorySpace::CPU, "This Buffer type can only be used on the CPU." ); }
117 
123  template< typename=VoidBuffer >
125  void setName( std::string const & name )
126  { LVARRAY_UNUSED_VARIABLE( name ); }
127 };
128 
136 template< typename BUFFER >
138 void check( BUFFER const & buf, std::ptrdiff_t const size )
139 {
140 #ifdef LVARRAY_BOUNDS_CHECK
141  LVARRAY_ERROR_IF_GT( 0, buf.capacity() );
142  LVARRAY_ERROR_IF_GT( 0, size );
143  LVARRAY_ERROR_IF_GT( size, buf.capacity() );
144 #else
145  LVARRAY_DEBUG_VAR( buf );
146  LVARRAY_DEBUG_VAR( size );
147 #endif
148 }
149 
158 template< typename BUFFER >
159 inline
160 void checkInsert( BUFFER const & buf, std::ptrdiff_t const size, std::ptrdiff_t const pos )
161 {
162 #ifdef LVARRAY_BOUNDS_CHECK
163  check( buf, size );
164  LVARRAY_ERROR_IF_GT( 0, pos );
165  LVARRAY_ERROR_IF_GT( pos, size );
166 #else
167  LVARRAY_DEBUG_VAR( buf );
168  LVARRAY_DEBUG_VAR( size );
169  LVARRAY_DEBUG_VAR( pos );
170 #endif
171 }
172 
180 template< typename BUFFER >
182 void free( BUFFER & buf, std::ptrdiff_t const size )
183 {
184  using T = typename BUFFER::value_type;
185 
186  check( buf, size );
187 
188  if( !std::is_trivially_destructible< T >::value )
189  {
190  buf.move( MemorySpace::CPU, true );
191  arrayManipulation::destroy( buf.data(), size );
192  }
193 
194  buf.free();
195 }
196 
205 template< typename BUFFER >
207 void setCapacity( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity )
208 {
209  check( buf, size );
210  buf.reallocate( size, newCapacity );
211 }
212 
220 template< typename BUFFER >
222 void reserve( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity )
223 {
224  check( buf, size );
225 
226  if( newCapacity > buf.capacity() )
227  {
228  setCapacity( buf, size, newCapacity );
229  }
230 }
231 
242 template< typename BUFFER >
243 void dynamicReserve( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity )
244 {
245  check( buf, size );
246 
247  if( newCapacity > buf.capacity() )
248  {
249  setCapacity( buf, size, 2 * newCapacity );
250  }
251 }
252 
264 template< typename BUFFER, typename ... ARGS >
266 void resize( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS && ... args )
267 {
268  check( buf, size );
269 
270  reserve( buf, size, newSize );
271 
272  arrayManipulation::resize( buf.data(), size, newSize, std::forward< ARGS >( args )... );
273 
274 #if !defined(__CUDA_ARCH__)
275  if( newSize > 0 )
276  {
277  buf.registerTouch( MemorySpace::CPU );
278  }
279 #endif
280 }
281 
290 template< typename BUFFER, typename ... ARGS >
291 void emplaceBack( BUFFER & buf, std::ptrdiff_t const size, ARGS && ... args )
292 {
293  check( buf, size );
294 
295  dynamicReserve( buf, size, size + 1 );
296  arrayManipulation::emplaceBack( buf.data(), size, std::forward< ARGS >( args ) ... );
297 }
298 
308 template< typename BUFFER, typename ... ARGS >
309 void emplace( BUFFER & buf,
310  std::ptrdiff_t const size,
311  std::ptrdiff_t const pos,
312  ARGS && ... args )
313 {
314  checkInsert( buf, size, pos );
315 
316  dynamicReserve( buf, size, size + 1 );
317  arrayManipulation::emplace( buf.data(), size, pos, std::forward< ARGS >( args ) ... );
318 }
319 
331 template< typename BUFFER, typename ITER >
332 std::ptrdiff_t insert( BUFFER & buf,
333  std::ptrdiff_t const size,
334  std::ptrdiff_t const pos,
335  ITER const first,
336  ITER const last )
337 {
338  checkInsert( buf, size, pos );
339 
340  std::ptrdiff_t const nVals = arrayManipulation::iterDistance( first, last );
341  dynamicReserve( buf, size, size + nVals );
342  arrayManipulation::insert( buf.data(), size, pos, first, nVals );
343  return nVals;
344 }
345 
352 template< typename BUFFER >
353 void popBack( BUFFER & buf, std::ptrdiff_t const size )
354 {
355  check( buf, size );
356  arrayManipulation::popBack( buf.data(), size );
357 }
358 
366 template< typename BUFFER >
367 void erase( BUFFER & buf, std::ptrdiff_t const size, std::ptrdiff_t const pos )
368 {
369  check( buf, size );
370  LVARRAY_ERROR_IF_GE( pos, size );
371 
372  arrayManipulation::erase( buf.data(), size, pos, std::ptrdiff_t( 1 ) );
373 }
374 
385 template< typename DST_BUFFER, typename SRC_BUFFER >
387 void copyInto( DST_BUFFER & dst,
388  std::ptrdiff_t const dstSize,
389  SRC_BUFFER const & src,
390  std::ptrdiff_t const srcSize )
391 {
392  check( dst, dstSize );
393  check( src, srcSize );
394 
395  resize( dst, dstSize, srcSize );
396 
397  using T = typename DST_BUFFER::value_type;
398  T * const LVARRAY_RESTRICT dstData = dst.data();
399  T const * const LVARRAY_RESTRICT srcData = src.data();
400 
401  for( std::ptrdiff_t i = 0; i < srcSize; ++i )
402  {
403  dstData[ i ] = srcData[ i ];
404  }
405 }
406 
407 } // namespace bufferManipulations
408 } // namespace LvArray
constexpr void check(BUFFER const &buf, std::ptrdiff_t const size)
Check that given Buffer and size are valid.
#define LVARRAY_UNUSED_VARIABLE(X)
Mark X as an unused variable, used to silence compiler warnings.
Definition: Macros.hpp:51
void emplace(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos, ARGS &&... args)
Construct a new value at position pos.
constexpr std::iterator_traits< ITER >::difference_type iterDistance(ITER first, ITER const last, std::input_iterator_tag)
std::ptrdiff_t insert(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos, ITER const first, ITER const last)
Insert multiple values into the buffer.
void reserve(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
Reserve space in the buffer for at least the given capacity.
void emplaceBack(BUFFER &buf, std::ptrdiff_t const size, ARGS &&... args)
Construct a new value at the end of the buffer.
This class implements the default behavior for the Buffer methods related to execution space...
void dynamicReserve(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
If the buffer&#39;s capacity is greater than newCapacity this is a no-op. Otherwise the buffer&#39;s capacity...
Contains templates useful for type manipulation.
void setName(std::string const &name)
Set the name associated with this buffer.
#define LVARRAY_ERROR_IF_NE_MSG(lhs, rhs, msg)
Raise a hard error if two values are not equal.
Definition: Macros.hpp:230
void copyInto(DST_BUFFER &dst, std::ptrdiff_t const dstSize, SRC_BUFFER const &src, std::ptrdiff_t const srcSize)
Copy values from the source buffer into the destination buffer.
void popBack(BUFFER &buf, std::ptrdiff_t const size)
Remove a value from the end of the buffer.
#define CONSTEXPR_WITHOUT_BOUNDS_CHECK
Expands to constexpr when array bound checking is disabled.
Definition: Macros.hpp:449
void destroy(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destory the values in the array.
#define LVARRAY_ERROR_IF_GT(lhs, rhs)
Raise a hard error if one value compares greater than the other.
Definition: Macros.hpp:252
void free(BUFFER &buf, std::ptrdiff_t const size)
Destroy the values in the buffer and free it&#39;s memory.
void checkInsert(BUFFER const &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos)
Check that given Buffer, size, and insertion position, are valid.
#define HAS_MEMBER_FUNCTION_NO_RTYPE(NAME,...)
Macro that expands to a static constexpr bool templated on a type that is only true when the type has...
void emplace(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ARGS &&... args)
Insert into the array constructing the new value in place.
void popBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size)
Destroy the value at the end of the array.
Contains functions for manipulating a contiguous array of values.
void move(MemorySpace const space, bool const touch) const
Move the buffer to the given execution space, optionally touching it.
#define LVARRAY_DEBUG_VAR(X)
Mark X as an debug variable, used to silence compiler warnings.
Definition: Macros.hpp:57
MemorySpace
An enum containing the available memory spaces.
void moveNested(MemorySpace const space, std::ptrdiff_t const size, bool const touch) const
Move the buffer to the given execution space, optionally touching it.
void setCapacity(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newCapacity)
Set the capacity of the buffer.
The top level namespace.
Definition: Array.hpp:24
void resize(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the give array.
Contains a bunch of macro definitions.
std::ostream & operator<<(std::ostream &os, MemorySpace const space)
Output a MemorySpace enum to a stream.
#define LVARRAY_ERROR_IF_GE(lhs, rhs)
Raise a hard error if one value compares greater than or equal to the other.
Definition: Macros.hpp:267
void erase(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, std::ptrdiff_t const n=1)
Shift the values in the array at or above the given position down by the given amount overwriting the...
void emplaceBack(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, ARGS &&... args)
Append the to the array constructing the new value in place.
std::string string
String type.
Definition: DataTypes.hpp:131
#define DISABLE_HD_WARNING
Disable host device warnings.
Definition: Macros.hpp:401
void insert(T *const LVARRAY_RESTRICT ptr, std::ptrdiff_t const size, std::ptrdiff_t const index, ITERATOR first, std::ptrdiff_t const n)
Insert the given values into the array at the given position.
void erase(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const pos)
Erase a value from the buffer.
void registerTouch(MemorySpace const space) const
Touch the buffer in the given space.
void resize(BUFFER &buf, std::ptrdiff_t const size, std::ptrdiff_t const newSize, ARGS &&... args)
Resize the buffer to the given size.
#define LVARRAY_HOST_DEVICE
Mark a function for both host and device usage.
Definition: Macros.hpp:389