Arcane  v4.1.4.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
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/* Classe de base des tableaux. */
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 Classe de base interne pour les tableaux.
32 *
33 * Cette classe gère uniquement les meta-données pour les tableaux comme
34 * le nombre d'éléments ou la capacité.
35 *
36 * \a m_md est un pointeur contenant les meta-donné du tableau. Si le
37 * tableau est partagé (SharedArray, SharedArray2), alors ce pointeur
38 * est alloué dynamiquement et dans ce cas _isUseOwnMetaData() doit
39 * retourner \a false. Si le tableau n'est pas partagé (UniqueArray ou
40 * UniqueArray2), alors les meta-données sont conservées directement
41 * dans l'instance du tableau pour éviter des allocations inutiles
42 * et \a m_md pointe alors vers \a m_meta_data. Dans tous les cas, il
43 * ne faut pas utiliser \a m_meta_data directement, mais toujours passer
44 * par \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:
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 Positionne le nom du tableau pour les informations de debug.
68 *
69 * Ce nom peut être utilisé par exemple pour les affichages listing.
70 */
71 void setDebugName(const String& name);
72 //! Nom de debug (nul si aucun nom spécifié)
73 String debugName() const;
74
75 protected:
76
77 ArrayMetaData* m_md = nullptr;
78 ArrayMetaData m_meta_data;
79
80 protected:
81
82 //! Méthode explicite pour une RunQueue nulle.
83 static constexpr RunQueue* _nullRunQueue() { return nullptr; }
84
85 /*!
86 * \brief Indique si \a m_md fait référence à \a m_meta_data.
87 *
88 * C'est le cas pour les UniqueArray et UniqueArray2 mais
89 * pas pour les SharedArray et SharedArray2.
90 */
91 virtual bool _isUseOwnMetaData() const
92 {
93 return true;
94 }
95
96 protected:
97
98 void _swapMetaData(AbstractArrayBase& rhs)
99 {
100 std::swap(m_md, rhs.m_md);
101 std::swap(m_meta_data, rhs.m_meta_data);
102 _checkSetUseOwnMetaData();
103 rhs._checkSetUseOwnMetaData();
104 }
105
106 void _copyMetaData(const AbstractArrayBase& rhs)
107 {
108 // Déplace les meta-données
109 // Attention si on utilise m_meta_data alors il
110 // faut positionner m_md pour qu'il pointe vers notre propre m_meta_data.
111 m_meta_data = rhs.m_meta_data;
112 m_md = rhs.m_md;
113 _checkSetUseOwnMetaData();
114 }
115
116 void _allocateMetaData()
117 {
118#ifdef ARCCORE_CHECK
119 if (m_md->is_not_null)
120 ArrayMetaData::throwNullExpected();
121#endif
122 if (_isUseOwnMetaData()) {
123 m_meta_data = ArrayMetaData();
124 m_md = &m_meta_data;
125 }
126 else {
127 m_md = new ArrayMetaData();
128 m_md->is_allocated_by_new = true;
129 }
130 m_md->is_not_null = true;
131 }
132
133 void _deallocateMetaData(ArrayMetaData* md)
134 {
135 if (md->is_allocated_by_new)
136 delete md;
137 else
138 *md = ArrayMetaData();
139 }
140
141 void _checkValidSharedArray()
142 {
143#ifdef ARCCORE_CHECK
144 if (m_md->is_not_null && !m_md->is_allocated_by_new)
145 ArrayMetaData::throwInvalidMetaDataForSharedArray();
146#endif
147 }
148
149 private:
150
151 void _checkSetUseOwnMetaData()
152 {
153 if (!m_md->is_allocated_by_new)
154 m_md = &m_meta_data;
155 }
156};
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160/*!
161 * \ingroup Collection
162 * \brief Classe abstraite de base d'un vecteur.
163 *
164 * Cette classe ne peut pas être utilisée directement. Pour utiliser un
165 * vecteur, choisissez la classe SharedArray ou UniqueArray.
166 */
167template <typename T>
169: public AbstractArrayBase
170{
171 public:
172
173 typedef typename ArrayTraits<T>::ConstReferenceType ConstReferenceType;
174 typedef typename ArrayTraits<T>::IsPODType IsPODType;
175 typedef AbstractArray<T> ThatClassType;
176 using TrueImpl = T;
177
178 public:
179
180 //! Type des éléments du tableau
181 typedef T value_type;
182 //! Type pointeur d'un élément du tableau
184 //! Type pointeur constant d'un élément du tableau
185 typedef const value_type* const_pointer;
186 //! Type de l'itérateur sur un élément du tableau
188 //! Type de l'itérateur constant sur un élément du tableau
190 //! Type référence d'un élément du tableau
192 //! Type référence constante d'un élément du tableau
193 typedef ConstReferenceType const_reference;
194 //! Type indexant le tableau
196 //! Type d'une distance entre itérateur éléments du tableau
197 typedef ptrdiff_t difference_type;
198
199 typedef std::reverse_iterator<iterator> reverse_iterator;
200 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
201
202 protected:
203
204 //! Construit un vecteur vide avec l'allocateur par défaut
206 {
207 }
208 //! Constructeur par déplacement. Ne doit être utilisé que par UniqueArray
209 AbstractArray(ThatClassType&& rhs) ARCCORE_NOEXCEPT
210 : m_ptr(rhs.m_ptr)
211 {
212 _copyMetaData(rhs);
213 rhs._reset();
214 }
215
216 ~AbstractArray() override
217 {
218 --m_md->nb_ref;
220 }
221
222 public:
223
224 AbstractArray(const AbstractArray<T>& rhs) = delete;
225 AbstractArray<T>& operator=(const AbstractArray<T>& rhs) = delete;
226
227 protected:
228
229 static constexpr Int64 typeSize() { return static_cast<Int64>(sizeof(T)); }
230 AllocatedMemoryInfo _currentMemoryInfo() const
231 {
232 return AllocatedMemoryInfo(m_ptr, m_md->size * typeSize(), m_md->capacity * typeSize());
233 }
234
235 protected:
236
237 /*!
238 * \brief Initialise le tableau avec la vue \a view.
239 *
240 * Cette méthode ne doit être appelée que dans un constructeur de la classe dérivée.
241 */
242 void _initFromSpan(const Span<const T>& view)
243 {
244 Int64 asize = view.size();
245 if (asize != 0) {
246 _internalAllocate(asize, _nullRunQueue());
247 _createRange(0, asize, view.data());
248 m_md->size = asize;
249 }
250 }
251
252 /*!
253 * \brief Construit un vecteur vide avec un allocateur spécifique \a a.
254 *
255 * Si \a acapacity n'est pas nul, la mémoire est allouée pour
256 * contenir \a acapacity éléments (mais le tableau reste vide).
257 *
258 * Cette méthode ne doit être appelée que dans un constructeur de la classe dérivée
259 * et uniquement par les classes utilisant une sémantique à la UniqueArray.
260 */
262 void* pre_allocated_buffer = nullptr)
263 {
264 _directFirstAllocateWithAllocator(acapacity, o, pre_allocated_buffer);
265 }
266
267 public:
268
269 //! Libère la mémoire utilisée par le tableau.
270 void dispose()
271 {
272 _destroy();
273 MemoryAllocationOptions options(m_md->allocation_options);
274 _internalDeallocate();
275 _setToSharedNull();
276 // Si on a un allocateur spécifique, il faut allouer un
277 // bloc pour conserver cette information.
278 if (options.allocator() != m_md->_allocator())
279 _directFirstAllocateWithAllocator(0, options);
281 }
282
283 public:
284
285 operator ConstArrayView<T>() const
286 {
287 return ConstArrayView<T>(ARCCORE_CAST_SMALL_SIZE(size()), m_ptr);
288 }
289 operator Span<const T>() const
290 {
291 return Span<const T>(m_ptr, m_md->size);
292 }
293 operator SmallSpan<const T>() const
294 {
295 return SmallSpan<const T>(m_ptr, ARCCORE_CAST_SMALL_SIZE(size()));
296 }
297
298 public:
299
300 //! Nombre d'éléments du vecteur
301 Integer size() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
302 //! Nombre d'éléments du vecteur
303 Integer length() const { return ARCCORE_CAST_SMALL_SIZE(m_md->size); }
304 //! Capacité (nombre d'éléments alloués) du vecteur
305 Integer capacity() const { return ARCCORE_CAST_SMALL_SIZE(m_md->capacity); }
306 //! Nombre d'éléments du vecteur (en 64 bits)
307 Int64 largeSize() const { return m_md->size; }
308 //! Nombre d'éléments du vecteur (en 64 bits)
309 Int64 largeLength() const { return m_md->size; }
310 //! Capacité (nombre d'éléments alloués) du vecteur (en 64 bits)
311 Int64 largeCapacity() const { return m_md->capacity; }
312 //! Capacité (nombre d'éléments alloués) du vecteur
313 bool empty() const { return m_md->size == 0; }
314 //! Vrai si le tableau contient l'élément de valeur \a v
315 bool contains(ConstReferenceType v) const
316 {
317 const T* ptr = m_ptr;
318 for (Int64 i = 0, n = m_md->size; i < n; ++i) {
319 if (ptr[i] == v)
320 return true;
321 }
322 return false;
323 }
324
325 public:
326
327 //! Elément d'indice \a i
328 ConstReferenceType operator[](Int64 i) const
329 {
330 ARCCORE_CHECK_AT(i, m_md->size);
331 return m_ptr[i];
332 }
333 //! Elément d'indice \a i
334 ConstReferenceType operator()(Int64 i) const
335 {
336 ARCCORE_CHECK_AT(i, m_md->size);
337 return m_ptr[i];
338 }
339
340 public:
341
342 //! Modifie les informations sur la localisation mémoire
344 {
345 m_md->_setMemoryLocationHint(new_hint, m_ptr, sizeof(T));
346 }
347
348 /*!
349 * \brief Positionne l'emplacement physique de la zone mémoire.
350 *
351 * \warning L'appelant doit garantir la cohérence entre l'allocateur
352 * et la zone mémoire spécifiée.
353 */
355 {
356 m_md->_setHostDeviceMemoryLocation(location);
357 }
358
359 //! Positionne l'emplacement physique de la zone mémoire.
361 {
362 return m_md->allocation_options.hostDeviceMemoryLocation();
363 }
364
365 public:
366
367 friend bool operator==(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
368 {
369 return operator==(Span<const T>(rhs), Span<const T>(lhs));
370 }
371
372 friend bool operator!=(const AbstractArray<T>& rhs, const AbstractArray<T>& lhs)
373 {
374 return !(rhs == lhs);
375 }
376
377 friend bool operator==(const AbstractArray<T>& rhs, const Span<const T>& lhs)
378 {
379 return operator==(Span<const T>(rhs), lhs);
380 }
381
382 friend bool operator!=(const AbstractArray<T>& rhs, const Span<const T>& lhs)
383 {
384 return !(rhs == lhs);
385 }
386
387 friend bool operator==(const Span<const T>& rhs, const AbstractArray<T>& lhs)
388 {
389 return operator==(rhs, Span<const T>(lhs));
390 }
391
392 friend bool operator!=(const Span<const T>& rhs, const AbstractArray<T>& lhs)
393 {
394 return !(rhs == lhs);
395 }
396
397 friend std::ostream& operator<<(std::ostream& o, const AbstractArray<T>& val)
398 {
399 o << Span<const T>(val);
400 return o;
401 }
402
403 private:
404
405 using AbstractArrayBase::m_meta_data;
406
407 protected:
408
409 // NOTE: Ces deux champs sont utilisés pour l'affichage TTF de totalview.
410 // Si on modifie leur ordre il faut mettre à jour la partie correspondante
411 // dans l'afficheur totalview de Arcane.
412 T* m_ptr = nullptr;
413
414 protected:
415
416 //! Réserve le mémoire pour \a new_capacity éléments
417 void _reserve(Int64 new_capacity)
418 {
419 if (new_capacity <= m_md->capacity)
420 return;
421 _internalRealloc(new_capacity, false);
422 }
423 /*!
424 * \brief Réalloue le tableau pour une nouvelle capacité égale à \a new_capacity.
425 *
426 * Si la nouvelle capacité est inférieure à l'ancienne, rien ne se passe.
427 */
428 template <typename PodType>
429 void _internalRealloc(Int64 new_capacity, bool compute_capacity, PodType pod_type, RunQueue* queue = nullptr)
430 {
431 if (_isSharedNull()) {
432 if (new_capacity != 0)
433 _internalAllocate(new_capacity, queue);
434 return;
435 }
436
437 Int64 acapacity = new_capacity;
438 if (compute_capacity) {
439 acapacity = m_md->capacity;
440 //std::cout << " REALLOC: want=" << wanted_size << " current_capacity=" << capacity << '\n';
441 while (new_capacity > acapacity)
442 acapacity = (acapacity == 0) ? 4 : (acapacity + 1 + acapacity / 2);
443 //std::cout << " REALLOC: want=" << wanted_size << " new_capacity=" << capacity << '\n';
444 }
445 // Si la nouvelle capacité est inférieure à la courante,ne fait rien.
446 if (acapacity <= m_md->capacity)
447 return;
448 _internalReallocate(acapacity, pod_type, queue);
449 }
450
451 void _internalRealloc(Int64 new_capacity, bool compute_capacity)
452 {
453 _internalRealloc(new_capacity, compute_capacity, IsPODType());
454 }
455
456 //! Réallocation pour un type POD
457 void _internalReallocate(Int64 new_capacity, TrueType, RunQueue* queue)
458 {
459 T* old_ptr = m_ptr;
460 Int64 old_capacity = m_md->capacity;
461 _directReAllocate(new_capacity, queue);
462 bool update = (new_capacity < old_capacity) || (m_ptr != old_ptr);
463 if (update) {
465 }
466 }
467
468 //! Réallocation pour un type complexe (non POD)
469 void _internalReallocate(Int64 new_capacity, FalseType, RunQueue* queue)
470 {
471 T* old_ptr = m_ptr;
472 ArrayMetaData* old_md = m_md;
473 AllocatedMemoryInfo old_mem_info = _currentMemoryInfo();
474 Int64 old_size = m_md->size;
475 _directAllocate(new_capacity, queue);
476 if (m_ptr != old_ptr) {
477 for (Int64 i = 0; i < old_size; ++i) {
478 new (m_ptr + i) T(old_ptr[i]);
479 old_ptr[i].~T();
480 }
481 m_md->nb_ref = old_md->nb_ref;
482 m_md->_deallocate(old_mem_info, queue);
484 }
485 }
486 // Libère la mémoire
487 void _internalDeallocate(RunQueue* queue = nullptr)
488 {
489 if (!_isSharedNull())
490 m_md->_deallocate(_currentMemoryInfo(), queue);
491 if (m_md->is_not_null)
492 _deallocateMetaData(m_md);
493 }
494 void _internalAllocate(Int64 new_capacity, RunQueue* queue)
495 {
496 _directAllocate(new_capacity, queue);
497 m_md->nb_ref = _getNbRef();
499 }
500
501 void _copyFromMemory(const T* source)
502 {
503 m_md->_copyFromMemory(m_ptr, source, sizeof(T), _nullRunQueue());
504 }
505
506 private:
507
508 /*!
509 * \brief Effectue la première allocation.
510 *
511 * Si \a pre_allocated_buffer est non nul, on l'utilise comme buffer
512 * pour la première allocation. C'est à l'appelant de s'assurer que
513 * ce buffer est valide pour la capacité demandée. Le \a pre_allocated_buffer
514 * est utilisé notamment par l'allocateur de SmallArray.
515 */
516 void _directFirstAllocateWithAllocator(Int64 new_capacity, MemoryAllocationOptions options,
517 void* pre_allocated_buffer = nullptr)
518 {
519 IMemoryAllocator* wanted_allocator = options.allocator();
520 if (!wanted_allocator) {
521 wanted_allocator = ArrayMetaData::_defaultAllocator();
522 options.setAllocator(wanted_allocator);
523 }
524 _allocateMetaData();
525 m_md->allocation_options = options;
526 if (new_capacity > 0) {
527 if (!pre_allocated_buffer)
528 _allocateMP(new_capacity, options.runQueue());
529 else
530 _setMPCast(pre_allocated_buffer);
531 }
532 m_md->nb_ref = _getNbRef();
533 m_md->size = 0;
535 }
536
537 void _directAllocate(Int64 new_capacity, RunQueue* queue)
538 {
539 if (!m_md->is_not_null)
540 _allocateMetaData();
541 _allocateMP(new_capacity, queue);
542 }
543
544 void _allocateMP(Int64 new_capacity, RunQueue* queue)
545 {
546 _setMPCast(m_md->_allocate(new_capacity, typeSize(), queue));
547 }
548
549 void _directReAllocate(Int64 new_capacity, RunQueue* queue)
550 {
551 _setMPCast(m_md->_reallocate(_currentMemoryInfo(), new_capacity, typeSize(), queue));
552 }
553
554 public:
555
556 void changeAllocator(const MemoryAllocationOptions& options, RunQueue* queue)
557 {
558 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), queue));
560 }
561
562 void changeAllocator(const MemoryAllocationOptions& options)
563 {
564 _setMPCast(m_md->_changeAllocator(options, _currentMemoryInfo(), typeSize(), _nullRunQueue()));
566 }
567
568 public:
569
570 void printInfos(std::ostream& o)
571 {
572 o << " Infos: size=" << m_md->size << " capacity=" << m_md->capacity << '\n';
573 }
574
575 protected:
576
577 //! Mise à jour des références
578 virtual void _updateReferences()
579 {
580 }
581 //! Mise à jour des références
583 {
584 return 1;
585 }
586 //! Ajoute \a n élément de valeur \a val à la fin du tableau
587 void _addRange(ConstReferenceType val, Int64 n)
588 {
589 Int64 s = m_md->size;
590 if ((s + n) > m_md->capacity)
591 _internalRealloc(s + n, true);
592 for (Int64 i = 0; i < n; ++i)
593 new (m_ptr + s + i) T(val);
594 m_md->size += n;
595 }
596
597 //! Ajoute \a n élément de valeur \a val à la fin du tableau
599 {
600 Int64 n = val.size();
601 const T* ptr = val.data();
602 Int64 s = m_md->size;
603 if ((s + n) > m_md->capacity)
604 _internalRealloc(s + n, true);
605 _createRange(s, s + n, ptr);
606 m_md->size += n;
607 }
608
609 //! Détruit l'instance si plus personne ne la référence
611 {
612 if (m_md->nb_ref == 0) {
613 _destroy();
614 _internalDeallocate(_nullRunQueue());
615 }
616 }
617 void _destroy()
618 {
619 _destroyRange(0, m_md->size, IsPODType());
620 }
621 void _destroyRange(Int64, Int64, TrueType)
622 {
623 // Rien à faire pour un type POD.
624 }
625 void _destroyRange(Int64 abegin, Int64 aend, FalseType)
626 {
627 if (abegin < 0)
628 abegin = 0;
629 for (Int64 i = abegin; i < aend; ++i)
630 m_ptr[i].~T();
631 }
632 void _createRangeDefault(Int64, Int64, TrueType)
633 {
634 }
635 void _createRangeDefault(Int64 abegin, Int64 aend, FalseType)
636 {
637 if (abegin < 0)
638 abegin = 0;
639 for (Int64 i = abegin; i < aend; ++i)
640 new (m_ptr + i) T();
641 }
642 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, TrueType)
643 {
644 if (abegin < 0)
645 abegin = 0;
646 for (Int64 i = abegin; i < aend; ++i)
647 m_ptr[i] = value;
648 }
649 void _createRange(Int64 abegin, Int64 aend, ConstReferenceType value, FalseType)
650 {
651 if (abegin < 0)
652 abegin = 0;
653 for (Int64 i = abegin; i < aend; ++i)
654 new (m_ptr + i) T(value);
655 }
656 void _createRange(Int64 abegin, Int64 aend, const T* values)
657 {
658 if (abegin < 0)
659 abegin = 0;
660 for (Int64 i = abegin; i < aend; ++i) {
661 new (m_ptr + i) T(*values);
662 ++values;
663 }
664 }
665 void _fill(ConstReferenceType value)
666 {
667 for (Int64 i = 0, n = size(); i < n; ++i)
668 m_ptr[i] = value;
669 }
670 void _clone(const ThatClassType& orig_array)
671 {
672 Int64 that_size = orig_array.size();
673 _internalAllocate(that_size, _nullRunQueue());
674 m_md->size = that_size;
675 m_md->dim1_size = orig_array.m_md->dim1_size;
676 m_md->dim2_size = orig_array.m_md->dim2_size;
677 _createRange(0, that_size, orig_array.m_ptr);
678 }
679 template <typename PodType>
680 void _resizeHelper(Int64 s, PodType pod_type, RunQueue* queue)
681 {
682 if (s < 0)
683 s = 0;
684 if (s > m_md->size) {
685 this->_internalRealloc(s, false, pod_type, queue);
686 this->_createRangeDefault(m_md->size, s, pod_type);
687 }
688 else {
689 this->_destroyRange(s, m_md->size, pod_type);
690 }
691 m_md->size = s;
692 }
693 void _resize(Int64 s)
694 {
695 _resizeHelper(s, IsPODType(), _nullRunQueue());
696 }
697 //! Redimensionne sans initialiser les nouvelles valeurs
698 void _resizeNoInit(Int64 s, RunQueue* queue = nullptr)
699 {
700 _resizeHelper(s, TrueType{}, queue);
701 }
702 void _clear()
703 {
704 this->_destroyRange(0, m_md->size, IsPODType());
705 m_md->size = 0;
706 }
707 //! Redimensionne et remplit les nouvelles valeurs avec \a value
708 void _resize(Int64 s, ConstReferenceType value)
709 {
710 if (s < 0)
711 s = 0;
712 if (s > m_md->size) {
713 this->_internalRealloc(s, false);
714 this->_createRange(m_md->size, s, value, IsPODType());
715 }
716 else {
717 this->_destroyRange(s, m_md->size, IsPODType());
718 }
719 m_md->size = s;
720 }
721 void _copy(const T* rhs_begin, TrueType)
722 {
723 _copyFromMemory(rhs_begin);
724 }
725 void _copy(const T* rhs_begin, FalseType)
726 {
727 for (Int64 i = 0, n = m_md->size; i < n; ++i)
728 m_ptr[i] = rhs_begin[i];
729 }
730 void _copy(const T* rhs_begin)
731 {
732 _copy(rhs_begin, IsPODType());
733 }
734
735 /*!
736 * \brief Redimensionne l'instance et recopie les valeurs de \a rhs.
737 *
738 * Si la taille diminue, les éléments compris entre size() et rhs.size()
739 * sont détruits.
740 *
741 * \post size()==rhs.size()
742 */
744 {
745 const T* rhs_begin = rhs.data();
746 Int64 rhs_size = rhs.size();
747 const Int64 current_size = m_md->size;
748 T* abegin = m_ptr;
749 // Vérifie que \a rhs n'est pas un élément à l'intérieur de ce tableau
750 if (abegin >= rhs_begin && abegin < (rhs_begin + rhs_size))
751 ArrayMetaData::overlapError(abegin, m_md->size, rhs_begin, rhs_size);
752
753 if (rhs_size > current_size) {
754 this->_internalRealloc(rhs_size, false);
755 // Crée les nouveaux éléments
756 this->_createRange(m_md->size, rhs_size, rhs_begin + current_size);
757 // Copie les éléments déjà existant
758 _copy(rhs_begin);
759 m_md->size = rhs_size;
760 }
761 else {
762 this->_destroyRange(rhs_size, current_size, IsPODType{});
763 m_md->size = rhs_size;
764 _copy(rhs_begin);
765 }
766 }
767
768 /*!
769 * \brief Implémente l'opérateur d'assignement par déplacement.
770 *
771 * Cet appel n'est valide que pour les tableaux de type UniqueArray
772 * qui n'ont qu'une seule référence. Les infos de \a rhs sont directement
773 * copiés cette l'instance. En retour, \a rhs contient le tableau vide.
774 */
775 void _move(ThatClassType& rhs) ARCCORE_NOEXCEPT
776 {
777 if (&rhs == this)
778 return;
779
780 // Comme il n'y a qu'une seule référence sur le tableau actuel, on peut
781 // directement libérer la mémoire.
782 _destroy();
783 _internalDeallocate(_nullRunQueue());
784
785 _setMP(rhs.m_ptr);
786
787 _copyMetaData(rhs);
788
789 // Indique que \a rhs est vide.
790 rhs._reset();
791 }
792 /*!
793 * \brief Échange les valeurs de l'instance avec celles de \a rhs.
794 *
795 * Cet appel n'est valide que pour les tableaux de type UniqueArray
796 * et l'échange se fait uniquement par l'échange des pointeurs. L'opération
797 * est donc de complexité constante.
798 */
799 void _swap(ThatClassType& rhs) ARCCORE_NOEXCEPT
800 {
801 std::swap(m_ptr, rhs.m_ptr);
802 _swapMetaData(rhs);
803 }
804
805 void _shrink()
806 {
807 _shrink(size());
808 }
809
810 // Réalloue la mémoire pour avoir une capacité proche de \a new_capacity
811 void _shrink(Int64 new_capacity)
812 {
813 if (_isSharedNull())
814 return;
815 // On n'augmente pas la capacité avec cette méthode
816 if (new_capacity > this->capacity())
817 return;
818 if (new_capacity < 4)
819 new_capacity = 4;
820 _internalReallocate(new_capacity, IsPODType(), _nullRunQueue());
821 }
822
823 /*!
824 * \brief Réinitialise le tableau à un tableau vide.
825 * \warning Cette méthode n'est valide que pour les UniqueArray et pas
826 * les SharedArray.
827 */
828 void _reset()
829 {
830 _setToSharedNull();
831 }
832
833 constexpr Integer _clampSizeOffet(Int64 offset, Int32 asize) const
834 {
835 Int64 max_size = m_md->size - offset;
836 if (asize > max_size)
837 // On est certain de ne pas dépasser 32 bits car on est inférieur à asize.
838 asize = static_cast<Integer>(max_size);
839 return asize;
840 }
841
842 // Uniquement pour UniqueArray et UniqueArray2
843 void _assignFromArray(const AbstractArray<T>& rhs)
844 {
845 if (&rhs == this)
846 return;
847 Span<const T> rhs_span(rhs);
848 if (rhs.allocator() == this->allocator()) {
849 _resizeAndCopyView(rhs_span);
850 }
851 else {
852 _destroy();
853 _internalDeallocate(_nullRunQueue());
854 _reset();
855 _initFromAllocator(rhs.allocationOptions(), 0);
856 _initFromSpan(rhs_span);
857 }
858 }
859
860 protected:
861
862 void _setMP(TrueImpl* new_mp)
863 {
864 m_ptr = new_mp;
865 }
866
867 void _setMP2(TrueImpl* new_mp, ArrayMetaData* new_md)
868 {
869 _setMP(new_mp);
870 // Il ne faut garder le nouveau m_md que s'il est alloué
871 // sinon on risque d'avoir des références sur des objets temporaires
872 m_md = new_md;
873 if (!m_md->is_allocated_by_new)
874 m_md = &m_meta_data;
875 }
876
877 bool _isSharedNull()
878 {
879 return m_ptr == nullptr;
880 }
881
882 private:
883
884 void _setToSharedNull()
885 {
886 m_ptr = nullptr;
887 m_meta_data = ArrayMetaData();
888 m_md = &m_meta_data;
889 }
890 void _setMPCast(void* p)
891 {
892 _setMP(reinterpret_cast<TrueImpl*>(p));
893 }
894};
895
896/*---------------------------------------------------------------------------*/
897/*---------------------------------------------------------------------------*/
898
899} // namespace Arcane
900
901/*---------------------------------------------------------------------------*/
902/*---------------------------------------------------------------------------*/
903
904#endif
Types et fonctions associés aux classes SpanImpl, SmallSpan and Span.
Classe de base interne pour les tableaux.
static constexpr RunQueue * _nullRunQueue()
Méthode explicite pour une RunQueue nulle.
virtual bool _isUseOwnMetaData() const
Indique si m_md fait référence à m_meta_data.
Classe abstraite de base d'un vecteur.
void _addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
Integer capacity() const
Capacité (nombre d'éléments alloués) du vecteur.
void _addRange(Span< const T > val)
Ajoute n élément de valeur val à la fin du tableau.
void _internalSetHostDeviceMemoryLocation(eHostDeviceMemoryLocation location)
Positionne l'emplacement physique de la zone mémoire.
virtual void _updateReferences()
Mise à jour des références.
void _checkFreeMemory()
Détruit l'instance si plus personne ne la référence.
ConstReferenceType operator[](Int64 i) const
Elément d'indice i.
void dispose()
Libère la mémoire utilisée par le tableau.
AbstractArray()
Construit un vecteur vide avec l'allocateur par défaut.
Integer size() const
Nombre d'éléments du vecteur.
void _initFromSpan(const Span< const T > &view)
Initialise le tableau avec la vue view.
void _move(ThatClassType &rhs) ARCCORE_NOEXCEPT
Implémente l'opérateur d'assignement par déplacement.
void _initFromAllocator(MemoryAllocationOptions o, Int64 acapacity, void *pre_allocated_buffer=nullptr)
Construit un vecteur vide avec un allocateur spécifique a.
ArrayIterator< pointer > iterator
void _resize(Int64 s, ConstReferenceType value)
Redimensionne et remplit les nouvelles valeurs avec value.
void setMemoryLocationHint(eMemoryLocationHint new_hint)
Modifie les informations sur la localisation mémoire.
void _internalReallocate(Int64 new_capacity, FalseType, RunQueue *queue)
Réallocation pour un type complexe (non POD)
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
eHostDeviceMemoryLocation hostDeviceMemoryLocation() const
Positionne l'emplacement physique de la zone mémoire.
Int64 largeSize() const
Nombre d'éléments du vecteur (en 64 bits)
bool contains(ConstReferenceType v) const
Vrai si le tableau contient l'élément de valeur v.
Int64 largeCapacity() const
Capacité (nombre d'éléments alloués) du vecteur (en 64 bits)
Int64 largeLength() const
Nombre d'éléments du vecteur (en 64 bits)
void _reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void _resizeAndCopyView(Span< const T > rhs)
Redimensionne l'instance et recopie les valeurs de rhs.
virtual Integer _getNbRef()
Mise à jour des références.
ArrayIterator< const_pointer > const_iterator
void _resizeNoInit(Int64 s, RunQueue *queue=nullptr)
Redimensionne sans initialiser les nouvelles valeurs.
AbstractArray(ThatClassType &&rhs) ARCCORE_NOEXCEPT
Constructeur par déplacement. Ne doit être utilisé que par UniqueArray.
void _internalRealloc(Int64 new_capacity, bool compute_capacity, PodType pod_type, RunQueue *queue=nullptr)
Réalloue le tableau pour une nouvelle capacité égale à new_capacity.
void _swap(ThatClassType &rhs) ARCCORE_NOEXCEPT
Échange les valeurs de l'instance avec celles de rhs.
ConstReferenceType operator()(Int64 i) const
Elément d'indice i.
void _reset()
Réinitialise le tableau à un tableau vide.
void _internalReallocate(Int64 new_capacity, TrueType, RunQueue *queue)
Réallocation pour un type POD.
Integer length() const
Nombre d'éléments du vecteur.
Informations sur une zone mémoire allouée.
String debugName() const
void setDebugName(const String &name)
Itérateur sur les classes tableau de Arccore.
bool is_not_null
Indique si cette instance n'est pas l'instance nulle (partagée par tous les SharedArray)
Int64 size
Nombre d'éléments du tableau (pour les tableaux 1D)
Int32 nb_ref
Nombre de références sur l'instance.
bool is_allocated_by_new
Indique is cette instance a été allouée par l'opérateur new.
Vue constante d'un tableau de type T.
Interface d'un allocateur pour la mémoire.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
Definition Span.h:537
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
eMemoryLocationHint
Indices sur la localisation mémoire attendue.
eHostDeviceMemoryLocation
Localisation physique d'une adresse mémoire.
std::int32_t Int32
Type entier signé sur 32 bits.