Arcane  4.2.1.0
User documentation
Loading...
Searching...
No Matches
AbstractArray.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* AbstractArray.h (C) 2000-2026 */
9/* */
10/* Base class for arrays. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_COMMON_ABSTRACTARRAY_H
13#define ARCCORE_COMMON_ABSTRACTARRAY_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arccore/base/Span.h"
18
19#include "arccore/common/ArrayTraits.h"
20#include "arccore/common/ArrayMetaData.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30/*!
31 * \brief Internal base class for arrays.
32 *
33 * This class only manages metadata for arrays such as
34 * the number of elements or capacity.
35 *
36 * \a m_md is a pointer containing the array's metadata. If the
37 * array is shared (SharedArray, SharedArray2), then this pointer
38 * is dynamically allocated and in this case _isUseOwnMetaData() must
39 * return \a false. If the array is not shared (UniqueArray or
40 * UniqueArray2), then the metadata is kept directly
41 * in the array instance to avoid unnecessary allocations
42 * and \a m_md then points to \a m_meta_data. In all cases, you
43 * must not use \a m_meta_data directly, but always go through
44 * \a m_md.
45 */
46class ARCCORE_COMMON_EXPORT AbstractArrayBase
47{
48 public:
49
50 AbstractArrayBase()
51 {
52 m_md = &m_meta_data;
53 }
54 virtual ~AbstractArrayBase() = default;
55
56 public:
57
58 IMemoryAllocator* allocator() const
59 {
60 return m_md->allocation_options.allocator();
61 }
62 MemoryAllocationOptions allocationOptions() const
63 {
64 return m_md->allocation_options;
65 }
66 /*!
67 * \brief Sets the array name for debug information.
68 *
69 * This name can be used, for example, for listing displays.
70 */
71 void setDebugName(const String& name);
72 //! Debug name (null if no name specified)
73 String debugName() const;
74
75 void printInfos(std::ostream& o);
76
77 protected:
78
79 ArrayMetaData* m_md = nullptr;
80 ArrayMetaData m_meta_data;
81
82 protected:
83
84 //! Explicit method for a null RunQueue.
85 static constexpr RunQueue* _nullRunQueue() { return nullptr; }
86
87 /*!
88 * \brief Indicates if \a m_md refers to \a m_meta_data.
89 *
90 * This is the case for UniqueArray and UniqueArray2 but
91 * not for SharedArray and SharedArray2.
92 */
93 virtual bool _isUseOwnMetaData() const
94 {
95 return true;
96 }
97
98 protected:
99
100 void _swapMetaData(AbstractArrayBase& rhs)
101 {
102 std::swap(m_md, rhs.m_md);
103 std::swap(m_meta_data, rhs.m_meta_data);
104 _checkSetUseOwnMetaData();
105 rhs._checkSetUseOwnMetaData();
106 }
107
108 void _copyMetaData(const AbstractArrayBase& rhs)
109 {
110 // Move the metadata
111 // Note if m_meta_data is used, m_md must be set to point to our own m_meta_data.
112 m_meta_data = rhs.m_meta_data;
113 m_md = rhs.m_md;
114 _checkSetUseOwnMetaData();
115 }
116
117 void _allocateMetaData()
118 {
119#ifdef ARCCORE_CHECK
120 if (m_md->is_not_null)
121 ArrayMetaData::throwNullExpected();
122#endif
123 if (_isUseOwnMetaData()) {
124 m_meta_data = ArrayMetaData();
125 m_md = &m_meta_data;
126 }
127 else {
128 m_md = new ArrayMetaData();
129 m_md->is_allocated_by_new = true;
130 }
131 m_md->is_not_null = true;
132 }
133
134 void _deallocateMetaData(ArrayMetaData* md)
135 {
136 if (md->is_allocated_by_new)
137 delete md;
138 else
139 *md = ArrayMetaData();
140 }
141
142 void _checkValidSharedArray()
143 {
144#ifdef ARCCORE_CHECK
145 if (m_md->is_not_null && !m_md->is_allocated_by_new)
146 ArrayMetaData::throwInvalidMetaDataForSharedArray();
147#endif
148 }
149
150 private:
151
152 void _checkSetUseOwnMetaData()
153 {
154 if (!m_md->is_allocated_by_new)
155 m_md = &m_meta_data;
156 }
157};
158
159/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
162/*!
163 * \ingroup Collection
164 * \brief Abstract base class for a vector.
165 *
166 * This class cannot be used directly. To use a
167 * vector, choose the SharedArray or UniqueArray class.
168 */
169template <typename T>
171: public AbstractArrayBase
172{
173 public:
174
175 typedef typename ArrayTraits<T>::ConstReferenceType ConstReferenceType;
176 typedef typename ArrayTraits<T>::IsPODType IsPODType;
177 typedef AbstractArray<T> ThatClassType;
178 using TrueImpl = T;
179
180 public:
181
182 //! Type of the array elements
183 typedef T value_type;
184 //! Pointer type of an array element
186 //! Constant pointer type of an array element
187 typedef const value_type* const_pointer;
188 //! Type of the iterator over an array element
190 //! Type of the constant iterator over an array element
192 //! Type reference of an array element
194 //! Type constant reference of an array element
195 typedef ConstReferenceType const_reference;
196 //! Type indexing the array
198 //! Type of a distance between array element iterators
199 typedef ptrdiff_t difference_type;
200
201 typedef std::reverse_iterator<iterator> reverse_iterator;
202 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
203
204 protected:
205
206 //! Constructs an empty vector with the default allocator
208 {
209 }
210 //! Move constructor. Should only be used by UniqueArray
211 AbstractArray(ThatClassType&& rhs) ARCCORE_NOEXCEPT
212 : m_ptr(rhs.m_ptr)
213 {
214 _copyMetaData(rhs);
215 rhs._reset();
216 }
217
218 ~AbstractArray() override
219 {
220 --m_md->nb_ref;
222 }
223
224 public:
225
226 AbstractArray(const AbstractArray<T>& rhs) = delete;
227 AbstractArray<T>& operator=(const AbstractArray<T>& rhs) = delete;
228
229 protected:
230
231 static constexpr Int64 typeSize() { return static_cast<Int64>(sizeof(T)); }
232 AllocatedMemoryInfo _currentMemoryInfo() const
233 {
234 return AllocatedMemoryInfo(m_ptr, m_md->size * typeSize(), m_md->capacity * typeSize());
235 }
236
237 protected:
238
239 /*!
240 * \brief Initializes the array with the view \a view.
241 *
242 * This method must only be called in a derived class constructor.
243 */
244 void _initFromSpan(const Span<const T>& view)
245 {
246 Int64 asize = view.size();
247 if (asize != 0) {
248 _internalAllocate(asize, _nullRunQueue());
249 _createRange(0, asize, view.data());
250 m_md->size = asize;
251 }
252 }
253
254 /*!
255 * \brief Constructs an empty vector with a specific allocator \a a.
256 *
257 * If \a acapacity is not null, memory is allocated to
258 * hold \a acapacity elements (but the array remains empty).
259 *
260 * This method must only be called in a derived class constructor
261 * and only by classes using UniqueArray semantics.
262 */
264 void* pre_allocated_buffer = nullptr)
265 {
266 _directFirstAllocateWithAllocator(acapacity, o, pre_allocated_buffer);
267 }
268
269 public:
270
271 //! Frees the memory used by the array.
272 void dispose()
273 {
274 _destroy();
275 MemoryAllocationOptions options(m_md->allocation_options);
276 _internalDeallocate();
277 _setToSharedNull();
278 // If we have a specific allocator, we must allocate a
279 // block to keep this information.
280 if (options.allocator() != m_md->_allocator())
281 _directFirstAllocateWithAllocator(0, options);
283 }
284
285 public:
286
287 operator ConstArrayView<T>() const
288 {
289 return ConstArrayView<T>(ARCCORE_CAST_SMALL_SIZE(size()), m_ptr);
290 }
291 operator Span<const T>() const
292 {
293 return Span<const T>(m_ptr, m_md->size);
294 }
295 operator SmallSpan<const T>() const
296 {
297 return SmallSpan<const T>(m_ptr, ARCCORE_CAST_SMALL_SIZE(size()));
298 }
299
300 public:
301
302 //! Number of elements in the vector
303 Integer size() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
304 //! Number of elements in the vector
305 Integer length() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
306 //! Capacity (number of allocated elements) of the vector
307 Integer capacity() const { return ARCCORE_CAST_SMALL_SIZE(m_md->capacity); }
308 //! Number of elements in the vector (in 64 bits)
309 Int64 largeSize() const { return m_md->size; }
310 //! Number of elements in the vector (in 64 bits)
311 Int64 largeLength() const { return m_md->size; }
312 //! Capacity (number of allocated elements) of the vector (in 64 bits)
313 Int64 largeCapacity() const { return m_md->capacity; }
314 //! Capacity (number of allocated elements) of the vector
315 bool empty() const { return m_md->size == 0; }
316 //! True if the array contains the value element \a v
317 bool contains(ConstReferenceType v) const
318 {
319 const T* ptr = m_ptr;
320 for (Int64 i = 0, n = m_md->size; i < n; ++i) {
321 if (ptr[i] == v)
322 return true;
323 }
324 return false;
325 }
326
327 public:
328
329 //! Element at index \a i
330 ConstReferenceType operator[](Int64 i) const
331 {
332 ARCCORE_CHECK_AT(i, m_md->size);
333 return m_ptr[i];
334 }
335 //! Element at index \a i
336 ConstReferenceType operator()(Int64 i) const
337 {
338 ARCCORE_CHECK_AT(i, m_md->size);
339 return m_ptr[i];
340 }
341
342 public:
343
344 //! Modifies the memory location information
346 {
347 m_md->_setMemoryLocationHint(new_hint, m_ptr, sizeof(T));
348 }
349
350 /*!
351 * \brief Sets the physical location of the memory region.
352 *
353 * \warning The caller must guarantee consistency between the allocator
354 * and the specified memory region.
355 */
357 {
358 m_md->m_host_device_memory_location = location;
359 }
360
361 //! Sets the physical location of the memory region.
363 {
364 return m_md->m_host_device_memory_location;
365 }
366
367 public:
368
369 friend bool operator==(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
370 {
371 return operator==(Span<const T>(rhs), Span<const T>(lhs));
372 }
373
374 friend bool operator!=(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
375 {
376 return !(rhs == lhs);
377 }
378
379 friend bool operator==(const AbstractArray<T>& rhs, const Span<const T>& lhs)
380 {
381 return operator==(Span<const T>(rhs), lhs);
382 }
383
384 friend bool operator!=(const AbstractArray<T>& rhs, const Span<const T>& lhs)
385 {
386 return !(rhs == lhs);
387 }
388
389 friend bool operator==(const Span<const T>& rhs, const AbstractArray<T>& lhs)
390 {
391 return operator==(rhs, Span<const T>(lhs));
392 }
393
394 friend bool operator!=(const Span<const T>& rhs, const AbstractArray<T>& lhs)
395 {
396 return !(rhs == lhs);
397 }
398
399 friend std::ostream& operator<<(std::ostream& o, const AbstractArray<T>& val)
400 {
401 o << Span<const T>(val);
402 return o;
403 }
404
405 private:
406
407 using AbstractArrayBase::m_meta_data;
408
409 protected:
410
411 // NOTE: These two fields are used for the TTF display of totalview.
412 // If their order is changed, the corresponding part must be updated
413 // in Arcane's totalview displayer.
414 T* m_ptr = nullptr;
415
416 protected:
417
418 //! Reserves memory for \a new_capacity elements
419 void _reserve(Int64 new_capacity)
420 {
421 if (new_capacity <= m_md->capacity) {
422 // In the case of a collective allocator, we still have to perform a
423 // realloc (the allocator must handle the optimization).
424 if (m_meta_data.is_collective_allocator) {
425 _internalRealloc(m_md->capacity, false);
426 }
427 return;
428 }
429 _internalRealloc(new_capacity, false);
430 }
431 /*!
432 * \brief Reallocates the array for a new capacity equal to \a new_capacity.
433 *
434 * If the new capacity is less than the old one, nothing happens.
435 */
436 void _internalRealloc(Int64 new_capacity, bool compute_capacity, RunQueue* queue = nullptr)
437 {
438 // Note: For shared memory, if one of the pointers is nullptr, then
439 // it is for all processes.
440 if (_isSharedNull()) {
441 if (new_capacity != 0 || m_meta_data.is_collective_allocator)
442 _internalAllocate(new_capacity, queue);
443 return;
444 }
445
446 Int64 acapacity = new_capacity;
447 if (compute_capacity) {
448 acapacity = m_md->capacity;
449 //std::cout << " REALLOC: want=" << wanted_size << " current_capacity=" << capacity << '\n';
450 while (new_capacity > acapacity)
451 acapacity = (acapacity == 0) ? 4 : (acapacity + 1 + acapacity / 2);
452 //std::cout << " REALLOC: want=" << wanted_size << " new_capacity=" << capacity << '\n';
453 }
454 // If the new capacity is less than the current one, do nothing
455 // (except for a collective allocator).
456 if (acapacity <= m_md->capacity) {
457 if (m_meta_data.is_collective_allocator) {
458 _internalReallocate(m_md->capacity, queue);
459 }
460 return;
461 }
462 _internalReallocate(acapacity, queue);
463 }
464
465 void _internalReallocate(Int64 new_capacity, RunQueue* queue)
466 {
467 if constexpr (std::is_trivially_copyable_v<T>) {
468 T* old_ptr = m_ptr;
469 Int64 old_capacity = m_md->capacity;
470 _directReAllocate(new_capacity, queue);
471 bool update = (new_capacity < old_capacity) || (m_ptr != old_ptr);
472 if (update) {
474 }
475 }
476 else {
477 T* old_ptr = m_ptr;
478 ArrayMetaData* old_md = m_md;
479 AllocatedMemoryInfo old_mem_info = _currentMemoryInfo();
480 Int64 old_size = m_md->size;
481 _directAllocate(new_capacity, queue);
482 if (m_ptr != old_ptr) {
483 for (Int64 i = 0; i < old_size; ++i) {
484 new (m_ptr + i) T(old_ptr[i]);
485 old_ptr[i].~T();
486 }
487 m_md->nb_ref = old_md->nb_ref;
488 m_md->_deallocate(old_mem_info, queue);
490 }
491 }
492 }
493
494 // Frees the memory
495 void _internalDeallocate(RunQueue* queue = nullptr)
496 {
497 // Note: For shared memory, if one of the pointers is nullptr, then
498 // it is for all processes.
499 if (!_isSharedNull())
500 m_md->_deallocate(_currentMemoryInfo(), queue);
501 if (m_md->is_not_null)
502 _deallocateMetaData(m_md);
503 }
504 void _internalAllocate(Int64 new_capacity, RunQueue* queue)
505 {
506 _directAllocate(new_capacity, queue);
507 m_md->nb_ref = _getNbRef();
509 }
510
511 void _copyFromMemory(const T* source)
512 {
513 m_md->_copyFromMemory(m_ptr, source, sizeof(T), _nullRunQueue());
514 }
515
516 private:
517
518 /*!
519 * \brief Performs the first allocation.
520 *
521 * If \a pre_allocated_buffer is not null, it is used as a buffer
522 * for the first allocation. The caller must ensure that
523 * this buffer is valid for the requested capacity. \a pre_allocated_buffer
524 * is notably used by the SmallArray allocator.
525 */
526 void _directFirstAllocateWithAllocator(Int64 new_capacity, MemoryAllocationOptions options,
527 void* pre_allocated_buffer = nullptr)
528 {
529 IMemoryAllocator* wanted_allocator = options.allocator();
530 if (!wanted_allocator) {
531 wanted_allocator = ArrayMetaData::_defaultAllocator();
532 options.setAllocator(wanted_allocator);
533 }
534 _allocateMetaData();
535 m_md->allocation_options = options;
536 if (new_capacity > 0) {
537 if (!pre_allocated_buffer)
538 _allocateMP(new_capacity, nullptr);
539 else
540 _setMPCast(pre_allocated_buffer);
541 }
542 m_md->nb_ref = _getNbRef();
543 m_md->size = 0;
545 }
546
547 void _directAllocate(Int64 new_capacity, RunQueue* queue)
548 {
549 if (!m_md->is_not_null)
550 _allocateMetaData();
551 _allocateMP(new_capacity, queue);
552 }
553
554 void _allocateMP(Int64 new_capacity, RunQueue* queue)
555 {
556 _setMPCast(m_md->_allocate(new_capacity, typeSize(), queue));
557 }
558
559 void _directReAllocate(Int64 new_capacity, RunQueue* queue)
560 {
561 _setMPCast(m_md->_reallocate(_currentMemoryInfo(), new_capacity, typeSize(), queue));
562 }
563
564 public:
565
566 void changeAllocator(const MemoryAllocationOptions& options, RunQueue* queue)
567 {
568 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), queue));
570 }
571
572 void changeAllocator(const MemoryAllocationOptions& options)
573 {
574 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), _nullRunQueue()));
576 }
577
578 protected:
579
580 //! Update references
581 virtual void _updateReferences()
582 {
583 }
584 //! Update references
586 {
587 return 1;
588 }
589 //! Adds n elements of value val to the end of the array
590 void _addRange(ConstReferenceType val, Int64 n)
591 {
592 Int64 s = m_md->size;
593 if ((s + n) > m_md->capacity)
594 _internalRealloc(s + n, true);
595 for (Int64 i = 0; i < n; ++i)
596 new (m_ptr + s + i) T(val);
597 m_md->size += n;
598 }
599
600 //! Adds n elements of value val to the end of the array
602 {
603 Int64 n = val.size();
604 const T* ptr = val.data();
605 Int64 s = m_md->size;
606 if ((s + n) > m_md->capacity)
607 _internalRealloc(s + n, true);
608 _createRange(s, s + n, ptr);
609 m_md->size += n;
610 }
611
612 //! Destroys the instance if no one references it
614 {
615 if (m_md->nb_ref == 0) {
616 _destroy();
617 _internalDeallocate(_nullRunQueue());
618 }
619 }
620 void _destroy()
621 {
622 _destroyRange(0, m_md->size, IsPODType());
623 }
624 void _destroyRange(Int64, Int64, TrueType)
625 {
626 // Nothing to do for a POD type.
627 }
628 void _destroyRange(Int64 abegin, Int64 aend, FalseType)
629 {
630 if (abegin < 0)
631 abegin = 0;
632 for (Int64 i = abegin; i < aend; ++i)
633 m_ptr[i].~T();
634 }
635 void _createRangeDefault(Int64, Int64, TrueType)
636 {
637 }
638 void _createRangeDefault(Int64 abegin, Int64 aend, FalseType)
639 {
640 if (abegin < 0)
641 abegin = 0;
642 for (Int64 i = abegin; i < aend; ++i)
643 new (m_ptr + i) T();
644 }
645 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, TrueType)
646 {
647 if (abegin < 0)
648 abegin = 0;
649 for (Int64 i = abegin; i < aend; ++i)
650 m_ptr[i] = value;
651 }
652 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, FalseType)
653 {
654 if (abegin < 0)
655 abegin = 0;
656 for (Int64 i = abegin; i < aend; ++i)
657 new (m_ptr + i) T(value);
658 }
659 void _createRange(Int64 abegin, Int64 aend, const T* values)
660 {
661 if (abegin < 0)
662 abegin = 0;
663 for (Int64 i = abegin; i < aend; ++i) {
664 new (m_ptr + i) T(*values);
665 ++values;
666 }
667 }
668 void _fill(ConstReferenceType value)
669 {
670 for (Int64 i = 0, n = size(); i < n; ++i)
671 m_ptr[i] = value;
672 }
673 void _clone(const ThatClassType& orig_array)
674 {
675 Int64 that_size = orig_array.size();
676 _internalAllocate(that_size, _nullRunQueue());
677 m_md->size = that_size;
678 m_md->dim1_size = orig_array.m_md->dim1_size;
679 m_md->dim2_size = orig_array.m_md->dim2_size;
680 _createRange(0, that_size, orig_array.m_ptr);
681 }
682 template <typename PodType>
683 void _resizeHelper(Int64 s, PodType pod_type, RunQueue* queue)
684 {
685 if (s < 0)
686 s = 0;
687 if (s > m_md->size) {
688 this->_internalRealloc(s, false, queue);
689 this->_createRangeDefault(m_md->size, s, pod_type);
690 }
691 else {
692 this->_destroyRange(s, m_md->size, pod_type);
693 if (m_meta_data.is_collective_allocator) {
694 this->_internalRealloc(s, false, queue);
695 }
696 }
697 m_md->size = s;
698 }
699 void _resize(Int64 s)
700 {
701 _resizeHelper(s, IsPODType(), _nullRunQueue());
702 }
703 //! Redimensionne sans initialiser les nouvelles valeurs
704 void _resizeNoInit(Int64 s, RunQueue* queue = nullptr)
705 {
706 _resizeHelper(s, TrueType{}, queue);
707 }
708 void _clear()
709 {
710 this->_destroyRange(0, m_md->size, IsPODType());
711 m_md->size = 0;
712 }
713 //! Redimensionne et remplit les nouvelles valeurs avec \a value
714 void _resize(Int64 s, ConstReferenceType value)
715 {
716 if (s < 0)
717 s = 0;
718 if (s > m_md->size) {
719 this->_internalRealloc(s, false);
720 this->_createRange(m_md->size, s, value, IsPODType());
721 }
722 else {
723 this->_destroyRange(s, m_md->size, IsPODType());
724 if (m_meta_data.is_collective_allocator) {
725 this->_internalRealloc(s, false);
726 }
727 }
728 m_md->size = s;
729 }
730 void _copy(const T* rhs_begin, TrueType)
731 {
732 _copyFromMemory(rhs_begin);
733 }
734 void _copy(const T* rhs_begin, FalseType)
735 {
736 for (Int64 i = 0, n = m_md->size; i < n; ++i)
737 m_ptr[i] = rhs_begin[i];
738 }
739 void _copy(const T* rhs_begin)
740 {
741 _copy(rhs_begin, IsPODType());
742 }
743
744 /*!
745 * \brief Redimensionne l'instance et recopie les valeurs de \a rhs.
746 *
747 * Si la taille diminue, les éléments compris entre size() et rhs.size()
748 * sont détruits.
749 *
750 * \post size()==rhs.size()
751 */
753 {
754 const T* rhs_begin = rhs.data();
755 Int64 rhs_size = rhs.size();
756 const Int64 current_size = m_md->size;
757 T* abegin = m_ptr;
758 // Vérifie que \a rhs n'est pas un élément à l'intérieur de ce tableau
759 if (abegin >= rhs_begin && abegin < (rhs_begin + rhs_size))
760 ArrayMetaData::overlapError(abegin, m_md->size, rhs_begin, rhs_size);
761
762 if (rhs_size > current_size) {
763 this->_internalRealloc(rhs_size, false);
764 // Crée les nouveaux éléments
765 this->_createRange(m_md->size, rhs_size, rhs_begin + current_size);
766 // Copie les éléments déjà existant
767 _copy(rhs_begin);
768 m_md->size = rhs_size;
769 }
770 else {
771 this->_destroyRange(rhs_size, current_size, IsPODType{});
772 m_md->size = rhs_size;
773 _copy(rhs_begin);
774 }
775 }
776
777 /*!
778 * \brief Implements the move assignment operator.
779 *
780 * This call is only valid for UniqueArray type arrays
781 * that have only one reference. The info from \a rhs is directly
782 * copied to this instance. In return, \a rhs contains an empty array.
783 */
784 void _move(ThatClassType& rhs) ARCCORE_NOEXCEPT
785 {
786 if (&rhs == this)
787 return;
788
789 // Comme il n'y a qu'une seule référence sur le tableau actuel, on peut
790 // directement libérer la mémoire.
791 _destroy();
792 _internalDeallocate(_nullRunQueue());
793
794 _setMP(rhs.m_ptr);
795
796 _copyMetaData(rhs);
797
798 // Indique que \a rhs est vide.
799 rhs._reset();
800 }
801 /*!
802 * \brief Swaps the values of the instance with those of \a rhs.
803 *
804 * This call is only valid for UniqueArray type arrays
805 * and the exchange is done only by swapping pointers. The operation
806 * is therefore constant complexity.
807 */
808 void _swap(ThatClassType& rhs) ARCCORE_NOEXCEPT
809 {
810 std::swap(m_ptr, rhs.m_ptr);
811 _swapMetaData(rhs);
812 }
813
814 void _shrink()
815 {
816 _shrink(size());
817 }
818
819 // Reallocates the memory to have a capacity close to \a new_capacity
820 void _shrink(Int64 new_capacity)
821 {
822 if (_isSharedNull())
823 return;
824 // On n'augmente pas la capacité avec cette méthode
825 if (new_capacity > this->capacity())
826 return;
827 if (new_capacity < 4)
828 new_capacity = 4;
829 _internalReallocate(new_capacity, _nullRunQueue());
830 }
831
832 /*!
833 * \brief Resets the array to an empty array.
834 * \warning This method is only valid for UniqueArray and not
835 * SharedArray.
836 */
837 void _reset()
838 {
839 _setToSharedNull();
840 }
841
842 constexpr Integer _clampSizeOffet(Int64 offset, Int32 asize) const
843 {
844 Int64 max_size = m_md->size - offset;
845 if (asize > max_size)
846 // On est certain de ne pas dépasser 32 bits car on est inférieur à asize.
847 asize = static_cast<Integer>(max_size);
848 return asize;
849 }
850
851 // Uniquement pour UniqueArray et UniqueArray2
852 void _assignFromArray(const AbstractArray<T>& rhs)
853 {
854 if (&rhs == this)
855 return;
856 Span<const T> rhs_span(rhs);
857 if (rhs.allocator() == this->allocator()) {
858 _resizeAndCopyView(rhs_span);
859 }
860 else {
861 _destroy();
862 _internalDeallocate(_nullRunQueue());
863 _reset();
864 _initFromAllocator(rhs.allocationOptions(), 0);
865 _initFromSpan(rhs_span);
866 }
867 }
868
869 protected:
870
871 void _setMP(TrueImpl* new_mp)
872 {
873 m_ptr = new_mp;
874 }
875
876 void _setMP2(TrueImpl* new_mp, ArrayMetaData* new_md)
877 {
878 _setMP(new_mp);
879 // Il ne faut garder le nouveau m_md que s'il est alloué
880 // sinon on risque d'avoir des références sur des objets temporaires
881 m_md = new_md;
882 if (!m_md->is_allocated_by_new)
883 m_md = &m_meta_data;
884 }
885
886 bool _isSharedNull()
887 {
888 return m_ptr == nullptr;
889 }
890
891 private:
892
893 void _setToSharedNull()
894 {
895 m_ptr = nullptr;
896 m_meta_data = ArrayMetaData();
897 m_md = &m_meta_data;
898 }
899 void _setMPCast(void* p)
900 {
901 _setMP(reinterpret_cast<TrueImpl*>(p));
902 }
903};
904
905/*---------------------------------------------------------------------------*/
906/*---------------------------------------------------------------------------*/
907
908} // namespace Arcane
909
910/*---------------------------------------------------------------------------*/
911/*---------------------------------------------------------------------------*/
912
913#endif
Types and functions associated with the classes SpanImpl, SmallSpan and Span.
Internal base class for arrays.
static constexpr RunQueue * _nullRunQueue()
Explicit method for a null RunQueue.
virtual bool _isUseOwnMetaData() const
Indicates if m_md refers to m_meta_data.
Abstract base class for a vector.
void _addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
Integer capacity() const
Capacity (number of allocated elements) of the vector.
void _addRange(Span< const T > val)
Adds n elements of value val to the end of the array.
void _internalSetHostDeviceMemoryLocation(eHostDeviceMemoryLocation location)
Sets the physical location of the memory region.
virtual void _updateReferences()
Update references.
void _checkFreeMemory()
Destroys the instance if no one references it.
ConstReferenceType operator[](Int64 i) const
Element at index i.
void dispose()
Frees the memory used by the array.
AbstractArray()
Constructs an empty vector with the default allocator.
Integer size() const
Number of elements in the vector.
void _initFromSpan(const Span< const T > &view)
Initializes the array with the view view.
void _move(ThatClassType &rhs) ARCCORE_NOEXCEPT
Implements the move assignment operator.
void _initFromAllocator(MemoryAllocationOptions o, Int64 acapacity, void *pre_allocated_buffer=nullptr)
Constructs an empty vector with a specific allocator a.
ArrayIterator< pointer > iterator
void _resize(Int64 s, ConstReferenceType value)
Redimensionne et remplit les nouvelles valeurs avec value.
void setMemoryLocationHint(eMemoryLocationHint new_hint)
Modifies the memory location information.
bool empty() const
Capacity (number of allocated elements) of the vector.
eHostDeviceMemoryLocation hostDeviceMemoryLocation() const
Sets the physical location of the memory region.
Int64 largeSize() const
Number of elements in the vector (in 64 bits).
bool contains(ConstReferenceType v) const
True if the array contains the value element v.
Int64 largeCapacity() const
Capacity (number of allocated elements) of the vector (in 64 bits).
Int64 largeLength() const
Number of elements in the vector (in 64 bits).
void _internalRealloc(Int64 new_capacity, bool compute_capacity, RunQueue *queue=nullptr)
Reallocates the array for a new capacity equal to new_capacity.
void _reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
void _resizeAndCopyView(Span< const T > rhs)
Redimensionne l'instance et recopie les valeurs de rhs.
virtual Integer _getNbRef()
Update references.
ArrayIterator< const_pointer > const_iterator
void _resizeNoInit(Int64 s, RunQueue *queue=nullptr)
Redimensionne sans initialiser les nouvelles valeurs.
AbstractArray(ThatClassType &&rhs) ARCCORE_NOEXCEPT
Move constructor. Should only be used by UniqueArray.
void _swap(ThatClassType &rhs) ARCCORE_NOEXCEPT
Swaps the values of the instance with those of rhs.
ConstReferenceType operator()(Int64 i) const
Element at index i.
void _reset()
Resets the array to an empty array.
Integer length() const
Number of elements in the vector.
String debugName() const
void setDebugName(const String &name)
Iterator over Arccore array classes.
bool is_not_null
Indicates if this instance is not the null instance (shared by all SharedArray).
Int64 size
Number of elements in the array (for 1D arrays).
Int64 capacity
Number of allocated elements.
Int32 nb_ref
Number of references on the instance.
bool is_allocated_by_new
Indicates if this instance was allocated by the new operator.
Constant view of an array of type T.
constexpr __host__ __device__ pointer data() const noexcept
Pointer to the start of the view.
Definition Span.h:537
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:325
View of an array of elements of type T.
Definition Span.h:633
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
eMemoryLocationHint
Indices for expected memory location.
eHostDeviceMemoryLocation
Physical location of a memory address.
std::int32_t Int32
Signed integer type of 32 bits.